diff --git a/src/bin/pumpkin.rs b/src/bin/pumpkin.rs
index e4727e2..5c38613 100644
--- a/src/bin/pumpkin.rs
+++ b/src/bin/pumpkin.rs
@@ -1,7 +1,6 @@
#[macro_use]
extern crate maplit;
-use float_ord::FloatOrd;
use glam::{Mat4, Quat, Vec3, Vec4};
use sdl2::event::Event;
@@ -13,10 +12,9 @@ use std::time::{Duration};
use opengl_rust::*;
-use file::load_small_file;
-use iqm::Model;
-use renderable_model::RenderableModel;
-use shader::{ShaderProgram, ShaderObject};
+use gl_state::*;
+use renderable_model::*;
+use shader::*;
use shader_closure::*;
use texture::Texture;
use timestep::TimeStep;
@@ -190,7 +188,7 @@ struct FlightState {
}
impl FlightState {
- pub fn handle_event (&mut self, event: &sdl2::event::Event) {
+ pub fn handle_event (&mut self, _event: &sdl2::event::Event) {
}
@@ -202,10 +200,13 @@ impl FlightState {
let nose = airplane.ori.mul_vec3 ((0.0, 1.0, 0.0).into ());
let speed = airplane.vel.length ();
// Different from nose since planes are always drifting
- let direction = match speed {
- 0.0 => Vec3::from ((0.0, 0.0, 0.0)),
- _ => airplane.vel * (1.0 / speed),
+ let direction = if speed == 0.0 {
+ Vec3::from ((0.0, 0.0, 0.0))
+ }
+ else {
+ airplane.vel * (1.0 / speed)
};
+
let object_space_dir = airplane.ori.conjugate ().mul_vec3 (direction);
// Forces
@@ -353,24 +354,6 @@ fn make_object_space_vec (inverse_model_mat: &Mat4, world_space_vec: &Vec3)
Vec3::from ((v4.x (), v4.y (), v4.z ()))
}
-fn renderable_from_iqm_file
(filename: P) -> RenderableModel
-where P: AsRef
-{
- let data = load_small_file (filename, 1024 * 1024).unwrap ();
- let model = Model::from_slice (&data).unwrap ();
-
- RenderableModel::from_iqm (&model)
-}
-
-fn shader_from_files (vert: P, frag: P) -> ShaderProgram
-where P: AsRef
-{
- let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, vert).unwrap ();
- let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, frag).unwrap ();
-
- ShaderProgram::new (&vert_shader, &frag_shader).unwrap ()
-}
-
struct Arrow {
origin: Vec3,
direction: Vec3,
@@ -383,344 +366,6 @@ struct RenderableArrow {
color: Vec3,
}
-#[derive (Copy, Clone, PartialEq, Eq)]
-pub enum FrontFace {
- Cw,
- Ccw,
-}
-
-impl From for u32 {
- fn from (v: FrontFace) -> Self {
- use FrontFace::*;
- {
- use gl::*;
- match v {
- Cw => CW,
- Ccw => CCW,
- }
- }
- }
-}
-
-#[derive (Copy, Clone, PartialEq, Eq)]
-pub enum StencilOp {
- Keep,
- Zero,
- Replace,
- Incr,
- Decr,
- Invert,
- IncrWrap,
- DecrWrap,
-}
-
-impl From for u32 {
- fn from (v: StencilOp) -> Self {
- use StencilOp::*;
- {
- use gl::*;
- match v {
- Keep => KEEP,
- Zero => ZERO,
- Replace => REPLACE,
- Incr => INCR,
- Decr => DECR,
- Invert => INVERT,
- IncrWrap => INCR_WRAP,
- DecrWrap => DECR_WRAP,
- }
- }
- }
-}
-
-#[derive (Copy, Clone, PartialEq, Eq)]
-pub enum StencilFunc {
- Never,
- Always,
- Less,
- LessEqual,
- Equal,
- Greater,
- GreaterEqual,
- NotEqual,
-}
-
-impl From for u32 {
- fn from (v: StencilFunc) -> Self {
- use StencilFunc::*;
- {
- 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)]
-pub enum DepthFunc {
- Never,
- Always,
- Less,
- LessEqual,
- Equal,
- Greater,
- GreaterEqual,
- NotEqual,
-}
-
-impl From 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)]
-pub struct StencilOpState {
- sfail: StencilOp,
- dpfail: StencilOp,
- dppass: StencilOp,
-}
-
-#[derive (Copy, Clone, PartialEq, Eq)]
-pub struct StencilFuncState {
- func: StencilFunc,
- reference: i32,
- mask: u32,
-}
-
-#[derive (Copy, Clone, PartialEq, Eq)]
-pub struct StencilState {
- op: StencilOpState,
- func: StencilFuncState,
-}
-
-// These are POD where no extra data is needed
-// to safely use the flags / numbers
-
-pub struct IsoGlState {
- shader_id: Option ,
-
- flags: HashMap ,
- front_face: Option ,
- stencil: Option ,
- depth_func: Option ,
-
- color_mask: Option <(u8, u8, u8, u8)>,
- depth_mask: Option ,
- stencil_mask: Option ,
-}
-
-impl std::default::Default for IsoGlState {
- fn default () -> Self {
- Self {
- shader_id: None,
- flags: hashmap! {},
- front_face: None,
- stencil: None,
- depth_func: None,
- color_mask: None,
- depth_mask: None,
- stencil_mask: None,
- }
- }
-}
-
-// These are POD IDs or hashes of non-POD data
-
-pub struct NonIsoGlState {
-}
-
-impl std::default::Default for NonIsoGlState {
- fn default () -> Self {
- Self {
- }
- }
-}
-
-pub struct GlState {
- iso: IsoGlState,
- non_iso: NonIsoGlState,
-}
-
-impl std::default::Default for GlState {
- fn default () -> Self {
- Self {
- iso: Default::default (),
- non_iso: Default::default (),
- }
- }
-}
-
-pub struct Pass {
- // In the context of a Pass, "None" means "Don't care"
-
- iso: IsoGlState,
-}
-
-impl Pass {
- pub fn apply_diff (&self, old_state: &mut IsoGlState) {
- let state = &self.iso;
-
- let mut flag_elision_count = 0;
-
- for (flag, value) in state.flags.iter () {
- let old_entry = old_state.flags.entry (*flag);
- if match &old_entry {
- hash_map::Entry::Vacant (_) => true,
- hash_map::Entry::Occupied (o) => o.get () != value,
- } {
- if *value {
- glezz::enable (*flag);
- }
- else {
- glezz::disable (*flag);
- }
-
- old_entry.or_insert (*value);
- }
- else {
- flag_elision_count += 1;
- }
- }
- if flag_elision_count > 0 {
- //println! ("Elided {} flags", flag_elision_count);
- }
-
- if let Some (v) = &state.front_face {
- if old_state.front_face != state.front_face {
- glezz::front_face ((*v).into ());
- old_state.front_face = state.front_face;
- }
- else {
- //println! ("Elided front_face ()");
- }
- }
-
- if let Some (v) = &state.stencil {
- if old_state.stencil != state.stencil {
- let func = &v.func;
- unsafe {
- gl::StencilFunc (
- func.func.into (),
- func.reference.into (),
- func.mask.into ()
- );
- }
-
- let op = &v.op;
- unsafe {
- gl::StencilOp (
- op.sfail.into (),
- op.dpfail.into (),
- op.dppass.into ()
- );
- }
- }
- else {
- //println! ("Elided stencil state");
- }
- }
-
- 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 old_state.color_mask != state.color_mask {
- glezz::color_mask (*r, *g, *b, *a);
- old_state.color_mask = state.color_mask;
- }
- else {
- //println! ("Elided color_mask ()");
- }
- }
-
- if let Some (v) = &state.depth_mask {
- if old_state.depth_mask != state.depth_mask {
- glezz::depth_mask (*v);
- old_state.depth_mask = state.depth_mask;
- }
- else {
- //println! ("Elided depth_mask ()");
- }
- }
-
- if let Some (v) = &state.stencil_mask {
- if old_state.stencil_mask != state.stencil_mask {
- glezz::stencil_mask (*v);
- old_state.stencil_mask = state.stencil_mask;
- }
- else {
- //println! ("Elided stencil_mask ()");
- }
- }
- }
-
- pub fn apply_slow (&self) {
- let mut iso = IsoGlState::default ();
-
- self.apply_diff (&mut iso);
- }
-
- pub fn with (&self, gl_state: &mut GlState, callback: F)
- where F: Fn ()
- {
- self.apply_diff (&mut gl_state.iso);
- callback ();
- }
-
- pub fn with_shader (
- &self,
- gl_state: &mut GlState,
- shader_component: &S,
- callback: F
- )
- where F: Fn (BorrowedShaderVars), S: ShaderLookup
- {
- if let Some (s) = self.iso.shader_id {
- self.apply_diff (&mut gl_state.iso);
- shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
- callback (shader_vars);
- });
- gl_state.iso.shader_id = Some (s);
- }
- else {
- panic! ("Called with_shader on a pass with no shader");
- }
- }
-}
-
-pub trait ShaderLookup {
- fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
-}
-
struct GameGraphics {
passes: Vec ,
@@ -1133,7 +778,7 @@ impl GameGraphics {
let gunmetal_grey = color_from_255 ((133.0, 149.0, 161.0));
glezz::uniform_3fv (unis [&ALBEDO], &gunmetal_grey);
- self.mesh_airplane.draw_all (attrs, |i| {
+ self.mesh_airplane.draw_all (attrs, |_i| {
true
});
diff --git a/src/gl_state.rs b/src/gl_state.rs
new file mode 100644
index 0000000..846dad7
--- /dev/null
+++ b/src/gl_state.rs
@@ -0,0 +1,338 @@
+use std::collections::*;
+
+use crate::glezz;
+use crate::shader_closure::*;
+
+#[derive (Copy, Clone, PartialEq, Eq)]
+pub enum FrontFace {
+ Cw,
+ Ccw,
+}
+
+impl From for u32 {
+ fn from (v: FrontFace) -> Self {
+ use FrontFace::*;
+ {
+ use gl::*;
+ match v {
+ Cw => CW,
+ Ccw => CCW,
+ }
+ }
+ }
+}
+
+#[derive (Copy, Clone, PartialEq, Eq)]
+pub enum StencilOp {
+ Keep,
+ Zero,
+ Replace,
+ Incr,
+ Decr,
+ Invert,
+ IncrWrap,
+ DecrWrap,
+}
+
+impl From for u32 {
+ fn from (v: StencilOp) -> Self {
+ use StencilOp::*;
+ {
+ use gl::*;
+ match v {
+ Keep => KEEP,
+ Zero => ZERO,
+ Replace => REPLACE,
+ Incr => INCR,
+ Decr => DECR,
+ Invert => INVERT,
+ IncrWrap => INCR_WRAP,
+ DecrWrap => DECR_WRAP,
+ }
+ }
+ }
+}
+
+#[derive (Copy, Clone, PartialEq, Eq)]
+pub enum StencilFunc {
+ Never,
+ Always,
+ Less,
+ LessEqual,
+ Equal,
+ Greater,
+ GreaterEqual,
+ NotEqual,
+}
+
+impl From for u32 {
+ fn from (v: StencilFunc) -> Self {
+ use StencilFunc::*;
+ {
+ 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)]
+pub enum DepthFunc {
+ Never,
+ Always,
+ Less,
+ LessEqual,
+ Equal,
+ Greater,
+ GreaterEqual,
+ NotEqual,
+}
+
+impl From 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)]
+pub struct StencilOpState {
+ pub sfail: StencilOp,
+ pub dpfail: StencilOp,
+ pub dppass: StencilOp,
+}
+
+#[derive (Copy, Clone, PartialEq, Eq)]
+pub struct StencilFuncState {
+ pub func: StencilFunc,
+ pub reference: i32,
+ pub mask: u32,
+}
+
+#[derive (Copy, Clone, PartialEq, Eq)]
+pub struct StencilState {
+ pub op: StencilOpState,
+ pub func: StencilFuncState,
+}
+
+// These are POD where no extra data is needed
+// to safely use the flags / numbers
+
+pub struct IsoGlState {
+ pub shader_id: Option ,
+
+ pub flags: HashMap ,
+ pub front_face: Option ,
+ pub stencil: Option ,
+ pub depth_func: Option ,
+
+ pub color_mask: Option <(u8, u8, u8, u8)>,
+ pub depth_mask: Option ,
+ pub stencil_mask: Option ,
+}
+
+impl std::default::Default for IsoGlState {
+ fn default () -> Self {
+ Self {
+ shader_id: None,
+ flags: hashmap! {},
+ front_face: None,
+ stencil: None,
+ depth_func: None,
+ color_mask: None,
+ depth_mask: None,
+ stencil_mask: None,
+ }
+ }
+}
+
+// These are POD IDs or hashes of non-POD data
+
+pub struct NonIsoGlState {
+}
+
+impl std::default::Default for NonIsoGlState {
+ fn default () -> Self {
+ Self {
+ }
+ }
+}
+
+pub struct GlState {
+ pub iso: IsoGlState,
+ pub non_iso: NonIsoGlState,
+}
+
+impl std::default::Default for GlState {
+ fn default () -> Self {
+ Self {
+ iso: Default::default (),
+ non_iso: Default::default (),
+ }
+ }
+}
+
+pub struct Pass {
+ // In the context of a Pass, "None" means "Don't care"
+
+ pub iso: IsoGlState,
+}
+
+impl Pass {
+ pub fn apply_diff (&self, old_state: &mut IsoGlState) {
+ let state = &self.iso;
+
+ let mut flag_elision_count = 0;
+
+ for (flag, value) in state.flags.iter () {
+ let old_entry = old_state.flags.entry (*flag);
+ if match &old_entry {
+ hash_map::Entry::Vacant (_) => true,
+ hash_map::Entry::Occupied (o) => o.get () != value,
+ } {
+ if *value {
+ glezz::enable (*flag);
+ }
+ else {
+ glezz::disable (*flag);
+ }
+
+ old_entry.or_insert (*value);
+ }
+ else {
+ flag_elision_count += 1;
+ }
+ }
+ if flag_elision_count > 0 {
+ //println! ("Elided {} flags", flag_elision_count);
+ }
+
+ if let Some (v) = &state.front_face {
+ if old_state.front_face != state.front_face {
+ glezz::front_face ((*v).into ());
+ old_state.front_face = state.front_face;
+ }
+ else {
+ //println! ("Elided front_face ()");
+ }
+ }
+
+ if let Some (v) = &state.stencil {
+ if old_state.stencil != state.stencil {
+ let func = &v.func;
+ unsafe {
+ gl::StencilFunc (
+ func.func.into (),
+ func.reference.into (),
+ func.mask.into ()
+ );
+ }
+
+ let op = &v.op;
+ unsafe {
+ gl::StencilOp (
+ op.sfail.into (),
+ op.dpfail.into (),
+ op.dppass.into ()
+ );
+ }
+ }
+ else {
+ //println! ("Elided stencil state");
+ }
+ }
+
+ 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 old_state.color_mask != state.color_mask {
+ glezz::color_mask (*r, *g, *b, *a);
+ old_state.color_mask = state.color_mask;
+ }
+ else {
+ //println! ("Elided color_mask ()");
+ }
+ }
+
+ if let Some (v) = &state.depth_mask {
+ if old_state.depth_mask != state.depth_mask {
+ glezz::depth_mask (*v);
+ old_state.depth_mask = state.depth_mask;
+ }
+ else {
+ //println! ("Elided depth_mask ()");
+ }
+ }
+
+ if let Some (v) = &state.stencil_mask {
+ if old_state.stencil_mask != state.stencil_mask {
+ glezz::stencil_mask (*v);
+ old_state.stencil_mask = state.stencil_mask;
+ }
+ else {
+ //println! ("Elided stencil_mask ()");
+ }
+ }
+ }
+
+ pub fn apply_slow (&self) {
+ let mut iso = IsoGlState::default ();
+
+ self.apply_diff (&mut iso);
+ }
+
+ pub fn with (&self, gl_state: &mut GlState, callback: F)
+ where F: Fn ()
+ {
+ self.apply_diff (&mut gl_state.iso);
+ callback ();
+ }
+
+ pub fn with_shader (
+ &self,
+ gl_state: &mut GlState,
+ shader_component: &S,
+ callback: F
+ )
+ where F: Fn (BorrowedShaderVars), S: ShaderLookup
+ {
+ if let Some (s) = self.iso.shader_id {
+ self.apply_diff (&mut gl_state.iso);
+ shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
+ callback (shader_vars);
+ });
+ gl_state.iso.shader_id = Some (s);
+ }
+ else {
+ panic! ("Called with_shader on a pass with no shader");
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index f9b9cdd..f4608be 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,12 @@
#[macro_use]
extern crate iota;
+#[macro_use]
+extern crate maplit;
+
pub mod file;
pub mod glezz;
+pub mod gl_state;
pub mod gpu_buffers;
pub mod iqm;
pub mod renderable_model;
diff --git a/src/renderable_model.rs b/src/renderable_model.rs
index 316add7..52a0990 100644
--- a/src/renderable_model.rs
+++ b/src/renderable_model.rs
@@ -142,3 +142,12 @@ impl RenderableModel {
self.meshes.len ()
}
}
+
+pub fn renderable_from_iqm_file (filename: P) -> RenderableModel
+where P: AsRef
+{
+ let data = crate::file::load_small_file (filename, 1024 * 1024).unwrap ();
+ let model = crate::iqm::Model::from_slice (&data).unwrap ();
+
+ RenderableModel::from_iqm (&model)
+}
diff --git a/src/shader.rs b/src/shader.rs
index 207309c..6e8aae3 100644
--- a/src/shader.rs
+++ b/src/shader.rs
@@ -197,3 +197,12 @@ impl Drop for ShaderProgram {
}
}
}
+
+pub fn shader_from_files (vert: P, frag: P) -> ShaderProgram
+where P: AsRef
+{
+ let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, vert).unwrap ();
+ let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, frag).unwrap ();
+
+ ShaderProgram::new (&vert_shader, &frag_shader).unwrap ()
+}
diff --git a/src/shader_closure.rs b/src/shader_closure.rs
index 6141979..b3e68dc 100644
--- a/src/shader_closure.rs
+++ b/src/shader_closure.rs
@@ -87,3 +87,7 @@ impl ShaderClosure {
});
}
}
+
+pub trait ShaderLookup {
+ fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
+}