Wow, ECS is really amazing for this kind of work. Physics are attached to renderable entities and render as expected!

This commit is contained in:
2021-02-10 22:19:26 -08:00
parent fe45a9f166
commit 9f4c8a856c
5 changed files with 2237 additions and 137 deletions

View File

@@ -1,4 +1,3 @@
extern crate tobj;
extern crate winit;
@@ -9,26 +8,32 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use bytemuck::__core::ops::Range;
use cgmath::{Decomposed, Deg, InnerSpace, Quaternion, Rotation3, SquareMatrix};
use cgmath::{Decomposed, Deg, Euler, InnerSpace, Quaternion, Rotation3, SquareMatrix};
use futures::task::LocalSpawn;
use legion::*;
use rapier3d::dynamics::{
IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
};
use rapier3d::geometry::Collider as r3dCollider;
use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase};
use rapier3d::math;
use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
use rapier3d::pipeline::PhysicsPipeline;
use wgpu::{BindGroup, Buffer, TextureView};
use wgpu_subscriber;
use winit::event::DeviceEvent::MouseMotion;
use winit::platform::unix::x11::ffi::Time;
use winit::{
event::{self, WindowEvent},
event_loop::{ControlFlow, EventLoop},
};
use winit::event::DeviceEvent::MouseMotion;
use winit::platform::unix::x11::ffi::Time;
use rapier3d::math;
use crate::physics::PhysicsState;
use crate::render::Renderer;
use rapier3d::pipeline::PhysicsPipeline;
use rapier3d::dynamics::{IntegrationParameters, RigidBodySet, JointSet, RigidBodyBuilder};
use rapier3d::geometry::{BroadPhase, NarrowPhase, ColliderSet, ColliderBuilder};
use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
mod geometry;
mod light;
mod physics;
mod render;
/*
@@ -75,7 +80,8 @@ pub struct Position {
x: f32,
y: f32,
z: f32,
mx: cgmath::Matrix4<f32>,
rot: cgmath::Quaternion<f32>,
//mx: cgmath::Matrix4<f32>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -116,6 +122,17 @@ pub struct Mesh {
bind_group: Arc<BindGroup>,
}
#[derive(Clone, Debug)]
pub struct Physics {
rigid_body: RigidBody,
rigid_body_handle: Option<RigidBodyHandle>,
}
#[derive(Clone)]
pub struct Collider {
collider: r3dCollider,
collider_handle: Option<ColliderHandle>,
}
//log::info!("");
fn main() {
@@ -133,6 +150,11 @@ fn main() {
.build();
// TODO schedule for the update system and others
let mut update_schedule = Schedule::builder()
.add_system(physics::run_physics_system())
.add_system(physics::update_models_system())
// next system here, gamelogic update system?
.build();
let event_loop = EventLoop::new();
let mut builder = winit::window::WindowBuilder::new();
@@ -159,6 +181,11 @@ fn main() {
let mut resources = Resources::default();
resources.insert(renderer);
let (physics_state, physics_pipeline) =
PhysicsState::build(rapier3d::math::Vector::new(0.0, 0.0, -9.81));
resources.insert(physics_state);
resources.insert(physics_pipeline);
event_loop.run(move |event, _, control_flow| {
// Artificially slows the loop rate to 10 millis
// This is called after redraw events cleared
@@ -171,7 +198,7 @@ fn main() {
window.request_redraw();
last_update_inst = Instant::now();
}
physics();
update_schedule.execute(&mut world, &mut resources);
pool.run_until_stalled();
}
event::Event::DeviceEvent {
@@ -227,124 +254,8 @@ fn main() {
});
}
pub fn physics() {
/* // let mut mechanical_world = DefaultMechanicalWorld::new(Vector3::new(0.0, -9.81, 0.0));
// let mut geometrical_world = DefaultGeometricalWorld::new();
//
// let mut bodies = DefaultBodySet::new();
// let mut colliders = DefaultColliderSet::new();
// let mut joint_constraints = DefaultJointConstraintSet::new();
// let mut force_generators = DefaultForceGeneratorSet::new();
//
// // Run the simulation.
// mechanical_world.step(
// &mut geometrical_world,
// &mut bodies,
// &mut colliders,
// &mut joint_constraints,
// &mut force_generators
// );
//
// let ground_handle = bodies.insert(Ground::new());
// let ground_shape = ShapeHandle::new(Cuboid::new(Vector3::new(3.0, 0.2, 3.0)
// ));
//
// let main_floor = ColliderDesc::new(ground_shape)
// .translation(Vector3::y() * -0.2)
// .build(BodyPartHandle(ground_handle, 0));
// colliders.insert(main_floor);
//
// // Build the rigid body.
// let rb = RigidBodyDesc::new()
// .translation(Vector3::new(1.0, 1.0, 1.0))
// .build();
// let rb_handle = bodies.insert(rb);
//
// // Build the collider.
// let cuboid = ShapeHandle::new(Cuboid::new(Vector3::new(1.0, 1.0, 1.0)));
// let co = ColliderDesc::new(cuboid.clone())
// .density(1.0)
// .build(BodyPartHandle(rb_handle, 0));
// colliders.insert(co);
//
// //testbed.set_body_color(rb_handle, color);
//
// let rigid_body =
// RigidBodyDesc::new()
// // The rigid body position. Will override `.translation(...)` and `.rotation(...)`.
// .position(Isometry3::new(
// Vector3::new(1.0, 2.0, 3.0),
// Vector3::y() * PI,
// ))
// .gravity_enabled(true)
// .status(BodyStatus::Dynamic)
// .velocity(VelocityN::linear(1.0, 2.0, 3.0))
// .linear_damping(10.0)
// .angular_damping(5.0)
// .max_linear_velocity(10.0)
// .max_angular_velocity(1.7)
// .mass(1.2)
// // Arbitrary user-defined data associated to the rigid body to be built.
// .user_data(10)
// .build();
//
// let parent_handle = bodies.insert(rigid_body);
//
// let shape = ShapeHandle::new(Ball::new(1.5));
// let collider = ColliderDesc::new(shape)
// .density(1.0)
// .translation(Vector3::y() * 5.0)
// .build(BodyPartHandle(parent_handle, 0));
// let collider_handle = colliders.insert(collider);*/
// Here the gravity is -9.81 along the y axis.
let mut pipeline = PhysicsPipeline::new();
let gravity = rapier3d::math::Vector::new(0.0, -9.81, 0.0);
let integration_parameters = IntegrationParameters::default();
let mut broad_phase = BroadPhase::new();
let mut narrow_phase = NarrowPhase::new();
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut joints = JointSet::new();
// We ignore contact events for now.
let event_handler = ();
let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic().build();
let mut dynamic_ball_body_handle = bodies.insert(dynamic_ball_body);
let mut static_floor_body = RigidBodyBuilder::new_static().position(Isometry3::new(
Vector3::new(1.0, 2.0, 3.0),
Vector::y() * PI,
)).build();
let mut static_floor_body_handle = bodies.insert(static_floor_body);
let ball_collider = ColliderBuilder::ball(0.5).build();
let floor_collider = ColliderBuilder::cuboid(0.5, 0.2, 0.1).build();
let ball_collider_handle = colliders.insert(ball_collider, dynamic_ball_body_handle, &mut bodies);
let floor_collider_handle = colliders.insert(floor_collider, dynamic_ball_body_handle, &mut bodies);
// Run the simulation in the game loop.
loop {
pipeline.step(
&gravity,
&integration_parameters,
&mut broad_phase,
&mut narrow_phase,
&mut bodies,
&mut colliders,
&mut joints,
None,
None,
&event_handler
);
}
}
pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
let untitled_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj");
let monkey_mesh = renderer.load_mesh_to_buffer("./resources/monkey.obj");
// This could be used for relationships between entities...???
let light_entity: Entity = world.push((
@@ -372,14 +283,18 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
scale: 1.0,
};
let mesh_entity: Entity = world.push((
let monkey_entity: Entity = world.push((
Position {
x: 17.0,
y: 15.0,
z: 10.0,
mx: cgmath::Matrix4::from(transform),
x: 1.0,
y: 2.0,
z: 2.0,
rot: Quaternion::from(Euler {
x: Deg(90.0),
y: Deg(45.0),
z: Deg(15.0),
}), //mx: cgmath::Matrix4::from(transform),
},
untitled_mesh,
monkey_mesh,
Color {
r: 1.0,
g: 0.5,
@@ -388,6 +303,29 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
},
));
let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic()
.position(Isometry3::new(
Vector3::new(0.0, 0.0, 5.0),
Vector::y() * PI,
))
.build();
let mut static_floor_body = RigidBodyBuilder::new_static()
.position(Isometry3::new(
Vector3::new(0.0, 0.0, 0.0),
Vector::y() * PI,
))
.build();
let ball_collider = ColliderBuilder::ball(1.5).build();
let floor_collider = ColliderBuilder::cuboid(0.5, 0.2, 0.1).build();
//let mut dynamic_ball_body_handle = bodies.insert(dynamic_ball_body);
//let mut static_floor_body_handle = bodies.insert(static_floor_body.clone());
// let ball_collider_handle = colliders.insert(ball_collider, dynamic_ball_body_handle, &mut bodies);
// let floor_collider_handle = colliders.insert(floor_collider, dynamic_ball_body_handle, &mut bodies);
let plane_mesh = renderer.create_plane(7.0);
let plane_entity: Entity = world.push((
@@ -395,7 +333,11 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
x: 0.0,
y: 0.0,
z: 0.0,
mx: cgmath::Matrix4::identity(),
rot: Quaternion::from(Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
}),
},
plane_mesh,
Color {
@@ -404,5 +346,43 @@ pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
b: 0.5,
a: 1.0,
},
Physics {
rigid_body: static_floor_body,
rigid_body_handle: None,
},
Collider {
collider: floor_collider,
collider_handle: None,
},
));
let ball_mesh = renderer.load_mesh_to_buffer("./resources/ball.obj");
let ball_mesh: Entity = world.push((
Position {
x: 2.0,
y: 2.0,
z: 3.0,
rot: Quaternion::from(Euler {
x: Deg(25.0),
y: Deg(45.0),
z: Deg(15.0),
}),
},
ball_mesh,
Color {
r: 1.0,
g: 0.5,
b: 0.5,
a: 1.0,
},
Physics {
rigid_body: dynamic_ball_body,
rigid_body_handle: None,
},
Collider {
collider: ball_collider,
collider_handle: None,
},
));
}