physics are hooked up but edge collisions are not working

main
_ 2021-12-18 23:03:02 +00:00
parent 47e835005b
commit 8e7101dccd
5 changed files with 93 additions and 24 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/quic_server.crt
/target /target
**/*.rs.bk **/*.rs.bk

BIN
cube.iqm Normal file

Binary file not shown.

BIN
sphere.iqm Normal file

Binary file not shown.

View File

@ -8,6 +8,7 @@ use maplit::hashmap;
use opengl_rust::{ use opengl_rust::{
prelude::*, prelude::*,
gl_state::*, gl_state::*,
physics::PhysicsBody,
renderable_model::{ renderable_model::{
attributes, attributes,
RenderableModel, RenderableModel,
@ -30,6 +31,11 @@ pub const
} }
} }
#[derive (Default)]
struct GameState {
player: PhysicsBody,
}
struct GameGraphics { struct GameGraphics {
passes: Vec <Pass>, passes: Vec <Pass>,
@ -38,6 +44,7 @@ struct GameGraphics {
mesh_cube: RenderableModel, mesh_cube: RenderableModel,
mesh_sky: RenderableModel, mesh_sky: RenderableModel,
mesh_sphere: RenderableModel,
text_stream: TriangleStream, text_stream: TriangleStream,
@ -53,6 +60,7 @@ impl ShaderLookup for GameGraphics {
impl GameGraphics { impl GameGraphics {
fn draw ( fn draw (
&self, &self,
state: &GameState,
gl_state: &mut GlState, gl_state: &mut GlState,
) { ) {
use uniforms as u; use uniforms as u;
@ -71,7 +79,7 @@ impl GameGraphics {
let world_model_mat = Mat4::IDENTITY; let world_model_mat = Mat4::IDENTITY;
self.passes [0].with (gl_state, || { self.passes [0].with (gl_state, || {
glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32); glezz::clear_color (0.5f32, 0.5f32, 0.5f32, 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);
}); });
@ -80,14 +88,21 @@ impl GameGraphics {
let unis = shader_vars.unis; let unis = shader_vars.unis;
{ {
let mvp = view_mat * Mat4::IDENTITY; let mvp = view_mat *
Mat4::from_translation (state.player.pos) *
Mat4::from_scale ((0.5, 0.5, 0.5).into ());
glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp);
//let object_space_light = make_object_space_vec (&inverse_truck, &light); self.mesh_sphere.draw_all (attrs, |_| {
//let object_space_sky = make_object_space_vec (&inverse_truck, &Vec3::from ((0.0, 0.0, 1.0))); true
});
//glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light); }
//glezz::uniform_3fv (unis [&OBJECT_SPACE_SKY], &object_space_sky);
{
let mvp = view_mat *
Mat4::from_scale ((4.0, 4.0, 1.0).into ()) *
Mat4::from_translation ((0.0, 0.0, -2.0).into ());
glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp);
self.mesh_cube.draw_all (attrs, |_| { self.mesh_cube.draw_all (attrs, |_| {
true true
@ -104,7 +119,7 @@ impl GameGraphics {
glezz::uniform_3fv (unis [&u::MIN_ALBEDO], &black); glezz::uniform_3fv (unis [&u::MIN_ALBEDO], &black);
glezz::uniform_1i (unis [&u::TEXTURE], 0); glezz::uniform_1i (unis [&u::TEXTURE], 0);
self.mesh_sky.draw_all (attrs, |_| true); // self.mesh_sky.draw_all (attrs, |_| true);
} }
}); });
} }
@ -169,6 +184,7 @@ async fn main () -> Result <()> {
let mesh_cube = renderable_from_iqm_file ("cube.iqm"); let mesh_cube = renderable_from_iqm_file ("cube.iqm");
let mesh_sky = renderable_from_iqm_file ("sky-sphere.iqm"); let mesh_sky = renderable_from_iqm_file ("sky-sphere.iqm");
let mesh_sphere = renderable_from_iqm_file ("sphere.iqm");
let passes = vec![ let passes = vec![
// Clear everything // Clear everything
@ -185,7 +201,7 @@ async fn main () -> Result <()> {
(gl::TEXTURE_2D, true), (gl::TEXTURE_2D, true),
(gl::STENCIL_TEST, false), (gl::STENCIL_TEST, false),
].into_iter ()) ].into_iter ())
.front_face (FrontFace::Cw) .front_face (FrontFace::Ccw)
.color_mask ([1, 1, 1, 1]) .color_mask ([1, 1, 1, 1])
.depth_mask (1) .depth_mask (1)
.clone (), .clone (),
@ -221,6 +237,7 @@ async fn main () -> Result <()> {
let graphics = GameGraphics { let graphics = GameGraphics {
mesh_cube, mesh_cube,
mesh_sky, mesh_sky,
mesh_sphere,
passes, passes,
shader_lookup, shader_lookup,
shaders, shaders,
@ -229,6 +246,35 @@ async fn main () -> Result <()> {
}; };
let mut gl_state = Default::default (); let mut gl_state = Default::default ();
let mut game_state = GameState::default ();
let phys_params = opengl_rust::physics::Params {
dt: 1.0 / 60.0,
gravity: (0.0, 0.0, -0.25).into (),
margin: 0.00125,
};
let phys_world: Vec <_> = vec! [
(
(-4.0, -4.0, -1.0),
(-4.0, 4.0, -1.0),
(4.0, -4.0, -1.0),
),
(
(4.0, 4.0, -1.0),
(4.0, -4.0, -1.0),
(-4.0, 4.0, -1.0),
),
].into_iter ()
.map (|(v0, v1, v2)| {
opengl_rust::physics::Triangle {
verts: [
v0.into (),
v1.into (),
v2.into (),
],
}
})
.collect ();
let player_speed = 2.0;
'running: loop { 'running: loop {
let _frames_to_do = time_step.step (); let _frames_to_do = time_step.step ();
@ -239,13 +285,35 @@ async fn main () -> Result <()> {
Event::KeyDown { keycode: Some (Keycode::Escape), .. } => { Event::KeyDown { keycode: Some (Keycode::Escape), .. } => {
break 'running break 'running
}, },
Event::KeyDown { keycode: Some (Keycode::R), .. } => {
game_state = Default::default ();
},
_ => (), _ => (),
} }
} }
let kb_state = event_pump.keyboard_state ();
game_state.player.vel.x = 0.0;
game_state.player.vel.y = 0.0;
if kb_state.is_scancode_pressed (Scancode::Left) {
game_state.player.vel.x -= player_speed;
}
if kb_state.is_scancode_pressed (Scancode::Right) {
game_state.player.vel.x += player_speed;
}
if kb_state.is_scancode_pressed (Scancode::Up) {
game_state.player.vel.y += player_speed;
}
if kb_state.is_scancode_pressed (Scancode::Down) {
game_state.player.vel.y -= player_speed;
}
game_state.player = opengl_rust::physics::step (&phys_params, &phys_world, 0.5, &game_state.player).body;
window.gl_make_current (&gl_ctx).unwrap (); window.gl_make_current (&gl_ctx).unwrap ();
graphics.draw (&mut gl_state); graphics.draw (&game_state, &mut gl_state);
window.gl_swap_window (); window.gl_swap_window ();
graphics_frames += 1; graphics_frames += 1;

View File

@ -1,10 +1,10 @@
use glam::{Vec2, Vec3}; use glam::{Vec2, Vec3};
use partial_min_max::{min, max}; use partial_min_max::{min, max};
#[derive (Debug, PartialEq)] #[derive (Debug, Default, PartialEq)]
pub struct PhysicsBody { pub struct PhysicsBody {
pos: Vec3, pub pos: Vec3,
vel: Vec3, pub vel: Vec3,
} }
#[derive (Debug, PartialEq)] #[derive (Debug, PartialEq)]
@ -16,7 +16,7 @@ pub struct PhysicsResult {
#[derive (Copy, Clone)] #[derive (Copy, Clone)]
pub struct Triangle { pub struct Triangle {
verts: [Vec3; 3], pub verts: [Vec3; 3],
} }
fn vec_min (a: &Vec3, b: &Vec3) -> Vec3 { fn vec_min (a: &Vec3, b: &Vec3) -> Vec3 {
@ -193,6 +193,7 @@ pub fn get_candidate (world: &[Triangle], p0: Vec3, p1: Vec3, radius: f32)
let denom = (p1 - p0).length (); let denom = (p1 - p0).length ();
let t_times_denom = a_ray.x - discriminant.sqrt (); let t_times_denom = a_ray.x - discriminant.sqrt ();
let t = t_times_denom / denom;
if t_times_denom < 0.0 || t_times_denom > denom { if t_times_denom < 0.0 || t_times_denom > denom {
// The cylinder is along the line, // The cylinder is along the line,
@ -204,11 +205,10 @@ pub fn get_candidate (world: &[Triangle], p0: Vec3, p1: Vec3, radius: f32)
let p_impact_times_denom = p0 * (denom - t_times_denom) + p1 * (t_times_denom); let p_impact_times_denom = p0 * (denom - t_times_denom) + p1 * (t_times_denom);
let p_impact = p_impact_times_denom / denom; let p_impact = p_impact_times_denom / denom;
let impact_along_cylinder_times_denom = Vec3::dot (cylinder_axis, p_impact_times_denom); let impact_along_cylinder = Vec3::dot (cylinder_axis, p_impact);
let impact_along_cylinder = impact_along_cylinder_times_denom / denom;
let a_along_cylinder = Vec3::dot (cylinder_axis, a); let a_along_cylinder = Vec3::dot (cylinder_axis, a);
if impact_along_cylinder_times_denom < a_along_cylinder * denom || impact_along_cylinder_times_denom > Vec3::dot (cylinder_axis, b) * denom if impact_along_cylinder < a_along_cylinder || impact_along_cylinder > Vec3::dot (cylinder_axis, b)
{ {
// The infinite cylinder is on the line segment, // The infinite cylinder is on the line segment,
// but the finite cylinder is not. // but the finite cylinder is not.
@ -279,12 +279,12 @@ pub fn get_candidate (world: &[Triangle], p0: Vec3, p1: Vec3, radius: f32)
} }
pub struct Params { pub struct Params {
dt: f32, pub dt: f32,
gravity: Vec3, pub gravity: Vec3,
margin: f32, pub margin: f32,
} }
pub fn physics_step ( pub fn step (
params: &Params, world: &[Triangle], params: &Params, world: &[Triangle],
radius: f32, input: &PhysicsBody, radius: f32, input: &PhysicsBody,
) -> PhysicsResult ) -> PhysicsResult
@ -447,7 +447,7 @@ mod test {
}, },
), ),
] { ] {
let a = physics_step (&params, &world, radius, &body_before); let a = step (&params, &world, radius, &body_before);
assert! (a.body.pos.distance_squared (e.body.pos) <= 0.00125); assert! (a.body.pos.distance_squared (e.body.pos) <= 0.00125);
assert! (a.body.vel.distance_squared (e.body.vel) <= 0.00125); assert! (a.body.vel.distance_squared (e.body.vel) <= 0.00125);
@ -480,7 +480,7 @@ mod test {
}, },
); );
let a = physics_step (&params, &world, radius, &body_before); let a = step (&params, &world, radius, &body_before);
let e = PhysicsResult { let e = PhysicsResult {
body: PhysicsBody { body: PhysicsBody {
@ -503,7 +503,7 @@ mod test {
vel: (0.0, 0.0, 0.0).into (), vel: (0.0, 0.0, 0.0).into (),
}; };
let a = physics_step (&params, &world, radius, &body_before); let a = step (&params, &world, radius, &body_before);
let e = PhysicsResult { let e = PhysicsResult {
body: PhysicsBody { body: PhysicsBody {