diff --git a/gi/src/graphics/colormap/linear.rs b/gi/src/graphics/colormap/linear.rs index 3cd87cd..1caaa9b 100644 --- a/gi/src/graphics/colormap/linear.rs +++ b/gi/src/graphics/colormap/linear.rs @@ -34,7 +34,8 @@ impl LinearColormap { } } - pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) { + pub fn set_colors>>(&mut self, colors: T) { + let colors = colors.into(); if colors != self.colors { self.colors = colors; self.color_changed = true; @@ -49,7 +50,7 @@ impl LinearColormap { impl ColorMap for LinearColormap { fn attach_with_program( - &mut self, + &self, gl: &glow::Context, program: &crate::components::Program, ) -> crate::errors::Result<()> { @@ -80,38 +81,27 @@ impl ColorMap for LinearColormap { glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32, ); - - let location = program.get_uniform_location(gl, "colormap_conf"); - gl.uniform_4_f32( - location.as_ref(), - self.min, - self.max, - self.colors.len() as f32, - self.unvalid, - ); - self.texture = Some(texture); + // self.texture = Some(texture); } + let location = program.get_uniform_location(gl, "colormap_conf"); + gl.uniform_4_f32( + location.as_ref(), + self.min, + self.max, + self.colors.len() as f32, + self.unvalid, + ); } #[cfg(not(target_os = "macos"))] unsafe { let texture = gl.create_named_texture(glow::TEXTURE_1D).unwrap(); - gl.texture_parameter_i32( - texture, - glow::TEXTURE_MIN_FILTER, - glow::NEAREST as i32, - ); - gl.texture_parameter_i32( - texture, - glow::TEXTURE_MAG_FILTER, - glow::NEAREST as i32, - ); + gl.texture_parameter_i32(texture, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32); + gl.texture_parameter_i32(texture, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32); // gl.tex_storage_1d(texture, 0, glow::RGBA, self.colors.len() as i32) todo!("implement this"); - - } Ok(()) diff --git a/gi/src/graphics/colormap/mod.rs b/gi/src/graphics/colormap/mod.rs index 7b288ea..2d522f0 100644 --- a/gi/src/graphics/colormap/mod.rs +++ b/gi/src/graphics/colormap/mod.rs @@ -4,7 +4,7 @@ pub mod linear; pub trait ColorMap { fn attach_with_program( - &mut self, + &self, gl: &glow::Context, program: &crate::components::Program, ) -> crate::errors::Result<()>; diff --git a/gi/src/graphics/mod.rs b/gi/src/graphics/mod.rs index 4e11162..fe4fae6 100644 --- a/gi/src/graphics/mod.rs +++ b/gi/src/graphics/mod.rs @@ -157,6 +157,7 @@ macro_rules! config_for_everyitem { pub trait AttachWithIO { type State: CameraOP; + type Status; fn attach_with_mouse( &mut self, state: &Self::State, @@ -168,6 +169,8 @@ pub trait AttachWithIO { fn reset(&mut self); fn init_camera(&self) -> Camera; + + fn status(&self) -> Self::Status; } #[derive(Debug, Clone)] diff --git a/gi/src/graphics/planet/terrain.rs b/gi/src/graphics/planet/terrain.rs index 5577411..4ef29b3 100644 --- a/gi/src/graphics/planet/terrain.rs +++ b/gi/src/graphics/planet/terrain.rs @@ -3,6 +3,8 @@ use glow::HasContext; use crate::components::Program; use crate::errors::Result; use crate::graphics::collections::agg_fast_path::Path; +use crate::graphics::colormap::linear::LinearColormap; +use crate::graphics::colormap::ColorMap; use crate::graphics::{AttaWithBuffer, Graphics}; use crate::pg::Attach; use crate::resources::RcGlRcResource; @@ -14,6 +16,7 @@ pub struct Terrain { program: Program, // Buffers attach: Attach, + color_mapping: LinearColormap, } impl Terrain { @@ -26,19 +29,29 @@ impl Terrain { let default_attach = config.create_attach(gl); let program = Program::new(vertex, fragment, None, "330 core"); + let mut color_mapping = LinearColormap::new()?; + + color_mapping.set_colors([ + [0, 77, 204, 0], + [194, 179, 128, 13], + [51, 204, 51, 77], + [51, 51, 51, 153], + [255, 255, 255, 255], + ]); + + color_mapping.set_range(0.0, 1.0); + Ok(Self { program, attach: default_attach, + color_mapping, }) } fn set_conf(&mut self, gl: &glow::Context, config: &TerrainConfig) -> Result<()> { unsafe { - let sun_loc = self.program.get_uniform_location(gl, "sun_location"); - gl.uniform_3_f32_slice(sun_loc.as_ref(), &config.sun_location); - - let er = self.program.get_uniform_location(gl, "ER"); - gl.uniform_1_f32(er.as_ref(), config.earth_radius); + let er = self.program.get_uniform_location(gl, "earth"); + gl.uniform_3_f32(er.as_ref(), config.earth_radius, config.theta, config.phi); let ts = self.program.get_uniform_location(gl, "terrain_scale"); gl.uniform_1_f32(ts.as_ref(), config.terrain_scale); @@ -49,6 +62,13 @@ impl Terrain { gl.active_texture(glow::TEXTURE0); gl.bind_texture(glow::TEXTURE_2D, Some(texture.native())); } + + let tex_range = self.program.get_uniform_location(gl, "tex_range"); + + gl.uniform_4_f32_slice(tex_range.as_ref(), config.tex_range.as_slice()); + + let max_height = self.program.get_uniform_location(gl, "maxHeight"); + gl.uniform_1_f32(max_height.as_ref(), config.max_height); } Ok(()) } @@ -58,6 +78,8 @@ pub struct TerrainConfig { pub earth_radius: f32, pub sun_location: [f32; 3], pub terrain_scale: f32, + pub theta: f32, + pub phi: f32, max_height: f32, tex_range: [f32; 4], terrain_texture: Option>, @@ -100,11 +122,13 @@ impl TerrainConfig { impl Default for TerrainConfig { fn default() -> Self { Self { - earth_radius: 3.0, + earth_radius: 300.0, sun_location: [10.0, 0.0, 0.0], terrain_scale: 1.0, - tex_range: [0.0, 0.0, 0.0, 0.0], - max_height: 1.0, + tex_range: [0.0, 90.0, 60.0, 90.0], + max_height: 10.0, + phi: 0.0, + theta: 0.0, terrain_texture: None, } } @@ -118,24 +142,51 @@ impl TerrainConfig { ) -> crate::errors::Result<()> { let img = image::open(path).unwrap(); let img = img.flipv(); - let img = img.to_rgba8(); + let img = img.to_luma8(); let (width, height) = img.dimensions(); let data = img.into_raw(); let texture = unsafe { let texture = gl.create_texture().unwrap(); gl.bind_texture(glow::TEXTURE_2D, Some(texture)); + gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1); + + gl.tex_parameter_f32(glow::TEXTURE_2D, glow::TEXTURE_BORDER_COLOR, 0.0); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::CLAMP_TO_BORDER as i32, + ); + + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::CLAMP_TO_BORDER as i32, + ); + + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR as i32, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::LINEAR as i32, + ); + gl.tex_image_2d( glow::TEXTURE_2D, 0, - glow::RGBA as i32, + glow::R8 as i32, width as i32, height as i32, 0, - glow::RGBA, + glow::RED, glow::UNSIGNED_BYTE, Some(&data), ); + gl.generate_mipmap(glow::TEXTURE_2D); texture }; @@ -145,6 +196,10 @@ impl TerrainConfig { Ok(()) } + + pub fn get_alt_texture(&self) -> Option<&RcGlRcResource> { + self.terrain_texture.as_ref() + } } impl Graphics for Terrain { @@ -161,6 +216,8 @@ impl Graphics for Terrain { } fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> { + self.color_mapping.attach_with_program(gl, &self.program); + self.color_mapping.bind_texture(gl, &self.program); self.attach.bind_self(gl, &self.program); unsafe { gl.draw_elements(glow::TRIANGLES, self.attach.len, glow::UNSIGNED_INT, 0); diff --git a/gi/src/graphics/threed.rs b/gi/src/graphics/threed.rs index f8e7c5c..c1063dd 100644 --- a/gi/src/graphics/threed.rs +++ b/gi/src/graphics/threed.rs @@ -42,6 +42,8 @@ impl AttaWithProgram for Trackball { impl AttachWithIO for Trackball { type State = super::MouseState; + type Status = (); + fn attach_with_mouse( &mut self, state: &Self::State, @@ -74,4 +76,8 @@ impl AttachWithIO for Trackball { Vec3::new(0.0, 0.0, 0.0), ) } + + fn status(&self) -> Self::Status { + () + } } diff --git a/gi/src/graphics/transforms/plane.rs b/gi/src/graphics/transforms/plane.rs index 069f86e..078823d 100644 --- a/gi/src/graphics/transforms/plane.rs +++ b/gi/src/graphics/transforms/plane.rs @@ -47,6 +47,7 @@ impl PlaneTrans { impl AttachWithIO for PlaneTrans { type State = MouseKeyboardState; + type Status = (); fn attach_with_mouse( &mut self, @@ -104,6 +105,10 @@ impl AttachWithIO for PlaneTrans { } fn reset(&mut self) {} + + fn status(&self) -> Self::Status { + () + } } impl AttaWithProgram for PlaneTrans { diff --git a/gi/src/graphics/transforms/trackball.rs b/gi/src/graphics/transforms/trackball.rs index 05e8584..73cac43 100644 --- a/gi/src/graphics/transforms/trackball.rs +++ b/gi/src/graphics/transforms/trackball.rs @@ -1,9 +1,13 @@ -use crate::components::Program; +use crate::camera::Camera; use crate::errors::Result; -use crate::graphics::AttaWithProgram; +use crate::graphics::{AttaWithProgram, MouseKeyboardState, MouseState}; +use crate::pg::layout_type::ViewPort; +use crate::ui::operation::Projection; +use crate::{components::Program, graphics::AttachWithIO}; use glow::HasContext; use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3}; +use nalgebra_glm::Vec3; #[derive(Debug, Clone)] pub struct TrackballModel { @@ -18,6 +22,12 @@ pub struct TrackballModel { phi: f32, } +impl Default for TrackballModel { + fn default() -> Self { + Self::new(0.0, 0.0, 200.0) + } +} + impl TrackballModel { pub fn new(phi: f32, theta: f32, range: f32) -> Self { let mut trackball = Self { @@ -55,6 +65,8 @@ impl TrackballModel { self.count = 0; } self.model = self.rotation.to_homogeneous(); + self.theta = self.get_orientation().0; + self.phi = self.get_orientation().1; } fn model(&self) -> &Matrix4 { @@ -138,21 +150,38 @@ impl TrackballModel { } } -// impl Trackball { -// pub fn new() -> Result { -// let model = TrackballModel::new(0.0, 0.0); +impl AttachWithIO for TrackballModel { + type State = MouseKeyboardState; + type Status = (f32, f32); -// Ok(Self { model }) -// } + fn attach_with_mouse( + &mut self, + state: &Self::State, + camera: &mut Camera, + projection: &mut Projection, + viewport: &ViewPort, + ) -> bool { + match state.mouse_state { + MouseState::Drag { from, delta } => { + self.drag_to(from[0], from[1], delta[0], delta[1]); + true + } + _ => false, + } + } -// pub fn on_mouse_drag(&mut self, x: f32, y: f32, dx: f32, dy: f32) { -// self.model.drag_to(x, y, dx, dy); -// } + fn reset(&mut self) {} -// pub fn model(&self) -> &Matrix4 { -// self.model.model() -// } -// } + fn init_camera(&self) -> Camera { + let mut camera = Camera::default(); + camera.set_position(Vec3::new(0.0, 0.0, 1100.0)); + camera + } + + fn status(&self) -> Self::Status { + (self.theta, self.phi) + } +} impl AttaWithProgram for TrackballModel { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { diff --git a/gi/src/pg/app.rs b/gi/src/pg/app.rs index 1cb17f0..8b1340e 100644 --- a/gi/src/pg/app.rs +++ b/gi/src/pg/app.rs @@ -10,7 +10,7 @@ use crate::{ }, ui::{ helper::{self, Helper}, - operation::Operation, + operation::{Operation, Operations}, }, utils::resources::{ ManagedResource, RcGlBuffer, RcGlFramebuffer, RcGlRcFramebuffer, RcGlRcRenderbuffer, @@ -51,14 +51,14 @@ impl App { Ok(()) } - pub fn set_init_modules(&mut self, modules: ModulePackage) { - self.init_modules = Some(modules); + pub fn set_init_modules>(&mut self, modules: T) { + self.init_modules = Some(modules.into()); } pub fn render<'a>( &'a mut self, modules: &mut Vec>>, - operation: &Operation, + operation: &Operations, viewport: &ViewPort, ) { if let Some(module) = self.init_modules.as_mut() { diff --git a/gi/src/pg/mod.rs b/gi/src/pg/mod.rs index f71bfc9..811a0a5 100644 --- a/gi/src/pg/mod.rs +++ b/gi/src/pg/mod.rs @@ -33,7 +33,10 @@ use crate::{ transforms::plane::PlaneTrans, AttaWithProgram, AttachWithIO, Graphics, }, - ui::{operation::Operation, typ::LayoutAttach}, + ui::{ + operation::{Operation, Operations}, + typ::LayoutAttach, + }, utils::resources::GL, }; @@ -259,13 +262,13 @@ macro_rules! impl_module_package { pub fn draw_modules( &mut self, modules: &mut ModulePackage, - operation: &Operation, + operation: &Operations, viewport: &ViewPort, ) -> Result<()> { match &mut modules.modules { $( _ModulePackage::$b(m) => { - self.$method().render(m, operation, viewport)?; + self.$method().render(m, operation.into(), viewport)?; } )+ } diff --git a/gi/src/pg/modules/earth.rs b/gi/src/pg/modules/earth.rs index 57547a4..1060592 100644 --- a/gi/src/pg/modules/earth.rs +++ b/gi/src/pg/modules/earth.rs @@ -13,6 +13,7 @@ use crate::{ transforms::plane::PlaneTrans, Graphics, }, + ui::operation::Operations, GL, }; @@ -34,7 +35,7 @@ pub struct EarthModulePackage {} impl<'b, 'gl: 'b> Module for EarthModule<'b, 'gl> { type Cursor = EarthModulePackage; type Data = (); - type Operation = PlaneTrans; + // type Operation = PlaneTrans; const NAME: &'static str = "Earth"; @@ -49,49 +50,51 @@ impl<'b, 'gl: 'b> Module for EarthModule<'b, 'gl> { fn render( &mut self, cursor: &mut Self::Cursor, - operation: &crate::ui::operation::Operation, + operation: &crate::ui::operation::Operations, viewport: &crate::pg::layout_type::ViewPort, ) -> super::Result<()> { self.earth.mount(&self.gl)?; self.earth.set_config(&self.gl, &EarthConfig::default())?; // operation.attach_with_program(&self.gl, self.earth.program_mut()); - // Camera Info - let camera_loc = operation.camera().get_position(); + if let Operations::PT(operation) = operation { + // Camera Info + let camera_loc = operation.camera().get_position(); - // focal length - let focal_length = operation.projection().fov(); - let focal_length = 1.0 / ((focal_length / 2.0).to_radians().tan()); + // focal length + let focal_length = operation.projection().fov(); + let focal_length = 1.0 / ((focal_length / 2.0).to_radians().tan()); - // Viewport Info - let resolution = viewport.size(); + // Viewport Info + let resolution = viewport.size(); - let znear = operation.projection().z_near(); - let zfar = operation.projection().z_far(); + let znear = operation.projection().z_near(); + let zfar = operation.projection().z_far(); - unsafe { - let earth_program = self.earth.program_mut(); - let cloc = earth_program.get_uniform_location(&self.gl, "camera_location"); - let foc = earth_program.get_uniform_location(&self.gl, "focal_length"); - let res = earth_program.get_uniform_location(&self.gl, "resolution"); + unsafe { + let earth_program = self.earth.program_mut(); + let cloc = earth_program.get_uniform_location(&self.gl, "camera_location"); + let foc = earth_program.get_uniform_location(&self.gl, "focal_length"); + let res = earth_program.get_uniform_location(&self.gl, "resolution"); - let projection_params = - earth_program.get_uniform_location(&self.gl, "projection_params"); + let projection_params = + earth_program.get_uniform_location(&self.gl, "projection_params"); - let ca = earth_program.get_uniform_location(&self.gl, "ca"); + let ca = earth_program.get_uniform_location(&self.gl, "ca"); - self.gl - .uniform_3_f32(cloc.as_ref(), camera_loc.x, camera_loc.y, camera_loc.z); - self.gl.uniform_1_f32(foc.as_ref(), focal_length); - self.gl.uniform_2_f32_slice(res.as_ref(), &resolution); - self.gl - .uniform_2_f32(projection_params.as_ref(), znear, zfar); + self.gl + .uniform_3_f32(cloc.as_ref(), camera_loc.x, camera_loc.y, camera_loc.z); + self.gl.uniform_1_f32(foc.as_ref(), focal_length); + self.gl.uniform_2_f32_slice(res.as_ref(), &resolution); + self.gl + .uniform_2_f32(projection_params.as_ref(), znear, zfar); - self.gl.uniform_matrix_3_f32_slice( - ca.as_ref(), - false, - operation.camera().ca().as_slice(), - ); + self.gl.uniform_matrix_3_f32_slice( + ca.as_ref(), + false, + operation.camera().ca().as_slice(), + ); + } } self.earth.draw(&self.gl, 1); diff --git a/gi/src/pg/modules/geoquadmesh.rs b/gi/src/pg/modules/geoquadmesh.rs index cadb76e..de93bd5 100644 --- a/gi/src/pg/modules/geoquadmesh.rs +++ b/gi/src/pg/modules/geoquadmesh.rs @@ -5,9 +5,10 @@ use crate::{ geoquadmesh::{GeoQuadMesh, GeoQuadMeshConfig}, ppi::{PPIConfig, PPI}, transforms::plane::PlaneTrans, - AttaWithBuffer, Graphics, + AttaWithBuffer, AttaWithProgram, Graphics, }, pg::SideBarInputMsg, + ui::operation::Operations, GL, }; use radarg_core::{config::Setting, CoordType, Data}; @@ -115,14 +116,14 @@ impl<'b, 'a: 'b> GeoQuadMeshModule<'b, 'a> { impl<'b, 'a: 'b> Module for GeoQuadMeshModule<'b, 'a> { type Cursor = GeoQuadMeshPackage; type Data = Arc; - type Operation = PlaneTrans; + // type Operation = PlaneTrans; const NAME: &'static str = "GeoQuadMesh"; fn render<'dt>( &mut self, cursor: &mut Self::Cursor, - operation: &Operation, + operation: &Operations, viewport: &ViewPort, ) -> Result<()> { // PPI Program diff --git a/gi/src/pg/modules/mod.rs b/gi/src/pg/modules/mod.rs index a447094..d530aee 100644 --- a/gi/src/pg/modules/mod.rs +++ b/gi/src/pg/modules/mod.rs @@ -3,7 +3,7 @@ use crate::{ graphics::AttachWithIO, resources::{RcGlRcBuffer, RcGlRcResource, RcGlRcVertexArray}, ui::{ - operation::{self, Operation}, + operation::{self, Operation, Operations}, typ::CameraOP, }, utils::resources::{ManagedResource, RcGlBuffer, RcGlVertexArray}, @@ -152,20 +152,22 @@ impl Attach { pub trait Module: Sized { type Cursor: ModuleCursor; type Data; - type Operation: AttachWithIO; + // type Operation: AttachWithIO; const NAME: &'static str; fn render( &mut self, cursor: &mut Self::Cursor, - operation: &Operation, + operation: &Operations, viewport: &ViewPort, ) -> Result<()>; fn load_data<'dt>(&self, data: &Self::Data, setting: &Setting) -> Result; - fn supported(&self, data: &Data) -> bool; + fn supported(&self, data: &Data) -> bool { + false + } } pub trait ModuleCursor { diff --git a/gi/src/pg/modules/ppi.rs b/gi/src/pg/modules/ppi.rs index 7096296..c35ce59 100644 --- a/gi/src/pg/modules/ppi.rs +++ b/gi/src/pg/modules/ppi.rs @@ -4,9 +4,10 @@ use crate::{ font::{Anchor, FontConfig, LineStyle, PositionText, Text, TextLine}, ppi::{PPIConfig, PPI}, transforms::plane::PlaneTrans, - AttaWithBuffer, Graphics, + AttaWithBuffer, AttaWithProgram, Graphics, }, pg::SideBarInputMsg, + ui::operation::Operations, GL, }; use radarg_core::{config::Setting, CoordType}; @@ -283,14 +284,14 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { type Cursor = PPIPackage; type Data = Arc; - type Operation = PlaneTrans; + // type Operation = PlaneTrans; const NAME: &'static str = "PPI"; fn render<'dt>( &mut self, cursor: &mut Self::Cursor, - operation: &Operation, + operation: &Operations, viewport: &ViewPort, ) -> Result<()> { // PPI Program @@ -299,7 +300,6 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { // Mount PPI Program self.ppi_program.mount(&self.gl)?; - // Deal with the operation operation.attach_with_program(&self.gl, self.ppi_program.program()); let ppi_attach = &mut cursor.ppi_attach; diff --git a/gi/src/pg/modules/terrain.rs b/gi/src/pg/modules/terrain.rs index 2bc0a2e..f92a1cc 100644 --- a/gi/src/pg/modules/terrain.rs +++ b/gi/src/pg/modules/terrain.rs @@ -10,7 +10,7 @@ use std::{cell::RefCell, rc::Rc, sync::Arc}; use crate::{ graphics::{ planet::terrain::{Terrain, TerrainConfig}, - transforms::plane::PlaneTrans, + transforms::{plane::PlaneTrans, trackball::TrackballModel}, Graphics, }, GL, @@ -23,20 +23,24 @@ pub struct TerrainModule<'b, 'gl: 'b> { terrain: &'b mut Terrain, } -impl<'b, 'gl: 'b> TerrainModule<'b, 'gl> { - pub fn name(&self) -> &'static str { - "Terrain" - } - - pub fn supported(&self, data: &Arc) -> bool { - false - } -} - impl<'b, 'gl: 'b> TerrainModule<'b, 'gl> { pub fn new(gl: &'gl GL, terrain: &'b mut Terrain) -> Self { Self { gl, terrain } } + + fn bind_texture(&self, conf: &TerrainConfig) { + unsafe { + if let Some(tex) = conf.get_alt_texture() { + self.gl.active_texture(glow::TEXTURE1); + self.gl.bind_texture(glow::TEXTURE_2D, Some(tex.native())); + let position = self + .terrain + .program_ref() + .get_uniform_location(&self.gl, "terrain_texture"); + self.gl.uniform_1_i32(position.as_ref(), 1); + } + } + } } pub struct TerrainModulePackage { @@ -46,7 +50,7 @@ pub struct TerrainModulePackage { impl<'b, 'gl: 'b> Module for TerrainModule<'b, 'gl> { type Cursor = TerrainModulePackage; type Data = (); - type Operation = PlaneTrans; + // type Operation = TrackballModel; const NAME: &'static str = "Terrain"; @@ -64,33 +68,68 @@ impl<'b, 'gl: 'b> Module for TerrainModule<'b, 'gl> { fn render( &mut self, cursor: &mut Self::Cursor, - operation: &crate::ui::operation::Operation, + operation: &crate::ui::operation::Operations, viewport: &crate::pg::layout_type::ViewPort, ) -> super::Result<()> { self.terrain.mount(&self.gl)?; + let conf = &mut cursor.conf.terrain_conf; - let conf = &cursor.conf.terrain_conf; + match operation { + crate::ui::operation::Operations::TB(operation) => { + // Theta and Phi + let (theta, phi) = operation.status(); + conf.theta = theta; + conf.phi = phi; - self.terrain.set_config(&self.gl, conf)?; - // operation.attach_with_program(&self.gl, self.earth.program_mut()); - // Camera Info - let camera_loc = operation.camera().get_position(); + println!("Theta: {}, Phi: {}", theta, phi); + self.terrain.set_config(&self.gl, conf); - // focal length - let focal_length = operation.projection().fov(); - let focal_length = 1.0 / ((focal_length / 2.0).to_radians().tan()); + // Camera Info + let camera_loc = operation.camera().get_position(); - // Viewport Info - let resolution = viewport.size(); + // focal length + let focal_length = operation.projection().fov(); + let focal_length = 1.0 / ((focal_length / 2.0).to_radians().tan()); - let znear = operation.projection().z_near(); - let zfar = operation.projection().z_far(); + // Viewport Info + let resolution = viewport.size(); + + let znear = operation.projection().z_near(); + let zfar = operation.projection().z_far(); + + // Left Hand Coordinate System + let ca = operation.camera().ca(); + + unsafe { + let gl = &self.gl; + let program = self.terrain.program_ref(); + + let p = program.get_uniform_location(gl, "focal_length"); + gl.uniform_1_f32(p.as_ref(), focal_length); + + let p = program.get_uniform_location(gl, "resolution"); + gl.uniform_2_f32_slice(p.as_ref(), &resolution); + + let p = program.get_uniform_location(gl, "projection_params"); + gl.uniform_2_f32(p.as_ref(), znear, zfar); + + let p = program.get_uniform_location(gl, "ca"); + gl.uniform_matrix_3_f32_slice(p.as_ref(), false, ca.as_slice()); + + let p = program.get_uniform_location(gl, "camera_location"); + gl.uniform_3_f32_slice( + p.as_ref(), + operation.camera().get_position().as_slice(), + ); + } + } + _ => {} + } + + self.bind_texture(conf); + self.terrain.draw(&self.gl, 4); Ok(()) } - - fn supported(&self, data: &radarg_core::Data) -> bool { - false - } } #[derive(Default)] diff --git a/gi/src/shaders/terrain.rs b/gi/src/shaders/terrain.rs index eeb48ee..4f51ae6 100644 --- a/gi/src/shaders/terrain.rs +++ b/gi/src/shaders/terrain.rs @@ -67,22 +67,41 @@ impl TerrainFragment { return vec2( max( max( t1.x, t1.y ), t1.z ),min( min( t2.x, t2.y ), t2.z ) ); } + + vec2 sdf(vec3 p) { float ER = earth.x; - float alpha = earth.y; - float beta = earth.z; + float theta = earth.y; + float phi = earth.z; - float longitude = atan(p.z, p.x) + alpha; - float latitude = atan(p.y, length(p.xz)) + beta; + // Lon and Lat + float lon = (atan(p.z, p.x) + theta) / (2.0 * PI) * 360.0; + float lat = (atan(p.y, length(p.xy)) + phi) / (2.0 * PI) * 360.0; - // 从高度图获取地形高度 - vec2 uv = vec2((longitude + PI) / (2.0 * PI), (latitude + PI / 2.0) / PI); + // Texture UV + float lon_start = tex_range.x; + float lon_end = tex_range.y; + + float lat_start = tex_range.z; + float lat_end = tex_range.w; + + float baseDist = length(p) - ER; + vec2 uv = vec2((lon - lon_start) / (lon_end - lon_start), (lat - lat_start) / (lat_end - lat_start)); float height = texture(terrain_texture, uv).r * maxHeight; + float h = baseDist - height*5.0; // 计算点到地球表面的最近距离 - float baseDist = length(p) - ER - height; - return vec2(baseDist, height); + return vec2(h, height); + } + + vec3 calcNormal( in vec3 pos ) + { + vec2 e = vec2(1.0,-1.0)*0.5773*0.0005; + return normalize( e.xyy*sdf( pos + e.xyy).x + + e.yyx*sdf( pos + e.yyx).x + + e.yxy*sdf( pos + e.yxy).x + + e.xxx*sdf( pos + e.xxx).x ); } vec2 raycast(vec3 ro, vec3 rd) { @@ -104,11 +123,12 @@ impl TerrainFragment { int i = 0; while (i < 70 && t < tmax) { - vec2 h = sdf(ro + rd * t); - if (abs(h.x) < (0.0001 * t)) { - res = vec2(t, h.y); + vec2 cast_result = sdf(ro + rd * t); + if (abs(cast_result.x) < (0.0001 * t)) { + res = cast_result; + break; } - t += h.x; + t += cast_result.x; i += 1; } } @@ -116,18 +136,51 @@ impl TerrainFragment { } void main() { + vec2 p = (2.0 * gl_FragCoord.xy - resolution) / resolution.y; vec3 rd = normalize(ca * vec3(p, focal_length)); - vec2 res = raycast(camera_location, rd); float t = res.x; + + vec3 pos = camera_location + rd*t; + + if (t < 0.0) { + discard; + } + + vec3 col = vec3(0.7, 0.7, 0.9) - max(1.0,0.0)*0.3; float m = res.y; - if (m < 0.0) { - discard; - } - FragColor = vec4(1.0, 0.0, 0.0, 1.0); + // float m = 1.0 - res.y; + // col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) ); + + // col = linear_colormap(m).rgb; + col = vec3(1.0,1.0,1.0); + + vec3 nor = calcNormal(pos); + + vec3 lin = vec3(0.0); + float ks = 1.0; + + // FragColor = vec4(m,m,m,1.0); + vec3 lig = normalize( vec3(-0.5, 0.4, -0.6) ); + vec3 hal = normalize( lig-rd ); + float dif = clamp( dot( nor, lig ), 0.0, 1.0 ); + float spe = pow( clamp( dot( nor, hal ), 0.0, 1.0 ),16.0); + + + + + spe *= dif; + spe *= 0.04+0.96*pow(clamp(1.0-dot(hal,lig),0.0,1.0),5.0); + lin += col*2.20*dif*vec3(1.30,1.00,0.70); + lin += 5.00*spe*vec3(1.30,1.00,0.70)*ks; + + col = clamp(mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ), 0.0, 1.0); + + FragColor = vec4(col, 1.0); + } " diff --git a/gi/src/ui/operation.rs b/gi/src/ui/operation.rs index 4f6c918..cc02a9c 100644 --- a/gi/src/ui/operation.rs +++ b/gi/src/ui/operation.rs @@ -2,10 +2,97 @@ use super::typ::CameraOP; use crate::{ camera::Camera, components::Program, - graphics::{AttaWithProgram, AttachWithIO}, + graphics::{ + transforms::{plane::PlaneTrans, trackball::TrackballModel}, + AttaWithProgram, AttachWithIO, + }, pg::layout_type::ViewPort, }; +macro_rules! impl_operations { + ($({$operation:ty => $b:tt, $method: ident}),+) => { + pub enum Operations { + $( + $b(Operation<$operation>) + ),+ + } + + + impl Operations { + + $( + pub fn $method() -> Self { + Operations::$b(Operation::new(<$operation>::default(), 16.0/9.0, 45.0,0.1,1000.0 )) + } + + )+ + + pub fn set_projection(&mut self, f: impl Fn(&mut Projection)) { + match self { + $( + Operations::$b(op) => { + op.set_projection(f); + op.need_update = true; + } + )+ + } + } + + pub fn deal_io(&mut self, viewport: &ViewPort, io: &super::io::IO) { + match self { + $( + Operations::$b(op) => { + op.deal_io(viewport, io); + } + )+ + } + } + + pub fn set_camera(&mut self, camera: Camera) { + match self { + $( + Operations::$b(op) => { + op.camera = camera; + op.need_update = true; + } + )+ + } + } + } + + + $( + + impl<'a> From<&'a Operations> for &'a Operation<$operation> { + fn from(operations: &'a Operations) -> Self { + match operations { + Operations::$b(op) => op, + _ => panic!("error transfer"), + } + } + } + )+ + + impl AttaWithProgram for Operations { + fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> super::Result<()> { + match self { + $( + + Operations::$b(op) => { + op.operation.attach_with_program(gl, program)?; + } + + ),+ + } + Ok(()) + } + } + + + + }; +} + pub struct Operation { camera: Camera, projection: Projection, @@ -51,7 +138,7 @@ impl Operation { self.need_update = true; } - pub fn attach_with_program(&self, gl: &glow::Context, program: &mut Program) { + pub fn attach_with_program(&self, gl: &glow::Context, program: &Program) { use glow::HasContext; unsafe { let projection = program.get_uniform_location(gl, "trackball_projection"); @@ -78,6 +165,10 @@ impl Operation { pub fn clean(&mut self) { self.need_update = false; } + + pub fn status(&self) -> ::Status { + self.operation.status() + } } pub struct Projection { @@ -143,3 +234,8 @@ impl Projection { self.projection.as_slice() } } + +impl_operations!( + {PlaneTrans => PT, plane_trans}, + {TrackballModel => TB, trackball_model} +); diff --git a/radar-g/src/main.rs b/radar-g/src/main.rs index 024f4f0..c5d6a38 100644 --- a/radar-g/src/main.rs +++ b/radar-g/src/main.rs @@ -56,8 +56,6 @@ fn main() { }); } - // gi.prepare(); - let app = adw::Application::builder().application_id(APP_ID).build(); let relm: RelmApp = relm4::RelmApp::from_app(app.clone()); relm4_icons::initialize_icons(); diff --git a/radar-g/src/widgets/render/imp.rs b/radar-g/src/widgets/render/imp.rs index 2d42d2a..0d14eae 100644 --- a/radar-g/src/widgets/render/imp.rs +++ b/radar-g/src/widgets/render/imp.rs @@ -8,7 +8,7 @@ use gi::graphics::transforms::plane::PlaneTrans; use gi::pg::layout_type::ViewPort; use gi::pg::{Module, ModulePackage}; use gi::ui::io::IO; -use gi::ui::operation::Operation; +use gi::ui::operation::Operations; use gi::{App as GI, Helper, GL}; use glow::HasContext; use gtk::glib::{self, prelude::*, Properties}; @@ -64,7 +64,7 @@ pub struct Render { #[property(get, set)] scale: Cell, pub(super) io: RefCell, - pub(super) opeartion: RefCell>, + pub(super) opeartion: RefCell, pub(super) exterior: RefCell, pub(super) interior: RefCell, pub(super) gi: RefCell>, @@ -79,13 +79,7 @@ impl Default for Render { fn default() -> Self { Self { scale: Cell::new(1.0), - opeartion: RefCell::new(Operation::new( - PlaneTrans::default(), - 16.0 / 9.0, - 45.0, - 0.1, - 1000.0, - )), + opeartion: RefCell::new(Operations::trackball_model()), io: RefCell::new(IO::default()), range_changing: Cell::new(0.0), render_status: Cell::new(0), @@ -247,9 +241,10 @@ impl Render { gi.prepare(&SETTING).expect("Cannot prepare GI"); // Terrain - let terrain_module = gi.program().terrain().load_data(&(), &SETTING).unwrap(); + let init_module = gi.program().terrain().load_data(&(), &SETTING).unwrap(); + // let init_module = gi.program().earth().load_data(&(), &SETTING).unwrap(); // Init Modules - gi.set_init_modules(terrain_module.into()); + gi.set_init_modules(init_module); // Set Modules self.viewport.replace(Some(viewport));