Start to rig stuff for the aerodynamics test I wanted to make in the first place
							parent
							
								
									afb0238c1b
								
							
						
					
					
						commit
						8a6d5518f1
					
				| 
						 | 
					@ -32,6 +32,7 @@ where V: Into <Vec3>
 | 
				
			||||||
	))
 | 
						))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Use iota macro
 | 
				
			||||||
const KEY_LEFT: usize = 0;
 | 
					const KEY_LEFT: usize = 0;
 | 
				
			||||||
const KEY_RIGHT: usize = KEY_LEFT + 1;
 | 
					const KEY_RIGHT: usize = KEY_LEFT + 1;
 | 
				
			||||||
const KEY_UP: usize = KEY_RIGHT + 1;
 | 
					const KEY_UP: usize = KEY_RIGHT + 1;
 | 
				
			||||||
| 
						 | 
					@ -60,41 +61,79 @@ impl ControllerState {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct EulerAngles {
 | 
				
			||||||
 | 
						pub azimuth: f32,
 | 
				
			||||||
 | 
						pub altitude: f32,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Default for EulerAngles {
 | 
				
			||||||
 | 
						fn default () -> Self {
 | 
				
			||||||
 | 
							Self {
 | 
				
			||||||
 | 
								azimuth: 0.0,
 | 
				
			||||||
 | 
								altitude: 0.0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl EulerAngles {
 | 
				
			||||||
 | 
						pub fn to_vec3 (&self) -> Vec3 {
 | 
				
			||||||
 | 
							let alt = self.altitude * std::f32::consts::PI / 180.0;
 | 
				
			||||||
 | 
							let azi = self.azimuth * std::f32::consts::PI / 180.0;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let z = alt.sin ();
 | 
				
			||||||
 | 
							let xy_len = alt.cos ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let x = xy_len * azi.sin ();
 | 
				
			||||||
 | 
							let y = xy_len * azi.cos ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							(x, y, z).into ()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct WorldState {
 | 
					struct WorldState {
 | 
				
			||||||
	azimuth: f32,
 | 
						camera: EulerAngles,
 | 
				
			||||||
	altitude: f32,
 | 
						wind: EulerAngles,
 | 
				
			||||||
	spin_speed: i32,
 | 
						spin_speed: i32,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl WorldState {
 | 
					impl WorldState {
 | 
				
			||||||
	pub fn new () -> Self {
 | 
						pub fn new () -> Self {
 | 
				
			||||||
		Self {
 | 
							Self {
 | 
				
			||||||
			azimuth: 0.0,
 | 
								camera: Default::default (),
 | 
				
			||||||
			altitude: 0.0,
 | 
								wind: Default::default (),
 | 
				
			||||||
			spin_speed: 0,
 | 
								spin_speed: 0,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	pub fn step (&mut self, controller: &ControllerState) {
 | 
						pub fn step (
 | 
				
			||||||
 | 
							&mut self, 
 | 
				
			||||||
 | 
							controller: &ControllerState,
 | 
				
			||||||
 | 
							user_control: &UserControl
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
		const SPIN_RAMP_TIME: i32 = 30;
 | 
							const SPIN_RAMP_TIME: i32 = 30;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let spin_f = 4.0 * self.spin_speed as f32 / SPIN_RAMP_TIME as f32;
 | 
							let spin_f = 4.0 * self.spin_speed as f32 / SPIN_RAMP_TIME as f32;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							let controlled_angle = match user_control {
 | 
				
			||||||
 | 
								UserControl::Camera => &mut self.camera,
 | 
				
			||||||
 | 
								UserControl::Wind => &mut self.wind,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		if controller.is_pressed (KEY_LEFT) {
 | 
							if controller.is_pressed (KEY_LEFT) {
 | 
				
			||||||
			self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
								self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
				
			||||||
			self.azimuth += spin_f;
 | 
								controlled_angle.azimuth += spin_f;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if controller.is_pressed (KEY_RIGHT) {
 | 
							else if controller.is_pressed (KEY_RIGHT) {
 | 
				
			||||||
			self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
								self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
				
			||||||
			self.azimuth -= spin_f;
 | 
								controlled_angle.azimuth -= spin_f;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if controller.is_pressed (KEY_UP) {
 | 
							else if controller.is_pressed (KEY_UP) {
 | 
				
			||||||
			self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
								self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
				
			||||||
			self.altitude = f32::min (90.0, self.altitude + spin_f);
 | 
								controlled_angle.altitude = f32::min (90.0, controlled_angle.altitude + spin_f);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if controller.is_pressed (KEY_DOWN) {
 | 
							else if controller.is_pressed (KEY_DOWN) {
 | 
				
			||||||
			self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
								self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
 | 
				
			||||||
			self.altitude = f32::max (-90.0, self.altitude - spin_f);
 | 
								controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			self.spin_speed = 0;
 | 
								self.spin_speed = 0;
 | 
				
			||||||
| 
						 | 
					@ -145,11 +184,13 @@ where P: AsRef <std::path::Path>
 | 
				
			||||||
struct Arrow {
 | 
					struct Arrow {
 | 
				
			||||||
	origin: Vec3,
 | 
						origin: Vec3,
 | 
				
			||||||
	direction: Vec3,
 | 
						direction: Vec3,
 | 
				
			||||||
 | 
						color: Vec3,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct RenderableArrow {
 | 
					struct RenderableArrow {
 | 
				
			||||||
	model_mat: Mat4,
 | 
						model_mat: Mat4,
 | 
				
			||||||
	inv_model_mat: Mat4,
 | 
						inv_model_mat: Mat4,
 | 
				
			||||||
 | 
						color: Vec3,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Copy, Clone, PartialEq, Eq)]
 | 
					#[derive (Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
| 
						 | 
					@ -233,6 +274,37 @@ impl From <StencilFunc> for u32 {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive (Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub enum DepthFunc {
 | 
				
			||||||
 | 
						Never, 
 | 
				
			||||||
 | 
						Always, 
 | 
				
			||||||
 | 
						Less, 
 | 
				
			||||||
 | 
						LessEqual, 
 | 
				
			||||||
 | 
						Equal, 
 | 
				
			||||||
 | 
						Greater, 
 | 
				
			||||||
 | 
						GreaterEqual,
 | 
				
			||||||
 | 
						NotEqual,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From <DepthFunc> for u32 {
 | 
				
			||||||
 | 
						fn from (v: DepthFunc) -> Self {
 | 
				
			||||||
 | 
							use DepthFunc::*;
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							use gl::*;
 | 
				
			||||||
 | 
							match v {
 | 
				
			||||||
 | 
								Never => NEVER,
 | 
				
			||||||
 | 
								Always => ALWAYS,
 | 
				
			||||||
 | 
								Less => LESS,
 | 
				
			||||||
 | 
								LessEqual => LEQUAL,
 | 
				
			||||||
 | 
								Equal => EQUAL,
 | 
				
			||||||
 | 
								Greater => GREATER,
 | 
				
			||||||
 | 
								GreaterEqual => GEQUAL,
 | 
				
			||||||
 | 
								NotEqual => NOTEQUAL,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive (Copy, Clone, PartialEq, Eq)]
 | 
					#[derive (Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
pub struct StencilOpState {
 | 
					pub struct StencilOpState {
 | 
				
			||||||
	sfail: StencilOp,
 | 
						sfail: StencilOp,
 | 
				
			||||||
| 
						 | 
					@ -257,9 +329,12 @@ pub struct StencilState {
 | 
				
			||||||
// to safely use the flags / numbers
 | 
					// to safely use the flags / numbers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct IsoGlState {
 | 
					pub struct IsoGlState {
 | 
				
			||||||
 | 
						shader_id: Option <u32>,
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	flags: HashMap <u32, bool>,
 | 
						flags: HashMap <u32, bool>,
 | 
				
			||||||
	front_face: Option <FrontFace>,
 | 
						front_face: Option <FrontFace>,
 | 
				
			||||||
	stencil: Option <StencilState>,
 | 
						stencil: Option <StencilState>,
 | 
				
			||||||
 | 
						depth_func: Option <DepthFunc>,
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	color_mask: Option <(u8, u8, u8, u8)>,
 | 
						color_mask: Option <(u8, u8, u8, u8)>,
 | 
				
			||||||
	depth_mask: Option <u8>,
 | 
						depth_mask: Option <u8>,
 | 
				
			||||||
| 
						 | 
					@ -269,9 +344,11 @@ pub struct IsoGlState {
 | 
				
			||||||
impl std::default::Default for IsoGlState {
 | 
					impl std::default::Default for IsoGlState {
 | 
				
			||||||
	fn default () -> Self {
 | 
						fn default () -> Self {
 | 
				
			||||||
		Self {
 | 
							Self {
 | 
				
			||||||
 | 
								shader_id: None,
 | 
				
			||||||
			flags: hashmap! {},
 | 
								flags: hashmap! {},
 | 
				
			||||||
			front_face: None,
 | 
								front_face: None,
 | 
				
			||||||
			stencil: None,
 | 
								stencil: None,
 | 
				
			||||||
 | 
								depth_func: None,
 | 
				
			||||||
			color_mask: None,
 | 
								color_mask: None,
 | 
				
			||||||
			depth_mask: None,
 | 
								depth_mask: None,
 | 
				
			||||||
			stencil_mask: None,
 | 
								stencil_mask: None,
 | 
				
			||||||
| 
						 | 
					@ -282,13 +359,11 @@ impl std::default::Default for IsoGlState {
 | 
				
			||||||
// These are POD IDs or hashes of non-POD data
 | 
					// These are POD IDs or hashes of non-POD data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct NonIsoGlState {
 | 
					pub struct NonIsoGlState {
 | 
				
			||||||
	shader_id: Option <u32>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::default::Default for NonIsoGlState {
 | 
					impl std::default::Default for NonIsoGlState {
 | 
				
			||||||
	fn default () -> Self {
 | 
						fn default () -> Self {
 | 
				
			||||||
		Self {
 | 
							Self {
 | 
				
			||||||
			shader_id: None,
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -307,17 +382,13 @@ impl std::default::Default for GlState {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Pass <'a> {
 | 
					pub struct Pass {
 | 
				
			||||||
	// In the context of a Pass, "None" means "Don't care"
 | 
						// In the context of a Pass, "None" means "Don't care"
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	iso: IsoGlState,
 | 
						iso: IsoGlState,
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// Non-iso state must have its sources here
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	shader: Option <&'a ShaderClosure>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Pass <'_> {
 | 
					impl Pass {
 | 
				
			||||||
	pub fn apply_diff (&self, old_state: &mut IsoGlState) {
 | 
						pub fn apply_diff (&self, old_state: &mut IsoGlState) {
 | 
				
			||||||
		let state = &self.iso;
 | 
							let state = &self.iso;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -381,6 +452,16 @@ impl Pass <'_> {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							if let Some (v) = &state.depth_func {
 | 
				
			||||||
 | 
								if old_state.depth_func != state.depth_func {
 | 
				
			||||||
 | 
									glezz::depth_func ((*v).into ());
 | 
				
			||||||
 | 
									old_state.depth_func = state.depth_func;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									//println! ("Elided depth_func ()");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		if let Some ((r, g, b, a)) = &state.color_mask {
 | 
							if let Some ((r, g, b, a)) = &state.color_mask {
 | 
				
			||||||
			if old_state.color_mask != state.color_mask {
 | 
								if old_state.color_mask != state.color_mask {
 | 
				
			||||||
				glezz::color_mask (*r, *g, *b, *a);
 | 
									glezz::color_mask (*r, *g, *b, *a);
 | 
				
			||||||
| 
						 | 
					@ -425,15 +506,20 @@ impl Pass <'_> {
 | 
				
			||||||
		callback ();
 | 
							callback ();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	pub fn with_shader <F> (&self, gl_state: &mut GlState, callback: F) 
 | 
						pub fn with_shader <F, S> (
 | 
				
			||||||
	where F: Fn (BorrowedShaderVars)
 | 
							&self, 
 | 
				
			||||||
 | 
							gl_state: &mut GlState, 
 | 
				
			||||||
 | 
							shader_component: &S, 
 | 
				
			||||||
 | 
							callback: F
 | 
				
			||||||
 | 
						) 
 | 
				
			||||||
 | 
						where F: Fn (BorrowedShaderVars), S: ShaderLookup
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if let Some (s) = self.shader {
 | 
							if let Some (s) = self.iso.shader_id {
 | 
				
			||||||
			self.apply_diff (&mut gl_state.iso);
 | 
								self.apply_diff (&mut gl_state.iso);
 | 
				
			||||||
			s.with (gl_state.non_iso.shader_id, |shader_vars| {
 | 
								shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
 | 
				
			||||||
				callback (shader_vars);
 | 
									callback (shader_vars);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
			gl_state.non_iso.shader_id = Some (s.get_id ());
 | 
								gl_state.iso.shader_id = Some (s);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			panic! ("Called with_shader on a pass with no shader");
 | 
								panic! ("Called with_shader on a pass with no shader");
 | 
				
			||||||
| 
						 | 
					@ -441,9 +527,15 @@ impl Pass <'_> {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait ShaderLookup {
 | 
				
			||||||
 | 
						fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct GameGraphics {
 | 
					struct GameGraphics {
 | 
				
			||||||
	shader_diffuse: ShaderClosure,
 | 
						passes: Vec <Pass>,
 | 
				
			||||||
	shader_shadow: ShaderClosure,
 | 
						
 | 
				
			||||||
 | 
						shaders: Vec <ShaderClosure>,
 | 
				
			||||||
 | 
						shader_lookup: HashMap <u32, usize>,
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	mesh_pumpkin: RenderableModel,
 | 
						mesh_pumpkin: RenderableModel,
 | 
				
			||||||
	mesh_sky: RenderableModel,
 | 
						mesh_sky: RenderableModel,
 | 
				
			||||||
| 
						 | 
					@ -456,6 +548,12 @@ struct GameGraphics {
 | 
				
			||||||
	grass_index: usize,
 | 
						grass_index: usize,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ShaderLookup for GameGraphics {
 | 
				
			||||||
 | 
						fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure {
 | 
				
			||||||
 | 
							&self.shaders [self.shader_lookup [&id]]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl GameGraphics {
 | 
					impl GameGraphics {
 | 
				
			||||||
	pub fn new () -> Self {
 | 
						pub fn new () -> Self {
 | 
				
			||||||
		let uniform_names = {
 | 
							let uniform_names = {
 | 
				
			||||||
| 
						 | 
					@ -480,10 +578,21 @@ impl GameGraphics {
 | 
				
			||||||
			]
 | 
								]
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let shader_diffuse = ShaderClosure::new (shader_from_files ("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"), &uniform_names, &attr_names);
 | 
							let shaders: Vec <_> = [
 | 
				
			||||||
		let shader_shadow = ShaderClosure::new (shader_from_files ("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"), &uniform_names, &attr_names);
 | 
								("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"),
 | 
				
			||||||
 | 
								("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"),
 | 
				
			||||||
 | 
							].iter ()
 | 
				
			||||||
 | 
							.map (|(v, f)| {
 | 
				
			||||||
 | 
								ShaderClosure::new (shader_from_files (v, f), &uniform_names, &attr_names)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.collect ();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		shader_diffuse.with (None, |shader_vars| {
 | 
							let shader_lookup = HashMap::from_iter (shaders.iter ().enumerate ()
 | 
				
			||||||
 | 
							.map (|(i, s)| {
 | 
				
			||||||
 | 
								(s.get_id (), i)
 | 
				
			||||||
 | 
							}));
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							shaders [0].with (None, |shader_vars| {
 | 
				
			||||||
			let attrs = shader_vars.attrs;
 | 
								let attrs = shader_vars.attrs;
 | 
				
			||||||
			use renderable_model::attributes::*;
 | 
								use renderable_model::attributes::*;
 | 
				
			||||||
			glezz::enable_vertex_attrib_array (attrs [POS]);
 | 
								glezz::enable_vertex_attrib_array (attrs [POS]);
 | 
				
			||||||
| 
						 | 
					@ -538,9 +647,183 @@ impl GameGraphics {
 | 
				
			||||||
			(colors, grass_index.unwrap ())
 | 
								(colors, grass_index.unwrap ())
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							let passes = vec! [
 | 
				
			||||||
 | 
								// Clear everything
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: None,
 | 
				
			||||||
 | 
										flags: hashmap! {},
 | 
				
			||||||
 | 
										front_face: None,
 | 
				
			||||||
 | 
										stencil: None,
 | 
				
			||||||
 | 
										depth_func: None,
 | 
				
			||||||
 | 
										color_mask: Some ((1, 1, 1, 1)),
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: Some (255),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Draw world
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: Some (shaders [0].get_id ()),
 | 
				
			||||||
 | 
										flags: hashmap! {
 | 
				
			||||||
 | 
											gl::CULL_FACE => true,
 | 
				
			||||||
 | 
											gl::DEPTH_TEST => true,
 | 
				
			||||||
 | 
											gl::TEXTURE_2D => true,
 | 
				
			||||||
 | 
											gl::STENCIL_TEST => false,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										front_face: Some (FrontFace::Cw),
 | 
				
			||||||
 | 
										stencil: Some (StencilState {
 | 
				
			||||||
 | 
											func: StencilFuncState {
 | 
				
			||||||
 | 
												func: StencilFunc::Always,
 | 
				
			||||||
 | 
												reference: 0,
 | 
				
			||||||
 | 
												mask: 0,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											op: StencilOpState {
 | 
				
			||||||
 | 
												sfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dpfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dppass: StencilOp::Keep,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}),
 | 
				
			||||||
 | 
										depth_func: Some (DepthFunc::Less),
 | 
				
			||||||
 | 
										color_mask: Some ((1, 1, 1, 1)),
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: Some (0),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Write shadows into stencil buffer
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: Some (shaders [1].get_id ()),
 | 
				
			||||||
 | 
										flags: hashmap! {
 | 
				
			||||||
 | 
											gl::CULL_FACE => true,
 | 
				
			||||||
 | 
											gl::DEPTH_TEST => true,
 | 
				
			||||||
 | 
											gl::STENCIL_TEST => true,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										front_face: Some (FrontFace::Ccw),
 | 
				
			||||||
 | 
										stencil: Some (StencilState {
 | 
				
			||||||
 | 
											func: StencilFuncState {
 | 
				
			||||||
 | 
												func: StencilFunc::Always,
 | 
				
			||||||
 | 
												reference: 1,
 | 
				
			||||||
 | 
												mask: 1,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											op: StencilOpState {
 | 
				
			||||||
 | 
												sfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dpfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dppass: StencilOp::Replace,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}),
 | 
				
			||||||
 | 
										depth_func: Some (DepthFunc::Less),
 | 
				
			||||||
 | 
										color_mask: Some ((0, 0, 0, 0)),
 | 
				
			||||||
 | 
										depth_mask: Some (0),
 | 
				
			||||||
 | 
										stencil_mask: Some (255),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Draw lit ground
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: Some (shaders [0].get_id ()),
 | 
				
			||||||
 | 
										flags: hashmap! {
 | 
				
			||||||
 | 
											gl::CULL_FACE => true,
 | 
				
			||||||
 | 
											gl::DEPTH_TEST => true,
 | 
				
			||||||
 | 
											gl::TEXTURE_2D => true,
 | 
				
			||||||
 | 
											gl::STENCIL_TEST => true,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										front_face: Some (FrontFace::Cw),
 | 
				
			||||||
 | 
										stencil: Some (StencilState {
 | 
				
			||||||
 | 
											func: StencilFuncState {
 | 
				
			||||||
 | 
												func: StencilFunc::NotEqual,
 | 
				
			||||||
 | 
												reference: 0,
 | 
				
			||||||
 | 
												mask: 1,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											op: StencilOpState {
 | 
				
			||||||
 | 
												sfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dpfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dppass: StencilOp::Keep,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}),
 | 
				
			||||||
 | 
										depth_func: Some (DepthFunc::Less),
 | 
				
			||||||
 | 
										color_mask: Some ((1, 1, 1, 1)),
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: Some (0),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Draw unlit ground
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: Some (shaders [0].get_id ()),
 | 
				
			||||||
 | 
										flags: hashmap! {
 | 
				
			||||||
 | 
											gl::CULL_FACE => true,
 | 
				
			||||||
 | 
											gl::DEPTH_TEST => true,
 | 
				
			||||||
 | 
											gl::TEXTURE_2D => true,
 | 
				
			||||||
 | 
											gl::STENCIL_TEST => true,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										front_face: Some (FrontFace::Cw),
 | 
				
			||||||
 | 
										stencil: Some (StencilState {
 | 
				
			||||||
 | 
											func: StencilFuncState {
 | 
				
			||||||
 | 
												func: StencilFunc::Equal,
 | 
				
			||||||
 | 
												reference: 0,
 | 
				
			||||||
 | 
												mask: 1,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											op: StencilOpState {
 | 
				
			||||||
 | 
												sfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dpfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dppass: StencilOp::Keep,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}),
 | 
				
			||||||
 | 
										depth_func: Some (DepthFunc::Less),
 | 
				
			||||||
 | 
										color_mask: Some ((1, 1, 1, 1)),
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: Some (0),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Clear depth
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: None,
 | 
				
			||||||
 | 
										flags: hashmap! {},
 | 
				
			||||||
 | 
										front_face: None,
 | 
				
			||||||
 | 
										stencil: None,
 | 
				
			||||||
 | 
										depth_func: None,
 | 
				
			||||||
 | 
										color_mask: None,
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: None,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								// Draw arrows
 | 
				
			||||||
 | 
								Pass {
 | 
				
			||||||
 | 
									iso: IsoGlState {
 | 
				
			||||||
 | 
										shader_id: Some (shaders [0].get_id ()),
 | 
				
			||||||
 | 
										flags: hashmap! {
 | 
				
			||||||
 | 
											gl::CULL_FACE => true,
 | 
				
			||||||
 | 
											gl::DEPTH_TEST => true,
 | 
				
			||||||
 | 
											gl::TEXTURE_2D => true,
 | 
				
			||||||
 | 
											gl::STENCIL_TEST => false,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										front_face: Some (FrontFace::Cw),
 | 
				
			||||||
 | 
										stencil: Some (StencilState {
 | 
				
			||||||
 | 
											func: StencilFuncState {
 | 
				
			||||||
 | 
												func: StencilFunc::Always,
 | 
				
			||||||
 | 
												reference: 0,
 | 
				
			||||||
 | 
												mask: 0,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											op: StencilOpState {
 | 
				
			||||||
 | 
												sfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dpfail: StencilOp::Keep,
 | 
				
			||||||
 | 
												dppass: StencilOp::Keep,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										}),
 | 
				
			||||||
 | 
										depth_func: Some (DepthFunc::Less),
 | 
				
			||||||
 | 
										color_mask: Some ((1, 1, 1, 1)),
 | 
				
			||||||
 | 
										depth_mask: Some (1),
 | 
				
			||||||
 | 
										stencil_mask: Some (0),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		Self {
 | 
							Self {
 | 
				
			||||||
			shader_diffuse,
 | 
								passes,
 | 
				
			||||||
			shader_shadow,
 | 
								shaders,
 | 
				
			||||||
 | 
								shader_lookup,
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			mesh_pumpkin,
 | 
								mesh_pumpkin,
 | 
				
			||||||
			mesh_sky,
 | 
								mesh_sky,
 | 
				
			||||||
| 
						 | 
					@ -574,8 +857,8 @@ impl GameGraphics {
 | 
				
			||||||
			green,
 | 
								green,
 | 
				
			||||||
		];
 | 
							];
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let longitude = state.azimuth.to_radians ();
 | 
							let longitude = state.camera.azimuth.to_radians ();
 | 
				
			||||||
		let latitude = (state.altitude - 90.0).to_radians ();
 | 
							let latitude = (state.camera.altitude - 90.0).to_radians ();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0);
 | 
							let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -598,122 +881,9 @@ impl GameGraphics {
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		//println! ("Started frame");
 | 
							//println! ("Started frame");
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let passes = vec! [
 | 
							let mut passes = self.passes.iter ();
 | 
				
			||||||
			// Clear everything
 | 
					 | 
				
			||||||
			Pass {
 | 
					 | 
				
			||||||
				shader: None,
 | 
					 | 
				
			||||||
				iso: IsoGlState {
 | 
					 | 
				
			||||||
					flags: hashmap! {},
 | 
					 | 
				
			||||||
					front_face: None,
 | 
					 | 
				
			||||||
					stencil: None,
 | 
					 | 
				
			||||||
					color_mask: Some ((1, 1, 1, 1)),
 | 
					 | 
				
			||||||
					depth_mask: Some (1),
 | 
					 | 
				
			||||||
					stencil_mask: Some (255),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			// Draw world
 | 
					 | 
				
			||||||
			Pass {
 | 
					 | 
				
			||||||
				shader: Some (&self.shader_diffuse),
 | 
					 | 
				
			||||||
				iso: IsoGlState {
 | 
					 | 
				
			||||||
					flags: hashmap! {
 | 
					 | 
				
			||||||
						gl::CULL_FACE => true,
 | 
					 | 
				
			||||||
						gl::DEPTH_TEST => true,
 | 
					 | 
				
			||||||
						gl::TEXTURE_2D => true,
 | 
					 | 
				
			||||||
						gl::STENCIL_TEST => false,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					front_face: Some (FrontFace::Cw),
 | 
					 | 
				
			||||||
					stencil: None,
 | 
					 | 
				
			||||||
					color_mask: Some ((1, 1, 1, 1)),
 | 
					 | 
				
			||||||
					depth_mask: Some (1),
 | 
					 | 
				
			||||||
					stencil_mask: Some (0),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			// Write shadows into stencil buffer
 | 
					 | 
				
			||||||
			Pass {
 | 
					 | 
				
			||||||
				shader: Some (&self.shader_shadow),
 | 
					 | 
				
			||||||
				iso: IsoGlState {
 | 
					 | 
				
			||||||
					flags: hashmap! {
 | 
					 | 
				
			||||||
						gl::CULL_FACE => true,
 | 
					 | 
				
			||||||
						gl::DEPTH_TEST => true,
 | 
					 | 
				
			||||||
						gl::STENCIL_TEST => true,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					front_face: Some (FrontFace::Ccw),
 | 
					 | 
				
			||||||
					stencil: Some (StencilState {
 | 
					 | 
				
			||||||
						func: StencilFuncState {
 | 
					 | 
				
			||||||
							func: StencilFunc::Always,
 | 
					 | 
				
			||||||
							reference: 1,
 | 
					 | 
				
			||||||
							mask: 1,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						op: StencilOpState {
 | 
					 | 
				
			||||||
							sfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dpfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dppass: StencilOp::Replace,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					}),
 | 
					 | 
				
			||||||
					color_mask: Some ((0, 0, 0, 0)),
 | 
					 | 
				
			||||||
					depth_mask: Some (0),
 | 
					 | 
				
			||||||
					stencil_mask: Some (255),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			// Draw lit ground
 | 
					 | 
				
			||||||
			Pass {
 | 
					 | 
				
			||||||
				shader: Some (&self.shader_diffuse),
 | 
					 | 
				
			||||||
				iso: IsoGlState {
 | 
					 | 
				
			||||||
					flags: hashmap! {
 | 
					 | 
				
			||||||
						gl::CULL_FACE => true,
 | 
					 | 
				
			||||||
						gl::DEPTH_TEST => true,
 | 
					 | 
				
			||||||
						gl::TEXTURE_2D => true,
 | 
					 | 
				
			||||||
						gl::STENCIL_TEST => true,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					front_face: Some (FrontFace::Cw),
 | 
					 | 
				
			||||||
					stencil: Some (StencilState {
 | 
					 | 
				
			||||||
						func: StencilFuncState {
 | 
					 | 
				
			||||||
							func: StencilFunc::NotEqual,
 | 
					 | 
				
			||||||
							reference: 0,
 | 
					 | 
				
			||||||
							mask: 1,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						op: StencilOpState {
 | 
					 | 
				
			||||||
							sfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dpfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dppass: StencilOp::Keep,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					}),
 | 
					 | 
				
			||||||
					color_mask: Some ((1, 1, 1, 1)),
 | 
					 | 
				
			||||||
					depth_mask: Some (1),
 | 
					 | 
				
			||||||
					stencil_mask: Some (0),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			// Draw unlit ground
 | 
					 | 
				
			||||||
			Pass {
 | 
					 | 
				
			||||||
				shader: Some (&self.shader_diffuse),
 | 
					 | 
				
			||||||
				iso: IsoGlState {
 | 
					 | 
				
			||||||
					flags: hashmap! {
 | 
					 | 
				
			||||||
						gl::CULL_FACE => true,
 | 
					 | 
				
			||||||
						gl::DEPTH_TEST => true,
 | 
					 | 
				
			||||||
						gl::TEXTURE_2D => true,
 | 
					 | 
				
			||||||
						gl::STENCIL_TEST => true,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					front_face: Some (FrontFace::Cw),
 | 
					 | 
				
			||||||
					stencil: Some (StencilState {
 | 
					 | 
				
			||||||
						func: StencilFuncState {
 | 
					 | 
				
			||||||
							func: StencilFunc::Equal,
 | 
					 | 
				
			||||||
							reference: 0,
 | 
					 | 
				
			||||||
							mask: 1,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
						op: StencilOpState {
 | 
					 | 
				
			||||||
							sfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dpfail: StencilOp::Keep,
 | 
					 | 
				
			||||||
							dppass: StencilOp::Keep,
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					}),
 | 
					 | 
				
			||||||
					color_mask: Some ((1, 1, 1, 1)),
 | 
					 | 
				
			||||||
					depth_mask: Some (1),
 | 
					 | 
				
			||||||
					stencil_mask: Some (0),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		];
 | 
					 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		passes [0].with (gl_state, || {
 | 
							passes.next ().unwrap ().with (gl_state, || {
 | 
				
			||||||
			glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32);
 | 
								glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32);
 | 
				
			||||||
			glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
 | 
								glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -730,7 +900,8 @@ impl GameGraphics {
 | 
				
			||||||
		use uniforms::*;
 | 
							use uniforms::*;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		// Draw the world except the ground plane
 | 
							// Draw the world except the ground plane
 | 
				
			||||||
		passes [1].with_shader (gl_state, |shader_vars| {
 | 
							passes.next ().unwrap ().with_shader (gl_state, self, 
 | 
				
			||||||
 | 
							|shader_vars| {
 | 
				
			||||||
			let unis = shader_vars.unis;
 | 
								let unis = shader_vars.unis;
 | 
				
			||||||
			let attrs = shader_vars.attrs;
 | 
								let attrs = shader_vars.attrs;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -759,19 +930,6 @@ impl GameGraphics {
 | 
				
			||||||
				i != self.grass_index
 | 
									i != self.grass_index
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			glezz::uniform_3fv (unis [&ALBEDO], &magenta);
 | 
					 | 
				
			||||||
			for arrow in arrows.iter () {
 | 
					 | 
				
			||||||
				let mvp = view_mat * arrow.model_mat;
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
				glezz::uniform_matrix_4fv (unis [&MVP], &mvp);
 | 
					 | 
				
			||||||
				let object_space_light = make_object_space_vec (&arrow.inv_model_mat, &light);
 | 
					 | 
				
			||||||
				let object_space_sky = make_object_space_vec (&arrow.inv_model_mat, &Vec3::from ((0.0, 0.0, 1.0)));
 | 
					 | 
				
			||||||
				glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
 | 
					 | 
				
			||||||
				glezz::uniform_3fv (unis [&OBJECT_SPACE_SKY], &object_space_sky);
 | 
					 | 
				
			||||||
				
 | 
					 | 
				
			||||||
				self.mesh_arrow.draw_all (attrs, |_| true);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			let draw_sky = true;
 | 
								let draw_sky = true;
 | 
				
			||||||
			if draw_sky {
 | 
								if draw_sky {
 | 
				
			||||||
				self.texture.bind ();
 | 
									self.texture.bind ();
 | 
				
			||||||
| 
						 | 
					@ -786,7 +944,8 @@ impl GameGraphics {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		// Draw shadows into stencil buffer
 | 
							// Draw shadows into stencil buffer
 | 
				
			||||||
		passes [2].with_shader (gl_state, |shader_vars| {
 | 
							passes.next ().unwrap ().with_shader (gl_state, self, 
 | 
				
			||||||
 | 
							|shader_vars| {
 | 
				
			||||||
			let unis = shader_vars.unis;
 | 
								let unis = shader_vars.unis;
 | 
				
			||||||
			let attrs = shader_vars.attrs;
 | 
								let attrs = shader_vars.attrs;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -813,7 +972,8 @@ impl GameGraphics {
 | 
				
			||||||
		let object_space_light = make_object_space_vec (&inverse_pumpkin, &light);
 | 
							let object_space_light = make_object_space_vec (&inverse_pumpkin, &light);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		// Draw unlit ground
 | 
							// Draw unlit ground
 | 
				
			||||||
		passes [3].with_shader (gl_state, |shader_vars| {
 | 
							passes.next ().unwrap ().with_shader (gl_state, self, 
 | 
				
			||||||
 | 
							|shader_vars| {
 | 
				
			||||||
			let unis = shader_vars.unis;
 | 
								let unis = shader_vars.unis;
 | 
				
			||||||
			let attrs = shader_vars.attrs;
 | 
								let attrs = shader_vars.attrs;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -835,16 +995,51 @@ impl GameGraphics {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		// Draw lit ground
 | 
							// Draw lit ground
 | 
				
			||||||
		passes [4].with_shader (gl_state, |shader_vars| {
 | 
							passes.next ().unwrap ().with_shader (gl_state, self, 
 | 
				
			||||||
 | 
							|shader_vars| {
 | 
				
			||||||
			let unis = shader_vars.unis;
 | 
								let unis = shader_vars.unis;
 | 
				
			||||||
			let attrs = shader_vars.attrs;
 | 
								let attrs = shader_vars.attrs;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
 | 
								glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
 | 
				
			||||||
			self.mesh_pitch.draw (attrs, self.grass_index);
 | 
								self.mesh_pitch.draw (attrs, self.grass_index);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// Clear depth
 | 
				
			||||||
 | 
							passes.next ().unwrap ().with (gl_state, || {
 | 
				
			||||||
 | 
								glezz::clear (gl::DEPTH_BUFFER_BIT);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// Draw arrows
 | 
				
			||||||
 | 
							passes.next ().unwrap ().with_shader (gl_state, self,
 | 
				
			||||||
 | 
							|shader_vars| {
 | 
				
			||||||
 | 
								let unis = &shader_vars.unis;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								glezz::uniform_3fv (unis [&MIN_BRIGHT], &black);
 | 
				
			||||||
 | 
								glezz::uniform_3fv (unis [&MIN_ALBEDO], &white);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								for arrow in arrows.iter () {
 | 
				
			||||||
 | 
									let mvp = view_mat * arrow.model_mat;
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									glezz::uniform_matrix_4fv (unis [&MVP], &mvp);
 | 
				
			||||||
 | 
									let object_space_light = make_object_space_vec (&arrow.inv_model_mat, &light);
 | 
				
			||||||
 | 
									let object_space_sky = make_object_space_vec (&arrow.inv_model_mat, &Vec3::from ((0.0, 0.0, 1.0)));
 | 
				
			||||||
 | 
									glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
 | 
				
			||||||
 | 
									glezz::uniform_3fv (unis [&OBJECT_SPACE_SKY], &object_space_sky);
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									glezz::uniform_3fv (unis [&ALBEDO], &arrow.color);
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									self.mesh_arrow.draw_all (shader_vars.attrs, |_| true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive (Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					enum UserControl {
 | 
				
			||||||
 | 
						Camera,
 | 
				
			||||||
 | 
						Wind,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main () {
 | 
					fn main () {
 | 
				
			||||||
	let sdl_context = sdl2::init ().unwrap ();
 | 
						let sdl_context = sdl2::init ().unwrap ();
 | 
				
			||||||
	let video_subsystem = sdl_context.video ().unwrap ();
 | 
						let video_subsystem = sdl_context.video ().unwrap ();
 | 
				
			||||||
| 
						 | 
					@ -871,16 +1066,13 @@ fn main () {
 | 
				
			||||||
	let graphics = GameGraphics::new ();
 | 
						let graphics = GameGraphics::new ();
 | 
				
			||||||
	let mut gl_state = Default::default ();
 | 
						let mut gl_state = Default::default ();
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						let mut user_control = UserControl::Camera;
 | 
				
			||||||
 | 
						let mut graphics_frames = 0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	let mut event_pump = sdl_context.event_pump ().unwrap ();
 | 
						let mut event_pump = sdl_context.event_pump ().unwrap ();
 | 
				
			||||||
	'running: loop {
 | 
						'running: loop {
 | 
				
			||||||
		let frames_to_do = time_step.step ();
 | 
							let frames_to_do = time_step.step ();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let controller = ControllerState::from_sdl_keyboard (&event_pump.keyboard_state ());
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		for _ in 0..frames_to_do {
 | 
					 | 
				
			||||||
			state.step (&controller);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		let _mouse = event_pump.mouse_state ();
 | 
							let _mouse = event_pump.mouse_state ();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		for event in event_pump.poll_iter() {
 | 
							for event in event_pump.poll_iter() {
 | 
				
			||||||
| 
						 | 
					@ -889,27 +1081,55 @@ fn main () {
 | 
				
			||||||
				Event::KeyDown { keycode: Some (Keycode::Escape), .. } => {
 | 
									Event::KeyDown { keycode: Some (Keycode::Escape), .. } => {
 | 
				
			||||||
					break 'running
 | 
										break 'running
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
									Event::KeyDown { keycode: Some (Keycode::C), .. } => {
 | 
				
			||||||
 | 
										user_control = UserControl::Camera;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Event::KeyDown { keycode: Some (Keycode::W), .. } => {
 | 
				
			||||||
 | 
										user_control = UserControl::Wind;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
				_ => (),
 | 
									_ => (),
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
							let controller = ControllerState::from_sdl_keyboard (&event_pump.keyboard_state ());
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							for _ in 0..frames_to_do {
 | 
				
			||||||
 | 
								state.step (&controller, &user_control);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let gravity = (0.0, 0.0, -1.0).into ();
 | 
				
			||||||
 | 
							let wind = state.wind.to_vec3 () * -1.0;
 | 
				
			||||||
 | 
							let origin: Vec3 = (0.0, 0.0, 1.35).into ();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let control_flash = if graphics_frames % 16 >= 8 {
 | 
				
			||||||
 | 
								(1.0, 1.0, 1.0).into ()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								(1.0, 0.0, 0.0).into ()
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		let arrows = vec![
 | 
							let arrows = vec![
 | 
				
			||||||
			Arrow {
 | 
								Arrow {
 | 
				
			||||||
				origin: (0.0, 0.0, 1.0).into (),
 | 
									origin: (0.0, 0.0, 1.35).into (),
 | 
				
			||||||
				direction: (0.0, 0.0, 1.0).into (),
 | 
									direction: gravity,
 | 
				
			||||||
 | 
									color: (1.0, 0.5, 0.5).into (),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Arrow {
 | 
								Arrow {
 | 
				
			||||||
				origin: (1.0, 0.0, 1.0).into (),
 | 
									origin: origin + wind * -2.0,
 | 
				
			||||||
				direction: (1.0, 0.0, 0.0).into (),
 | 
									direction: wind,
 | 
				
			||||||
			},
 | 
									color: if user_control == UserControl::Wind {
 | 
				
			||||||
			Arrow {
 | 
										control_flash
 | 
				
			||||||
				origin: (0.0, 1.0, 1.0).into (),
 | 
									}
 | 
				
			||||||
				direction: (0.0, 1.0, 0.0).into (),
 | 
									else {
 | 
				
			||||||
 | 
										(1.0, 0.5, 1.0).into ()
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		];
 | 
							];
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let renderable_arrows: Vec <_> = arrows.iter ().map (|arrow| {
 | 
							let renderable_arrows: Vec <_> = arrows.iter ().map (|arrow| {
 | 
				
			||||||
			let d = arrow.direction;
 | 
								let dir_len = arrow.direction.length ();
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								let d = arrow.direction / dir_len;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			let up: Vec3 = if d.z () > 0.5 {
 | 
								let up: Vec3 = if d.z () > 0.5 {
 | 
				
			||||||
				(-1.0, 0.0, 0.0)
 | 
									(-1.0, 0.0, 0.0)
 | 
				
			||||||
| 
						 | 
					@ -932,9 +1152,11 @@ fn main () {
 | 
				
			||||||
			dir_mat.set_y_axis ((up.x (), up.y (), up.z (), 0.0).into ());
 | 
								dir_mat.set_y_axis ((up.x (), up.y (), up.z (), 0.0).into ());
 | 
				
			||||||
			dir_mat.set_z_axis ((d.x (), d.y (), d.z (), 0.0).into ());
 | 
								dir_mat.set_z_axis ((d.x (), d.y (), d.z (), 0.0).into ());
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
 | 
								let s = dir_len * 0.0625;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			let model_mat =
 | 
								let model_mat =
 | 
				
			||||||
			Mat4::from_translation (arrow.origin) *
 | 
								Mat4::from_translation (arrow.origin) *
 | 
				
			||||||
			Mat4::from_scale ((0.125, 0.125, 0.125).into ()) *
 | 
								Mat4::from_scale ((s, s, s).into ()) *
 | 
				
			||||||
			dir_mat;
 | 
								dir_mat;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			let inv_model_mat = model_mat.inverse ();
 | 
								let inv_model_mat = model_mat.inverse ();
 | 
				
			||||||
| 
						 | 
					@ -942,6 +1164,7 @@ fn main () {
 | 
				
			||||||
			RenderableArrow {
 | 
								RenderableArrow {
 | 
				
			||||||
				model_mat,
 | 
									model_mat,
 | 
				
			||||||
				inv_model_mat,
 | 
									inv_model_mat,
 | 
				
			||||||
 | 
									color: arrow.color,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}).collect ();
 | 
							}).collect ();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -950,6 +1173,7 @@ fn main () {
 | 
				
			||||||
		graphics.draw (&state, &mut gl_state, &renderable_arrows);
 | 
							graphics.draw (&state, &mut gl_state, &renderable_arrows);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		window.gl_swap_window ();
 | 
							window.gl_swap_window ();
 | 
				
			||||||
 | 
							graphics_frames += 1;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		std::thread::sleep (Duration::from_millis (15));
 | 
							std::thread::sleep (Duration::from_millis (15));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +97,12 @@ pub fn stencil_mask (v: u32) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn depth_func (v: u32) {
 | 
				
			||||||
 | 
						unsafe {
 | 
				
			||||||
 | 
							gl::DepthFunc (v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// More abstract things below here
 | 
					// More abstract things below here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue