lots of skeleton stuff. lots of hacking. mostly hacking
This commit is contained in:
@@ -29,4 +29,5 @@ wgpu-subscriber = "0.1.0"
|
|||||||
tobj = "2.0.3"
|
tobj = "2.0.3"
|
||||||
legion = "0.3.1"
|
legion = "0.3.1"
|
||||||
nalgebra = "0.24.1"
|
nalgebra = "0.24.1"
|
||||||
rapier3d = { version = "0.5.0", features = [ "simd-nightly", "parallel" ] }
|
rapier3d = { version = "0.5.0", features = [ "simd-nightly", "parallel" ] }
|
||||||
|
gilrs = "0.8.0"
|
||||||
173
src/camera.rs
Normal file
173
src/camera.rs
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
use cgmath::{Matrix4, Vector3, Point3, Rad, InnerSpace};
|
||||||
|
use winit::event::{MouseScrollDelta, VirtualKeyCode, ElementState};
|
||||||
|
use winit::dpi::{PhysicalPosition, LogicalPosition};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use std::f32::consts::FRAC_PI_2;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct Camera {
|
||||||
|
pub position: Point3<f32>,
|
||||||
|
pub yaw: Rad<f32>,
|
||||||
|
pub pitch: Rad<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Camera {
|
||||||
|
pub fn new<
|
||||||
|
V: Into<Point3<f32>>,
|
||||||
|
Y: Into<Rad<f32>>,
|
||||||
|
P: Into<Rad<f32>>,
|
||||||
|
>(
|
||||||
|
position: V,
|
||||||
|
yaw: Y,
|
||||||
|
pitch: P,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
position: position.into(),
|
||||||
|
yaw: yaw.into(),
|
||||||
|
pitch: pitch.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn calc_matrix(&self) -> Matrix4<f32> {
|
||||||
|
Matrix4::look_at_dir(
|
||||||
|
self.position,
|
||||||
|
Vector3::new(
|
||||||
|
self.yaw.0.cos(),
|
||||||
|
self.pitch.0.sin(),
|
||||||
|
self.yaw.0.sin(),
|
||||||
|
).normalize(),
|
||||||
|
Vector3::unit_y(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CameraController {
|
||||||
|
amount_left: f32,
|
||||||
|
amount_right: f32,
|
||||||
|
amount_forward: f32,
|
||||||
|
amount_backward: f32,
|
||||||
|
amount_up: f32,
|
||||||
|
amount_down: f32,
|
||||||
|
rotate_horizontal: f32,
|
||||||
|
rotate_vertical: f32,
|
||||||
|
scroll: f32,
|
||||||
|
speed: f32,
|
||||||
|
sensitivity: f32,
|
||||||
|
last_frame: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CameraController {
|
||||||
|
pub fn new(speed: f32, sensitivity: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
amount_left: 0.0,
|
||||||
|
amount_right: 0.0,
|
||||||
|
amount_forward: 0.0,
|
||||||
|
amount_backward: 0.0,
|
||||||
|
amount_up: 0.0,
|
||||||
|
amount_down: 0.0,
|
||||||
|
rotate_horizontal: 0.0,
|
||||||
|
rotate_vertical: 0.0,
|
||||||
|
scroll: 0.0,
|
||||||
|
speed,
|
||||||
|
sensitivity,
|
||||||
|
last_frame: Instant::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool{
|
||||||
|
let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 };
|
||||||
|
match key {
|
||||||
|
VirtualKeyCode::W | VirtualKeyCode::Up => {
|
||||||
|
self.amount_forward = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
VirtualKeyCode::S | VirtualKeyCode::Down => {
|
||||||
|
self.amount_backward = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
VirtualKeyCode::A | VirtualKeyCode::Left => {
|
||||||
|
self.amount_left = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
VirtualKeyCode::D | VirtualKeyCode::Right => {
|
||||||
|
self.amount_right = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Space => {
|
||||||
|
self.amount_up = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
VirtualKeyCode::LShift => {
|
||||||
|
self.amount_down = amount;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) {
|
||||||
|
self.rotate_horizontal = mouse_dx as f32;
|
||||||
|
self.rotate_vertical = mouse_dy as f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_scroll(&mut self, delta: &MouseScrollDelta) {
|
||||||
|
self.scroll = -match delta {
|
||||||
|
// I'm assuming a line is about 100 pixels
|
||||||
|
MouseScrollDelta::LineDelta(_, scroll) => scroll * 100.0,
|
||||||
|
MouseScrollDelta::PixelDelta(LogicalPosition {
|
||||||
|
y: scroll,
|
||||||
|
..
|
||||||
|
}) => *scroll as f32,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_camera(&mut self, camera: &mut Camera, dt: Duration) {
|
||||||
|
|
||||||
|
|
||||||
|
let dt = dt.as_secs_f32();
|
||||||
|
|
||||||
|
// Move forward/backward and left/right
|
||||||
|
let (yaw_sin, yaw_cos) = camera.yaw.0.sin_cos();
|
||||||
|
let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize();
|
||||||
|
let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize();
|
||||||
|
camera.position += forward * (self.amount_forward - self.amount_backward) * self.speed * dt;
|
||||||
|
camera.position += right * (self.amount_right - self.amount_left) * self.speed * dt;
|
||||||
|
|
||||||
|
// Move in/out (aka. "zoom")
|
||||||
|
// Note: this isn't an actual zoom. The camera's position
|
||||||
|
// changes when zooming. I've added this to make it easier
|
||||||
|
// to get closer to an object you want to focus on.
|
||||||
|
let (pitch_sin, pitch_cos) = camera.pitch.0.sin_cos();
|
||||||
|
let scrollward = Vector3::new(pitch_cos * yaw_cos, pitch_sin, pitch_cos * yaw_sin).normalize();
|
||||||
|
camera.position += scrollward * self.scroll * self.speed * self.sensitivity * dt;
|
||||||
|
self.scroll = 0.0;
|
||||||
|
|
||||||
|
// Move up/down. Since we don't use roll, we can just
|
||||||
|
// modify the y coordinate directly.
|
||||||
|
camera.position.y += (self.amount_up - self.amount_down) * self.speed * dt;
|
||||||
|
|
||||||
|
// Rotate
|
||||||
|
camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt;
|
||||||
|
camera.pitch += Rad(-self.rotate_vertical) * self.sensitivity * dt;
|
||||||
|
|
||||||
|
// If process_mouse isn't called every frame, these values
|
||||||
|
// will not get set to zero, and the camera will rotate
|
||||||
|
// when moving in a non cardinal direction.
|
||||||
|
self.rotate_horizontal = 0.0;
|
||||||
|
self.rotate_vertical = 0.0;
|
||||||
|
|
||||||
|
// Keep the camera's angle from going too high/low.
|
||||||
|
if camera.pitch < -Rad(FRAC_PI_2) {
|
||||||
|
camera.pitch = -Rad(FRAC_PI_2);
|
||||||
|
} else if camera.pitch > Rad(FRAC_PI_2) {
|
||||||
|
camera.pitch = Rad(FRAC_PI_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
64
src/components.rs
Normal file
64
src/components.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
use wgpu::{TextureView, Buffer, BindGroup};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
|
||||||
|
use rapier3d::geometry::ColliderHandle;
|
||||||
|
use rapier3d::geometry::Collider as r3dCollider;
|
||||||
|
|
||||||
|
// a component is any type that is 'static, sized, send and sync
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct Position {
|
||||||
|
pub x: f32,
|
||||||
|
pub y: f32,
|
||||||
|
pub z: f32,
|
||||||
|
pub rot: cgmath::Quaternion<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct Color {
|
||||||
|
pub r: f32,
|
||||||
|
pub g: f32,
|
||||||
|
pub b: f32,
|
||||||
|
pub a: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct Velocity {
|
||||||
|
pub dx: f32,
|
||||||
|
pub dy: f32,
|
||||||
|
pub rs: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)]
|
||||||
|
pub struct RangeCopy<Idx> {
|
||||||
|
pub start: Idx,
|
||||||
|
pub end: Idx,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DirectionalLight {
|
||||||
|
pub color: wgpu::Color,
|
||||||
|
pub fov: f32,
|
||||||
|
pub depth: RangeCopy<f32>,
|
||||||
|
pub target_view: Arc<TextureView>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Mesh {
|
||||||
|
pub index_buffer: Arc<Buffer>,
|
||||||
|
pub index_count: usize,
|
||||||
|
pub vertex_buffer: Arc<Buffer>,
|
||||||
|
pub uniform_buffer: Arc<Buffer>,
|
||||||
|
pub bind_group: Arc<BindGroup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Physics {
|
||||||
|
pub rigid_body: RigidBody,
|
||||||
|
pub rigid_body_handle: Option<RigidBodyHandle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Collider {
|
||||||
|
pub collider: r3dCollider,
|
||||||
|
pub collider_handle: Option<ColliderHandle>,
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use bytemuck::__core::ops::Range;
|
use bytemuck::__core::ops::Range;
|
||||||
use bytemuck::{Zeroable, Pod};
|
use bytemuck::{Zeroable, Pod};
|
||||||
use crate::{OPENGL_TO_WGPU_MATRIX, DirectionalLight, Position};
|
|
||||||
use cgmath::Point3;
|
use cgmath::Point3;
|
||||||
|
use crate::render::OPENGL_TO_WGPU_MATRIX;
|
||||||
|
use crate::components::DirectionalLight;
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|||||||
193
src/main.rs
193
src/main.rs
@@ -8,13 +8,12 @@ use std::sync::Arc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use bytemuck::__core::ops::Range;
|
use bytemuck::__core::ops::Range;
|
||||||
use cgmath::{Decomposed, Deg, Euler, InnerSpace, Quaternion, Rotation3, SquareMatrix};
|
use cgmath::{Decomposed, Deg, Euler, InnerSpace, Quaternion, Rotation3, SquareMatrix, Point3, Rad};
|
||||||
use futures::task::LocalSpawn;
|
use futures::task::LocalSpawn;
|
||||||
use legion::*;
|
use legion::*;
|
||||||
use rapier3d::dynamics::{
|
use rapier3d::dynamics::{
|
||||||
IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
|
IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
|
||||||
};
|
};
|
||||||
use rapier3d::geometry::Collider as r3dCollider;
|
|
||||||
use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase};
|
use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase};
|
||||||
use rapier3d::math;
|
use rapier3d::math;
|
||||||
use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
|
use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
|
||||||
@@ -28,13 +27,23 @@ use winit::{
|
|||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use gilrs::Event as GilEvent;
|
||||||
|
|
||||||
|
use crate::camera::{CameraController, Camera};
|
||||||
|
use crate::components::{Collider, Color, Physics, Position};
|
||||||
use crate::physics::PhysicsState;
|
use crate::physics::PhysicsState;
|
||||||
use crate::render::Renderer;
|
use crate::render::Renderer;
|
||||||
|
use crate::owned_event::TrEventExtension;
|
||||||
|
use gilrs::{Gamepad, Gilrs};
|
||||||
|
use rapier3d::counters::Timer;
|
||||||
|
|
||||||
|
mod camera;
|
||||||
|
mod components;
|
||||||
mod geometry;
|
mod geometry;
|
||||||
mod light;
|
mod light;
|
||||||
mod physics;
|
mod physics;
|
||||||
mod render;
|
mod render;
|
||||||
|
mod owned_event;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -58,81 +67,13 @@ mvp:
|
|||||||
|
|
||||||
ECS
|
ECS
|
||||||
animation
|
animation
|
||||||
render 3d
|
render 3d (good!)
|
||||||
input/io
|
input/io
|
||||||
collision / physics
|
collision / physics (yep!)
|
||||||
entities & behaviours
|
entities & behaviours (got the entities!)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
|
||||||
#[allow(unused)]
|
|
||||||
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
|
|
||||||
1.0, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 0.5, 0.0,
|
|
||||||
0.0, 0.0, 0.5, 1.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
// a component is any type that is 'static, sized, send and sync
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub struct Position {
|
|
||||||
x: f32,
|
|
||||||
y: f32,
|
|
||||||
z: f32,
|
|
||||||
rot: cgmath::Quaternion<f32>,
|
|
||||||
//mx: cgmath::Matrix4<f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub struct Color {
|
|
||||||
r: f32,
|
|
||||||
g: f32,
|
|
||||||
b: f32,
|
|
||||||
a: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
pub struct Velocity {
|
|
||||||
dx: f32,
|
|
||||||
dy: f32,
|
|
||||||
rs: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)]
|
|
||||||
pub struct RangeCopy<Idx> {
|
|
||||||
pub start: Idx,
|
|
||||||
pub end: Idx,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct DirectionalLight {
|
|
||||||
color: wgpu::Color,
|
|
||||||
fov: f32,
|
|
||||||
depth: RangeCopy<f32>,
|
|
||||||
target_view: Arc<TextureView>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Mesh {
|
|
||||||
index_buffer: Arc<Buffer>,
|
|
||||||
index_count: usize,
|
|
||||||
vertex_buffer: Arc<Buffer>,
|
|
||||||
uniform_buffer: Arc<Buffer>,
|
|
||||||
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!("");
|
//log::info!("");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -151,12 +92,13 @@ fn main() {
|
|||||||
|
|
||||||
// TODO schedule for the update system and others
|
// TODO schedule for the update system and others
|
||||||
let mut update_schedule = Schedule::builder()
|
let mut update_schedule = Schedule::builder()
|
||||||
|
.add_system(physics::update_camera_system())
|
||||||
.add_system(physics::run_physics_system())
|
.add_system(physics::run_physics_system())
|
||||||
.add_system(physics::update_models_system())
|
.add_system(physics::update_models_system())
|
||||||
// next system here, gamelogic update system?
|
// next system here, gamelogic update system?
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::<TrEventExtension>::with_user_event();
|
||||||
let mut builder = winit::window::WindowBuilder::new();
|
let mut builder = winit::window::WindowBuilder::new();
|
||||||
builder = builder.with_title("MVGE");
|
builder = builder.with_title("MVGE");
|
||||||
|
|
||||||
@@ -169,8 +111,6 @@ fn main() {
|
|||||||
|
|
||||||
let window = builder.build(&event_loop).unwrap();
|
let window = builder.build(&event_loop).unwrap();
|
||||||
|
|
||||||
let mut last_update_inst = Instant::now();
|
|
||||||
|
|
||||||
// Load up the renderer (and the resources)
|
// Load up the renderer (and the resources)
|
||||||
let mut renderer = {
|
let mut renderer = {
|
||||||
let mut renderer = render::Renderer::init(&window);
|
let mut renderer = render::Renderer::init(&window);
|
||||||
@@ -186,20 +126,94 @@ fn main() {
|
|||||||
resources.insert(physics_state);
|
resources.insert(physics_state);
|
||||||
resources.insert(physics_pipeline);
|
resources.insert(physics_pipeline);
|
||||||
|
|
||||||
|
resources.insert(CameraController::new(1.0, 1.0));
|
||||||
|
resources.insert(Instant::now());
|
||||||
|
|
||||||
|
|
||||||
|
let event_loop_proxy = event_loop.create_proxy();
|
||||||
|
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let mut gilrs = Gilrs::new().unwrap();
|
||||||
|
// Iterate over all connected gamepads
|
||||||
|
let mut gamepad: Option<Gamepad> = None;
|
||||||
|
for (_id, gamepad_) in gilrs.gamepads() {
|
||||||
|
if gamepad_.name() == "PS4" {
|
||||||
|
gamepad = Some(gamepad_);
|
||||||
|
}
|
||||||
|
println!("{} is {:?} {:?}", gamepad_.name(), gamepad_.power_info(), gamepad_.id());
|
||||||
|
}
|
||||||
|
let mut active_gamepad = None;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
while let Some(GilEvent { id, event, time }) = gilrs.next_event() {
|
||||||
|
println!("{:?} New event from {}: {:?}", time, id, event);
|
||||||
|
active_gamepad = Some(id);
|
||||||
|
event_loop_proxy.send_event(TrEventExtension::GamepadEvent {
|
||||||
|
gil_event: GilEvent { id, event, time }
|
||||||
|
}).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// // You can also use cached gamepad state
|
||||||
|
// if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) {
|
||||||
|
// if gamepad.is_pressed(Button::South) {
|
||||||
|
// println!("Button South is pressed (XBox - A, PS - X)");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let step_size: f32 = 0.005;
|
||||||
|
let mut elapsed_time: f32 = { // deltatime since last frame
|
||||||
|
let last_frame = resources.get::<Instant>().unwrap();
|
||||||
|
last_frame.elapsed()
|
||||||
|
}.as_secs_f32();
|
||||||
|
|
||||||
|
let mut delta_time: f32 = 0.0;
|
||||||
|
let mut accumulator_time: f32 = 0.0;
|
||||||
|
let mut current_time: f32 = elapsed_time;
|
||||||
|
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
// Artificially slows the loop rate to 10 millis
|
// Artificially slows the loop rate to 10 millis
|
||||||
// This is called after redraw events cleared
|
// This is called after redraw events cleared
|
||||||
*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::from_millis(10));
|
//*control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::from_millis(10));
|
||||||
|
*control_flow = ControlFlow::Poll;
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
event::Event::MainEventsCleared => {
|
event::Event::MainEventsCleared => {
|
||||||
// ask for a redraw every 20 millis
|
|
||||||
if last_update_inst.elapsed() > Duration::from_millis(20) {
|
elapsed_time = { // deltatime since last frame
|
||||||
window.request_redraw();
|
let last_frame = resources.get::<Instant>().unwrap();
|
||||||
last_update_inst = Instant::now();
|
last_frame.elapsed()
|
||||||
|
}.as_secs_f32();
|
||||||
|
delta_time = elapsed_time - current_time;
|
||||||
|
current_time = elapsed_time;
|
||||||
|
if delta_time > 0.02 {
|
||||||
|
delta_time = 0.02;
|
||||||
}
|
}
|
||||||
|
accumulator_time += delta_time;
|
||||||
|
|
||||||
|
|
||||||
|
let dt = { // deltatime since last frame
|
||||||
|
let last_frame = resources.get::<Instant>().unwrap();
|
||||||
|
last_frame.elapsed()
|
||||||
|
};
|
||||||
|
|
||||||
update_schedule.execute(&mut world, &mut resources);
|
update_schedule.execute(&mut world, &mut resources);
|
||||||
pool.run_until_stalled();
|
|
||||||
|
// ask for a redraw every 20 millis
|
||||||
|
if dt > Duration::from_millis(20) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the world time here for next update
|
||||||
|
resources.insert(Instant::now());
|
||||||
|
|
||||||
|
render_schedule.execute(&mut world, &mut resources);
|
||||||
}
|
}
|
||||||
event::Event::DeviceEvent {
|
event::Event::DeviceEvent {
|
||||||
event: MouseMotion { delta },
|
event: MouseMotion { delta },
|
||||||
@@ -257,7 +271,20 @@ fn main() {
|
|||||||
pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
|
pub fn entity_loading(world: &mut World, renderer: &mut Renderer) {
|
||||||
let monkey_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 camera_ent: Entity = world.push((
|
||||||
|
// Camera {
|
||||||
|
// position: Point3 {
|
||||||
|
// x: 5.0,
|
||||||
|
// y: 5.0,
|
||||||
|
// z: 5.0
|
||||||
|
// },
|
||||||
|
// yaw: Rad(45.0),
|
||||||
|
// pitch: Rad(45.0)
|
||||||
|
// }
|
||||||
|
// ));
|
||||||
|
|
||||||
let light_entity: Entity = world.push((
|
let light_entity: Entity = world.push((
|
||||||
cgmath::Point3 {
|
cgmath::Point3 {
|
||||||
x: 7.0 as f32,
|
x: 7.0 as f32,
|
||||||
|
|||||||
213
src/owned_event.rs
Normal file
213
src/owned_event.rs
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
use winit::window::{WindowId, Theme};
|
||||||
|
use winit::event::{WindowEvent, DeviceId, DeviceEvent, KeyboardInput, ModifiersState, MouseScrollDelta, TouchPhase, ElementState, MouseButton, AxisId, Touch, StartCause, Event};
|
||||||
|
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
||||||
|
use gilrs::Event as GilEvent;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum TrUIEvent<T> {
|
||||||
|
UIEvent(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum TrEventExtension {
|
||||||
|
|
||||||
|
/// Custom events here
|
||||||
|
MouseHeldEvent {},
|
||||||
|
KeyHeldEvent {},
|
||||||
|
GamepadEvent {
|
||||||
|
gil_event: GilEvent,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum TrEvent<T> {
|
||||||
|
|
||||||
|
/// Custom events here
|
||||||
|
MouseHeldEvent {},
|
||||||
|
KeyHeldEvent {},
|
||||||
|
GamepadEvent {
|
||||||
|
gil_event: GilEvent,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Winit events here
|
||||||
|
NewEvents(StartCause),
|
||||||
|
WindowEvent {
|
||||||
|
window_id: WindowId,
|
||||||
|
event: TrWindowEvent,
|
||||||
|
},
|
||||||
|
DeviceEvent {
|
||||||
|
device_id: DeviceId,
|
||||||
|
event: DeviceEvent,
|
||||||
|
},
|
||||||
|
UserEvent(T),
|
||||||
|
Suspended,
|
||||||
|
Resumed,
|
||||||
|
MainEventsCleared,
|
||||||
|
RedrawRequested(WindowId),
|
||||||
|
RedrawEventsCleared,
|
||||||
|
LoopDestroyed,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<T> From<Event<'_, T>> for TrEvent<T> {
|
||||||
|
fn from(event: Event<T>) -> Self {
|
||||||
|
match event {
|
||||||
|
Event::NewEvents(cause) => {
|
||||||
|
TrEvent::NewEvents(cause)
|
||||||
|
},
|
||||||
|
Event::WindowEvent { window_id: window_id, event: event } => {
|
||||||
|
TrEvent::WindowEvent {
|
||||||
|
window_id: window_id,
|
||||||
|
event: match event {
|
||||||
|
WindowEvent::AxisMotion { device_id, axis, value } => {
|
||||||
|
TrWindowEvent::AxisMotion { device_id, axis, value }
|
||||||
|
},
|
||||||
|
WindowEvent::Resized(physical_size) => {
|
||||||
|
TrWindowEvent::Resized(physical_size)
|
||||||
|
}
|
||||||
|
WindowEvent::Moved(physical_position) => {
|
||||||
|
TrWindowEvent::Moved(physical_position)
|
||||||
|
}
|
||||||
|
WindowEvent::CloseRequested => {
|
||||||
|
TrWindowEvent::CloseRequested
|
||||||
|
}
|
||||||
|
WindowEvent::Destroyed => {
|
||||||
|
TrWindowEvent::Destroyed
|
||||||
|
}
|
||||||
|
WindowEvent::DroppedFile(path_buf) => {
|
||||||
|
TrWindowEvent::DroppedFile(path_buf)
|
||||||
|
}
|
||||||
|
WindowEvent::HoveredFile(path_buf) => {
|
||||||
|
TrWindowEvent::HoveredFile(path_buf)
|
||||||
|
}
|
||||||
|
WindowEvent::HoveredFileCancelled => {
|
||||||
|
TrWindowEvent::HoveredFileCancelled
|
||||||
|
}
|
||||||
|
WindowEvent::ReceivedCharacter(char) => {
|
||||||
|
TrWindowEvent::ReceivedCharacter(char)
|
||||||
|
}
|
||||||
|
WindowEvent::Focused(bool) => {
|
||||||
|
TrWindowEvent::Focused(bool)
|
||||||
|
}
|
||||||
|
WindowEvent::KeyboardInput { device_id: device_id, input: input, is_synthetic: is_synthetic } => {
|
||||||
|
TrWindowEvent::KeyboardInput { device_id, input, is_synthetic }
|
||||||
|
}
|
||||||
|
WindowEvent::ModifiersChanged(modifiers_state) => {
|
||||||
|
TrWindowEvent::ModifiersChanged(modifiers_state)
|
||||||
|
}
|
||||||
|
WindowEvent::CursorMoved { device_id: device_id, position: position, modifiers: modifiers } => {
|
||||||
|
TrWindowEvent::CursorMoved { device_id, position, modifiers }
|
||||||
|
}
|
||||||
|
WindowEvent::CursorEntered { device_id: device_id } => {
|
||||||
|
TrWindowEvent::CursorEntered { device_id }
|
||||||
|
}
|
||||||
|
WindowEvent::CursorLeft { device_id: device_id } => {
|
||||||
|
TrWindowEvent::CursorLeft { device_id }
|
||||||
|
}
|
||||||
|
WindowEvent::MouseWheel { device_id: device_id, delta: delta, phase: phase, modifiers: modifiers } => {
|
||||||
|
TrWindowEvent::MouseWheel { device_id, delta, phase, modifiers }
|
||||||
|
}
|
||||||
|
WindowEvent::MouseInput { device_id: device_id, state: state, button: button, modifiers: modifiers } => {
|
||||||
|
TrWindowEvent::MouseInput { device_id, state, button, modifiers }
|
||||||
|
}
|
||||||
|
WindowEvent::TouchpadPressure { device_id: device_id, pressure: pressure, stage: stage } => {
|
||||||
|
TrWindowEvent::TouchpadPressure { device_id, pressure, stage }
|
||||||
|
}
|
||||||
|
WindowEvent::Touch(touch) => {
|
||||||
|
TrWindowEvent::Touch(touch)
|
||||||
|
}
|
||||||
|
WindowEvent::ScaleFactorChanged { scale_factor: scale_factor, new_inner_size: new_inner_size } => {
|
||||||
|
TrWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size: PhysicalSize { width: new_inner_size.width, height: new_inner_size.height } }
|
||||||
|
}
|
||||||
|
WindowEvent::ThemeChanged(theme) => {
|
||||||
|
TrWindowEvent::ThemeChanged(theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::DeviceEvent { device_id: device_id, event: event } => {
|
||||||
|
TrEvent::DeviceEvent { device_id, event }
|
||||||
|
}
|
||||||
|
Event::UserEvent(user_event) => {
|
||||||
|
TrEvent::UserEvent(user_event)
|
||||||
|
}
|
||||||
|
Event::Suspended => {
|
||||||
|
TrEvent::Suspended
|
||||||
|
}
|
||||||
|
Event::Resumed => {
|
||||||
|
TrEvent::Resumed
|
||||||
|
}
|
||||||
|
Event::MainEventsCleared => {
|
||||||
|
TrEvent::MainEventsCleared
|
||||||
|
}
|
||||||
|
Event::RedrawRequested(window_id) => {
|
||||||
|
TrEvent::RedrawRequested(window_id)
|
||||||
|
}
|
||||||
|
Event::RedrawEventsCleared => {
|
||||||
|
TrEvent::RedrawEventsCleared
|
||||||
|
}
|
||||||
|
Event::LoopDestroyed => {
|
||||||
|
TrEvent::LoopDestroyed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum TrWindowEvent {
|
||||||
|
|
||||||
|
Resized(PhysicalSize<u32>),
|
||||||
|
Moved(PhysicalPosition<i32>),
|
||||||
|
CloseRequested,
|
||||||
|
Destroyed,
|
||||||
|
DroppedFile(PathBuf),
|
||||||
|
HoveredFile(PathBuf),
|
||||||
|
HoveredFileCancelled,
|
||||||
|
ReceivedCharacter(char),
|
||||||
|
Focused(bool),
|
||||||
|
KeyboardInput {
|
||||||
|
device_id: DeviceId,
|
||||||
|
input: KeyboardInput,
|
||||||
|
is_synthetic: bool,
|
||||||
|
},
|
||||||
|
ModifiersChanged(ModifiersState),
|
||||||
|
CursorMoved {
|
||||||
|
device_id: DeviceId,
|
||||||
|
position: PhysicalPosition<f64>,
|
||||||
|
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
},
|
||||||
|
CursorEntered { device_id: DeviceId },
|
||||||
|
CursorLeft { device_id: DeviceId },
|
||||||
|
MouseWheel {
|
||||||
|
device_id: DeviceId,
|
||||||
|
delta: MouseScrollDelta,
|
||||||
|
phase: TouchPhase,
|
||||||
|
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
},
|
||||||
|
MouseInput {
|
||||||
|
device_id: DeviceId,
|
||||||
|
state: ElementState,
|
||||||
|
button: MouseButton,
|
||||||
|
#[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
},
|
||||||
|
TouchpadPressure {
|
||||||
|
device_id: DeviceId,
|
||||||
|
pressure: f32,
|
||||||
|
stage: i64,
|
||||||
|
},
|
||||||
|
AxisMotion {
|
||||||
|
device_id: DeviceId,
|
||||||
|
axis: AxisId,
|
||||||
|
value: f64,
|
||||||
|
},
|
||||||
|
Touch(Touch),
|
||||||
|
ScaleFactorChanged {
|
||||||
|
scale_factor: f64,
|
||||||
|
new_inner_size: PhysicalSize<u32>,
|
||||||
|
},
|
||||||
|
ThemeChanged(Theme),
|
||||||
|
}
|
||||||
@@ -6,8 +6,10 @@ use rapier3d::pipeline::PhysicsPipeline;
|
|||||||
use legion::*;
|
use legion::*;
|
||||||
|
|
||||||
use crate::render::{EntityUniforms, Renderer};
|
use crate::render::{EntityUniforms, Renderer};
|
||||||
use crate::{Collider, Mesh, RigidBody, Physics, Position};
|
|
||||||
use cgmath::Quaternion;
|
use cgmath::Quaternion;
|
||||||
|
use crate::components::{Collider, Physics, Mesh, Position};
|
||||||
|
use crate::camera::{CameraController, Camera};
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
pub struct PhysicsState {
|
pub struct PhysicsState {
|
||||||
gravity: rapier3d::math::Vector<f32>,
|
gravity: rapier3d::math::Vector<f32>,
|
||||||
@@ -79,6 +81,20 @@ pub fn run_physics(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[system]
|
||||||
|
#[write_component(Camera)]
|
||||||
|
pub fn update_camera(
|
||||||
|
world: &mut SubWorld,
|
||||||
|
#[resource] camera_controller: &mut CameraController,
|
||||||
|
#[resource] last_frame: &mut Instant,
|
||||||
|
) {
|
||||||
|
let mut query = <(&mut Camera)>::query();
|
||||||
|
for (camera) in query.iter_mut(world) {
|
||||||
|
//camera.update_camera()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[system]
|
#[system]
|
||||||
#[write_component(Collider)]
|
#[write_component(Collider)]
|
||||||
#[write_component(Physics)]
|
#[write_component(Physics)]
|
||||||
|
|||||||
175
src/render.rs
175
src/render.rs
@@ -3,10 +3,11 @@ use std::{iter, num::NonZeroU32, ops::Range, rc::Rc};
|
|||||||
|
|
||||||
use bytemuck::__core::mem;
|
use bytemuck::__core::mem;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use cgmath::{Point3, Matrix4, Transform, vec3, Vector3};
|
use cgmath::{vec3, Decomposed, Deg, Euler, InnerSpace, Matrix4, Point3, Quaternion, Rotation3, Transform, Vector3, Rad};
|
||||||
use futures::executor::LocalPool;
|
use futures::executor::LocalPool;
|
||||||
use legion::world::SubWorld;
|
use legion::world::SubWorld;
|
||||||
use legion::*;
|
use legion::*;
|
||||||
|
use rapier3d::parry::motion::RigidMotionComposition;
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
BindGroup, BindGroupLayout, Buffer, Device, Instance, Queue, Surface, SwapChain,
|
BindGroup, BindGroupLayout, Buffer, Device, Instance, Queue, Surface, SwapChain,
|
||||||
@@ -16,10 +17,19 @@ use winit::dpi::PhysicalSize;
|
|||||||
use winit::platform::unix::x11::ffi::Time;
|
use winit::platform::unix::x11::ffi::Time;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
|
||||||
|
use crate::camera::{Camera, CameraController};
|
||||||
|
use crate::components::{Color, DirectionalLight, Mesh, Position, RangeCopy};
|
||||||
use crate::geometry::{create_plane, import_mesh, vertex, Vertex};
|
use crate::geometry::{create_plane, import_mesh, vertex, Vertex};
|
||||||
use crate::light::LightRaw;
|
use crate::light::LightRaw;
|
||||||
use crate::{Color, DirectionalLight, Mesh, Position, RangeCopy, Velocity, OPENGL_TO_WGPU_MATRIX};
|
|
||||||
use rapier3d::parry::motion::RigidMotionComposition;
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
#[allow(unused)]
|
||||||
|
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
|
||||||
|
1.0, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 0.5, 0.0,
|
||||||
|
0.0, 0.0, 0.5, 1.0,
|
||||||
|
);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -29,25 +39,30 @@ pub struct ForwardUniforms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Pod for ForwardUniforms {}
|
unsafe impl Pod for ForwardUniforms {}
|
||||||
|
|
||||||
unsafe impl Zeroable for ForwardUniforms {}
|
unsafe impl Zeroable for ForwardUniforms {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct EntityUniforms {
|
pub struct EntityUniforms {
|
||||||
model: [[f32; 4]; 4],
|
model: [[f32; 4]; 4],
|
||||||
color: [f32; 4],
|
color: [f32; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Pod for EntityUniforms {}
|
unsafe impl Pod for EntityUniforms {}
|
||||||
|
|
||||||
unsafe impl Zeroable for EntityUniforms {}
|
unsafe impl Zeroable for EntityUniforms {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct ShadowUniforms {
|
pub struct ShadowUniforms {
|
||||||
proj: [[f32; 4]; 4],
|
proj: [[f32; 4]; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Pod for ShadowUniforms {}
|
||||||
|
unsafe impl Zeroable for ShadowUniforms {}
|
||||||
|
|
||||||
|
/// A render pass consists of a pipeline, bindgroup, and uniform buf
|
||||||
|
/// The uniform buf is just the ShadowUniforms or ForwardUniforms
|
||||||
|
/// And the bindgroup is just the localbindgroup (the EntityUniforms) and the rest
|
||||||
pub struct Pass {
|
pub struct Pass {
|
||||||
pipeline: wgpu::RenderPipeline,
|
pipeline: wgpu::RenderPipeline,
|
||||||
bind_group: wgpu::BindGroup,
|
bind_group: wgpu::BindGroup,
|
||||||
@@ -55,7 +70,6 @@ pub struct Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
|
|
||||||
swapchain: SwapChain,
|
swapchain: SwapChain,
|
||||||
swapchain_description: SwapChainDescriptor,
|
swapchain_description: SwapChainDescriptor,
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
@@ -78,32 +92,6 @@ pub struct Renderer {
|
|||||||
light_uniform_buf: wgpu::Buffer,
|
light_uniform_buf: wgpu::Buffer,
|
||||||
|
|
||||||
camera_projection: Matrix4<f32>,
|
camera_projection: Matrix4<f32>,
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderer {
|
|
||||||
const MAX_LIGHTS: usize = 10;
|
|
||||||
const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
|
||||||
const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d {
|
|
||||||
width: 512,
|
|
||||||
height: 512,
|
|
||||||
depth: Self::MAX_LIGHTS as u32,
|
|
||||||
};
|
|
||||||
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
|
||||||
|
|
||||||
pub(crate) fn generate_matrix(aspect_ratio: f32) -> cgmath::Matrix4<f32> {
|
|
||||||
// Specifies the aspect ratio that determines the field of view in the x direction.
|
|
||||||
// The aspect ratio is the ratio of x (width) to y (height).
|
|
||||||
let mx_projection = cgmath::perspective(cgmath::Deg(45f32), aspect_ratio, 1.0, 20.0);
|
|
||||||
let mx_view = cgmath::Matrix4::look_at(
|
|
||||||
cgmath::Point3::new(3.0f32, -9.0, 6.0),
|
|
||||||
cgmath::Point3::new(0f32, 0.0, 0.0),
|
|
||||||
cgmath::Vector3::unit_z(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mx_correction = OPENGL_TO_WGPU_MATRIX;
|
|
||||||
mx_correction * mx_projection * mx_view
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[system]
|
#[system]
|
||||||
@@ -112,7 +100,12 @@ impl Renderer {
|
|||||||
#[write_component(Mesh)]
|
#[write_component(Mesh)]
|
||||||
#[write_component(Color)]
|
#[write_component(Color)]
|
||||||
#[write_component(DirectionalLight)]
|
#[write_component(DirectionalLight)]
|
||||||
pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
|
pub fn render_test(
|
||||||
|
world: &mut SubWorld,
|
||||||
|
#[resource] renderer: &mut Renderer,
|
||||||
|
#[resource] camera_controller: &mut CameraController,
|
||||||
|
) {
|
||||||
|
|
||||||
let mut encoder = renderer
|
let mut encoder = renderer
|
||||||
.device
|
.device
|
||||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||||
@@ -167,7 +160,6 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
|
|||||||
let mut query = <(&mut DirectionalLight, &mut Point3<f32>)>::query();
|
let mut query = <(&mut DirectionalLight, &mut Point3<f32>)>::query();
|
||||||
|
|
||||||
for (i, (light, pos)) in query.iter_mut(world).enumerate() {
|
for (i, (light, pos)) in query.iter_mut(world).enumerate() {
|
||||||
|
|
||||||
encoder.insert_debug_marker(&format!("shadow pass {} (light at position {:?})", i, pos));
|
encoder.insert_debug_marker(&format!("shadow pass {} (light at position {:?})", i, pos));
|
||||||
|
|
||||||
// The light uniform buffer already has the projection,
|
// The light uniform buffer already has the projection,
|
||||||
@@ -197,14 +189,11 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
|
|||||||
pass.set_bind_group(0, &renderer.shadow_pass.bind_group, &[]);
|
pass.set_bind_group(0, &renderer.shadow_pass.bind_group, &[]);
|
||||||
|
|
||||||
for mesh in &mesh_stack {
|
for mesh in &mesh_stack {
|
||||||
|
|
||||||
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
||||||
pass.set_index_buffer(mesh.index_buffer.slice(..));
|
pass.set_index_buffer(mesh.index_buffer.slice(..));
|
||||||
pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
|
pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
|
||||||
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
|
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
encoder.pop_debug_group();
|
encoder.pop_debug_group();
|
||||||
// forward pass
|
// forward pass
|
||||||
@@ -252,6 +241,77 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
|
const MAX_LIGHTS: usize = 10;
|
||||||
|
const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
||||||
|
const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d {
|
||||||
|
width: 512,
|
||||||
|
height: 512,
|
||||||
|
depth: Self::MAX_LIGHTS as u32,
|
||||||
|
};
|
||||||
|
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
||||||
|
|
||||||
|
pub fn generate_matrix(aspect_ratio: f32) -> cgmath::Matrix4<f32> {
|
||||||
|
// Specifies the aspect ratio that determines the field of view in the x direction.
|
||||||
|
// The aspect ratio is the ratio of x (width) to y (height).
|
||||||
|
let mx_projection = cgmath::perspective(cgmath::Deg(75f32), aspect_ratio, 1.0, 20.0);
|
||||||
|
let mx_view = cgmath::Matrix4::look_at(
|
||||||
|
cgmath::Point3::new(1.0f32, 1.0, 4.0),
|
||||||
|
cgmath::Point3::new(0.0f32, 0.0, 0.0),
|
||||||
|
cgmath::Vector3::unit_z(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mx_correction = OPENGL_TO_WGPU_MATRIX;
|
||||||
|
mx_correction * mx_projection * mx_view
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cam_look_delta(&mut self, delta: (f64, f64)) {
|
||||||
|
|
||||||
|
// let mx_projection = cgmath::perspective(cgmath::Deg(45f32), aspect_ratio, 1.0, 20.0);
|
||||||
|
// let mx_view = cgmath::Matrix4::look_at(
|
||||||
|
// cgmath::Point3::new(3.0f32, -9.0, 6.0),
|
||||||
|
// cgmath::Point3::new(0f32, 0.0, 0.0),
|
||||||
|
// cgmath::Vector3::unit_z(),
|
||||||
|
// );
|
||||||
|
// let mx_correction = OPENGL_TO_WGPU_MATRIX;
|
||||||
|
// let mx_total = mx_correction * mx_projection * mx_view;
|
||||||
|
//
|
||||||
|
// let rotation = Quaternion::from(Euler {
|
||||||
|
// x: Deg(90.0),
|
||||||
|
// y: Deg(45.0),
|
||||||
|
// z: Deg(15.0),
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Euler {
|
||||||
|
// x: (),
|
||||||
|
// y: (),
|
||||||
|
// z: ()
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// let offset = cgmath::vec3(1.0, 1.0, 4.0);
|
||||||
|
// let transform = Decomposed {
|
||||||
|
// disp: offset.clone(),
|
||||||
|
// rot: Quaternion::from_axis_angle(offset.normalize(), Deg(50.0)),
|
||||||
|
// scale: 1.0,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// let mut q = Quaternion::from(self.camera_direction);
|
||||||
|
// q.v.z += delta.0 as f32;
|
||||||
|
// q.v.y += delta.1 as f32;
|
||||||
|
// //let q2 = Quaternion::from_angle_x(Deg(delta.0 as f32));
|
||||||
|
// //let q3 = Quaternion::from_angle_y(Deg(delta.1 as f32));
|
||||||
|
// let w = Matrix4::from(q);
|
||||||
|
// //mx_total = mx_total + w;
|
||||||
|
//
|
||||||
|
// self.camera_projection = transform.into();
|
||||||
|
// let mut mx_total = self.camera_projection.clone();
|
||||||
|
//
|
||||||
|
// let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||||
|
// self.queue.write_buffer(
|
||||||
|
// &self.forward_pass.uniform_buf,
|
||||||
|
// 0,
|
||||||
|
// bytemuck::cast_slice(mx_ref),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_current_frame(&mut self) -> SwapChainFrame {
|
pub fn get_current_frame(&mut self) -> SwapChainFrame {
|
||||||
// Update the renderers swapchain state
|
// Update the renderers swapchain state
|
||||||
@@ -273,7 +333,6 @@ impl Renderer {
|
|||||||
indices: Vec<u32>,
|
indices: Vec<u32>,
|
||||||
vertices: Vec<Vertex>,
|
vertices: Vec<Vertex>,
|
||||||
) -> (Arc<Buffer>, Arc<Buffer>) {
|
) -> (Arc<Buffer>, Arc<Buffer>) {
|
||||||
|
|
||||||
let vertex_buf = Arc::new(
|
let vertex_buf = Arc::new(
|
||||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("vertex-buffer"),
|
label: Some("vertex-buffer"),
|
||||||
@@ -294,7 +353,11 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_light(&mut self) -> DirectionalLight {
|
pub fn create_light(&mut self) -> DirectionalLight {
|
||||||
let target = self.shadow_target_views.get(self.views_given as usize).take().unwrap();
|
let target = self
|
||||||
|
.shadow_target_views
|
||||||
|
.get(self.views_given as usize)
|
||||||
|
.take()
|
||||||
|
.unwrap();
|
||||||
self.views_given = self.views_given + 1;
|
self.views_given = self.views_given + 1;
|
||||||
DirectionalLight {
|
DirectionalLight {
|
||||||
color: wgpu::Color {
|
color: wgpu::Color {
|
||||||
@@ -640,7 +703,6 @@ impl Renderer {
|
|||||||
|
|
||||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||||
|
|
||||||
|
|
||||||
let forward_pass = {
|
let forward_pass = {
|
||||||
// Create pipeline layout
|
// Create pipeline layout
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
@@ -833,35 +895,12 @@ impl Renderer {
|
|||||||
wgpu::Features::DEPTH_CLAMPING
|
wgpu::Features::DEPTH_CLAMPING
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cam_look_delta(&mut self, delta: (f64, f64)) {
|
|
||||||
|
|
||||||
// let mx_projection = cgmath::perspective(cgmath::Deg(45f32), aspect_ratio, 1.0, 20.0);
|
|
||||||
// let mx_view = cgmath::Matrix4::look_at(
|
|
||||||
// cgmath::Point3::new(3.0f32, -9.0, 6.0),
|
|
||||||
// cgmath::Point3::new(0f32, 0.0, 0.0),
|
|
||||||
// cgmath::Vector3::unit_z(),
|
|
||||||
// );
|
|
||||||
// let mx_correction = OPENGL_TO_WGPU_MATRIX;
|
|
||||||
// let mx_total = mx_correction * mx_projection * mx_view;
|
|
||||||
let mut mx_total = self.camera_projection.clone();
|
|
||||||
let q = vec3(delta.0 as f32, delta.1 as f32, 1.0);
|
|
||||||
mx_total.transform_vector(q);
|
|
||||||
|
|
||||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
|
||||||
self.queue.write_buffer(
|
|
||||||
&self.forward_pass.uniform_buf,
|
|
||||||
0,
|
|
||||||
bytemuck::cast_slice(mx_ref),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resize(&mut self, width: u32, height: u32) {
|
pub fn resize(&mut self, width: u32, height: u32) {
|
||||||
|
|
||||||
self.swapchain_description.width = width;
|
self.swapchain_description.width = width;
|
||||||
self.swapchain_description.height = height;
|
self.swapchain_description.height = height;
|
||||||
self.swapchain = self.device.create_swap_chain(
|
self.swapchain = self
|
||||||
&self.surface, &self.swapchain_description.clone()
|
.device
|
||||||
);
|
.create_swap_chain(&self.surface, &self.swapchain_description.clone());
|
||||||
|
|
||||||
// update view-projection matrix
|
// update view-projection matrix
|
||||||
let mx_total = Self::generate_matrix(width as f32 / height as f32);
|
let mx_total = Self::generate_matrix(width as f32 / height as f32);
|
||||||
@@ -887,7 +926,5 @@ impl Renderer {
|
|||||||
});
|
});
|
||||||
self.forward_depth = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
self.forward_depth = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
self.camera_projection = mx_total;
|
self.camera_projection = mx_total;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user