11 Commits

18 changed files with 3071 additions and 2247 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
/target /target
Cargo.lock
.idea/*

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@@ -9,16 +9,48 @@ type = "PhysicsEntity"
mesh = "ball.obj" mesh = "ball.obj"
[entities.position] [entities.position]
x = 0.0 x = 15.0
y = 0.0 y = 15.0
z = 0.0 z = 15.0
[entities.position.rotation]
x = 0.0
y = 0.0
z = 0.0
[entities.physics]
body_status = "static"
[entities.physics.cuboid]
x = 1.0
y = 1.0
z = 1.0
[[entities]] [[entities]]
name = "camera.1" name = "camera.1"
type = "Camera" type = "Camera"
[entities.position]
x = 15.0
y = 15.0
z = 15.0
[[entities]] [[entities]]
name = "light.1" name = "light.1"
type = "Light" type = "Light"
mesh = "light.obj" mesh = "light.obj"
[entities.position]
x = 25.0
y = 75.0
z = 20.0
[[entities]]
name = "light.2"
type = "Light"
mesh = "light.obj"
[entities.position]
x = 50.0
y = 75.0
z = 20.0

View File

@@ -2,8 +2,8 @@
# Material Count: 1 # Material Count: 1
newmtl None newmtl None
Ns 0 Ns 500
Ka 0.000000 0.000000 0.000000 Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8 Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8 Ks 0.8 0.8 0.8
d 1 d 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2

View File

@@ -0,0 +1,46 @@
# Blender v2.91.2 OBJ File: ''
# www.blender.org
mtllib textured-cube.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.875000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.375000 1.000000
vt 0.375000 0.750000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.625000 0.250000
vt 0.875000 0.750000
vt 0.625000 1.000000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 5/1/1 3/2/1 1/3/1
f 3/2/2 8/4/2 4/5/2
f 7/6/3 6/7/3 8/8/3
f 2/9/4 8/10/4 6/11/4
f 1/3/5 4/5/5 2/9/5
f 5/12/6 2/9/6 6/7/6
f 5/1/1 7/13/1 3/2/1
f 3/2/2 7/14/2 8/4/2
f 7/6/3 5/12/3 6/7/3
f 2/9/4 4/5/4 8/10/4
f 1/3/5 3/2/5 4/5/5
f 5/12/6 1/3/6 2/9/6

View File

@@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 500
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

2372
resources/tilted-terrain.obj Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,8 @@ use cgmath::{Decomposed, InnerSpace, Matrix4, Point3, Rad, Vector3};
use winit_24::dpi::{LogicalPosition, PhysicalPosition}; use winit_24::dpi::{LogicalPosition, PhysicalPosition};
use winit_24::event::{ElementState, MouseScrollDelta, VirtualKeyCode}; use winit_24::event::{ElementState, MouseScrollDelta, VirtualKeyCode};
use crate::render::OPENGL_TO_WGPU_MATRIX; use crate::render::OPENGL_TO_WGPU_MATRIX;
use imgui::Condition;
use imgui::*;
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub struct Camera { pub struct Camera {
@@ -150,6 +151,7 @@ impl CameraController {
} }
pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) { pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) {
// Move forward/backward and left/right // Move forward/backward and left/right
let view_vector = Vector3::new( let view_vector = Vector3::new(
(1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()), (1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()),

View File

@@ -1,16 +1,20 @@
use wgpu::{TextureView, Buffer, BindGroup};
use std::sync::Arc; use std::sync::Arc;
use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
use rapier3d::geometry::ColliderHandle;
use rapier3d::geometry::Collider as r3dCollider;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use cgmath::Deg;
use cgmath::{Deg, Euler};
use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
use rapier3d::geometry::Collider as r3dCollider;
use rapier3d::geometry::ColliderHandle;
use wgpu::{BindGroup, Buffer, TextureView};
use crate::runtime::state::{TomlPositionDescription, TomlRotationDescription};
use imgui::Ui;
// a component is any type that is 'static, sized, send and sync // a component is any type that is 'static, sized, send and sync
pub struct ImguiWindow<'a, T> {
pub struct ImguiWindow<'a> { pub window: fn() -> imgui::Window<'a>,
pub window: imgui::Window<'a>, pub func: fn(&Ui, Vec<&T>),
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@@ -28,6 +32,62 @@ pub struct Position {
pub rot: cgmath::Euler<Deg<f32>>, pub rot: cgmath::Euler<Deg<f32>>,
} }
impl Default for Position {
fn default() -> Self {
Position {
x: 0.0,
y: 0.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
}
}
}
impl From<TomlPositionDescription> for Position {
fn from(pos: TomlPositionDescription) -> Self {
let euler = match pos.rot {
None => Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
Some(v) => Euler {
x: Deg(v.x),
y: Deg(v.y),
z: Deg(v.z),
},
};
Position {
x: pos.x,
y: pos.y,
z: pos.z,
rot: euler,
}
}
}
impl From<Option<TomlPositionDescription>> for Position {
fn from(pos: Option<TomlPositionDescription>) -> Self {
match pos {
None => Position {
x: 0.0,
y: 0.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
Some(v) => Position::from(v),
}
}
}
#[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)] #[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)]
pub struct RangeCopy<Idx> { pub struct RangeCopy<Idx> {
pub start: Idx, pub start: Idx,

View File

@@ -25,15 +25,15 @@ pub struct DirectionalLight {
pub fov: f32, pub fov: f32,
pub depth: RangeCopy<f32>, pub depth: RangeCopy<f32>,
pub target_view: Arc<TextureView>, pub target_view: Arc<TextureView>,
pub pos: Position,
} }
impl DirectionalLight { impl DirectionalLight {
pub fn to_raw(&self) -> LightRaw { pub fn to_raw(&self, pos: &Position) -> LightRaw {
use cgmath::{Deg, EuclideanSpace, Matrix4, PerspectiveFov, Point3, Vector3}; use cgmath::{Deg, EuclideanSpace, Matrix4, PerspectiveFov, Point3, Vector3};
let point3d = Point3::new(self.pos.x, self.pos.y, self.pos.z); let point3d = Point3::new(pos.x, pos.y, pos.z);
let mx_view = Matrix4::look_at(point3d, Point3::origin(), Vector3::unit_y()); let point3d_2 = Point3::new(pos.x, pos.y - 1.0, pos.z);
let mx_view = Matrix4::look_at(point3d, point3d_2, Vector3::unit_z());
let projection = PerspectiveFov { let projection = PerspectiveFov {
fovy: Deg(self.fov).into(), fovy: Deg(self.fov).into(),
@@ -46,7 +46,7 @@ impl DirectionalLight {
mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
LightRaw { LightRaw {
proj: *mx_view_proj.as_ref(), proj: *mx_view_proj.as_ref(),
pos: [self.pos.x, self.pos.y, self.pos.z, 1.0], pos: [pos.x, pos.y, pos.z, 1.0],
color: [ color: [
self.color.r as f32, self.color.r as f32,
self.color.g as f32, self.color.g as f32,

View File

@@ -1,16 +1,17 @@
extern crate env_logger;
extern crate imgui; extern crate imgui;
extern crate imgui_wgpu; extern crate imgui_wgpu;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate tobj;
extern crate winit_24;
extern crate env_logger;
extern crate toml;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate tobj;
extern crate toml;
extern crate winit_24;
use std::collections::HashMap;
use std::f32::consts::PI; use std::f32::consts::PI;
use std::fs;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@@ -20,6 +21,7 @@ use cgmath::{
}; };
use futures::executor::block_on; use futures::executor::block_on;
use futures::task::LocalSpawn; use futures::task::LocalSpawn;
use futures::FutureExt;
use gilrs::Event as GilEvent; use gilrs::Event as GilEvent;
use gilrs::{Gamepad, Gilrs}; use gilrs::{Gamepad, Gilrs};
use imgui::FontSource; use imgui::FontSource;
@@ -28,6 +30,7 @@ use imgui::*;
use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig};
use legion::systems::{SyncResources, UnsafeResources}; use legion::systems::{SyncResources, UnsafeResources};
use legion::*; use legion::*;
use log::LevelFilter;
use rapier3d::counters::Timer; use rapier3d::counters::Timer;
use rapier3d::dynamics::{ use rapier3d::dynamics::{
IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet, IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
@@ -40,7 +43,8 @@ use rapier3d::pipeline::PhysicsPipeline;
use wgpu::{BindGroup, Buffer, TextureView}; use wgpu::{BindGroup, Buffer, TextureView};
use wgpu_subscriber; use wgpu_subscriber;
use winit_24::event::DeviceEvent::MouseMotion; use winit_24::event::DeviceEvent::MouseMotion;
use winit_24::platform::unix::x11::ffi::Time; use winit_24::event::{ElementState, VirtualKeyCode};
use winit_24::event_loop::EventLoopProxy;
use winit_24::window::Window; use winit_24::window::Window;
use winit_24::{ use winit_24::{
event::{self, WindowEvent}, event::{self, WindowEvent},
@@ -54,13 +58,9 @@ use crate::imgui_supp::extended_winit_imgui_support;
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
use crate::owned_event::{OwnedEvent, OwnedEventExtension}; use crate::owned_event::{OwnedEvent, OwnedEventExtension};
use crate::physics::state::PhysicsState; use crate::physics::state::PhysicsState;
use std::fs; use crate::render::system::ImguiPerformanceProfilerLine;
use winit_24::event::{VirtualKeyCode, ElementState};
use std::collections::HashMap;
use futures::FutureExt;
use log::LevelFilter;
use crate::runtime::state::RuntimeState; use crate::runtime::state::RuntimeState;
use winit_24::event_loop::EventLoopProxy; use winit_24::dpi::PhysicalSize;
mod camera; mod camera;
mod components; mod components;
@@ -92,33 +92,38 @@ https://github.com/amethyst/legion
ECS ECS
animation animation
config / save loading (sorta!)
render 3d (good!) render 3d (good!)
input/io (yep!) input/io (yep!)
collision / physics (yep!) collision / physics (yep!)
entities & behaviours (got the entities!) entities & behaviours (got the entities!)
scripting! scripting!
Todo:
Load scene imgui interface w/ toml files
FPS graph port from voxel raycaster
better imgui interface with components & systems
Figure out eventing, GameInput, passing all events, etc.
+ texturing
*/ */
//log::info!(""); //log::info!("");
// ImGUI works on more or less a global state. which is MegaLame // ImGUI works on more or less an unsafe global state. which is MegaLame
static mut CURRENT_UI: Option<imgui::Ui<'static>> = None; static mut CURRENT_UI: Option<imgui::Ui<'static>> = None;
pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> { pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> {
CURRENT_UI.as_ref() CURRENT_UI.as_ref()
} }
fn main() { fn main() {
let logger = env_logger::builder()
let logger = env_logger::builder().filter(Some("minimal_viable_game_engine"), LevelFilter::Info).init(); .filter(Some("minimal_viable_game_engine"), LevelFilter::Info)
.init();
// for i in settings.get("entities") {
//
// }
let mut world = World::default(); let mut world = World::default();
@@ -129,10 +134,13 @@ fn main() {
let mut load_schedule = Schedule::builder() let mut load_schedule = Schedule::builder()
.add_system(runtime::system::runtime_load_system()) .add_system(runtime::system::runtime_load_system())
.add_system(runtime::system::runtime_spawn_system()) .add_system(runtime::system::runtime_spawn_system())
.flush()
.build(); .build();
let mut render_schedule = Schedule::builder() let mut render_schedule = Schedule::builder()
.add_system(render::system::render_imgui_system())
.add_system(render::system::render_test_system()) .add_system(render::system::render_test_system())
.add_system(render::system::render_performance_flag_system())
.build(); .build();
let mut update_schedule = Schedule::builder() let mut update_schedule = Schedule::builder()
@@ -149,11 +157,14 @@ fn main() {
let event_loop = EventLoop::<OwnedEventExtension>::with_user_event(); let event_loop = EventLoop::<OwnedEventExtension>::with_user_event();
let mut builder = winit_24::window::WindowBuilder::new(); let mut builder = winit_24::window::WindowBuilder::new();
builder = builder.with_title("MVGE"); builder = builder.with_title("MVGE");
builder = builder.with_inner_size(PhysicalSize::new(1200,900));
let window = builder.build(&event_loop).unwrap(); let window = builder.build(&event_loop).unwrap();
let mut resources = Resources::default(); let mut resources = Resources::default();
// Load up all the resources // Load up all the resources
{ {
let mut imgui_context = imgui::Context::create(); let mut imgui_context = imgui::Context::create();
@@ -194,7 +205,7 @@ fn main() {
// Physics // Physics
let (physics_state, physics_pipeline) = let (physics_state, physics_pipeline) =
PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.05)); PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.0));
resources.insert(physics_state); resources.insert(physics_state);
resources.insert(physics_pipeline); resources.insert(physics_pipeline);
@@ -240,21 +251,26 @@ fn main() {
// conditionally, and run the fps locked renderer // conditionally, and run the fps locked renderer
event::Event::MainEventsCleared => { event::Event::MainEventsCleared => {
event_schedule.execute(&mut world, &mut resources); event_schedule.execute(&mut world, &mut resources);
imgui_prepare_schedule.execute(&mut world, &mut resources);
resources resources
.get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>() .get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>()
.unwrap() .unwrap()
.clear(); .clear();
imgui_prepare_schedule.execute(&mut world, &mut resources);
let (step_size, elapsed_time) = { let (step_size, elapsed_time) = {
// deltatime since last frame let mut loop_state = resources.get_mut::<LoopState>().unwrap();
let loop_state = resources.get::<LoopState>().unwrap();
( (
loop_state.step_size, loop_state.step_size,
loop_state.start_time.elapsed().as_secs_f32(), loop_state.start_time.elapsed().as_secs_f32(),
) )
}; };
delta_time = elapsed_time - current_time; delta_time = elapsed_time - current_time;
{
let mut loop_state = resources.get_mut::<LoopState>().unwrap();
loop_state.delta_time = Duration::from_secs_f32(delta_time);
}
current_time = elapsed_time; current_time = elapsed_time;
if delta_time > 0.02 { if delta_time > 0.02 {
delta_time = 0.02; delta_time = 0.02;
@@ -263,10 +279,10 @@ fn main() {
while accumulator_time - step_size >= step_size { while accumulator_time - step_size >= step_size {
accumulator_time -= step_size; accumulator_time -= step_size;
// ==== DELTA TIME LOCKED ==== // ==== DELTA TIME LOCKED ====
update_schedule.execute(&mut world, &mut resources); update_schedule.execute(&mut world, &mut resources);
} }
// ==== FPS LOCKED ==== // ==== FPS LOCKED ====
render_schedule.execute(&mut world, &mut resources); render_schedule.execute(&mut world, &mut resources);
} }
@@ -287,15 +303,17 @@ fn main() {
event: winit_24::event::DeviceEvent::Key(keyboard_input), event: winit_24::event::DeviceEvent::Key(keyboard_input),
.. ..
} => { } => {
match keyboard_input.virtual_keycode.unwrap() { if keyboard_input.virtual_keycode.is_some() {
VirtualKeyCode::Escape => { match keyboard_input.virtual_keycode.unwrap() {
if keyboard_input.state == ElementState::Pressed { VirtualKeyCode::Escape => {
*control_flow = ControlFlow::Exit; if keyboard_input.state == ElementState::Pressed {
} else { *control_flow = ControlFlow::Exit;
//d } else {
//d
}
} }
_ => (),
} }
_ => ()
} }
} }
event::Event::WindowEvent { event::Event::WindowEvent {
@@ -318,7 +336,6 @@ fn main() {
} }
pub fn setup_gamepad(event_loop: &EventLoop<OwnedEventExtension>) { pub fn setup_gamepad(event_loop: &EventLoop<OwnedEventExtension>) {
let event_loop_proxy = event_loop.create_proxy(); let event_loop_proxy = event_loop.create_proxy();
std::thread::spawn(move || { std::thread::spawn(move || {
@@ -360,4 +377,3 @@ pub fn setup_gamepad(event_loop: &EventLoop<OwnedEventExtension>) {
} }
}); });
} }

View File

@@ -10,9 +10,11 @@ use rapier3d::geometry::{BroadPhase, ColliderSet, NarrowPhase};
use rapier3d::pipeline::{PhysicsPipeline, ChannelEventCollector}; use rapier3d::pipeline::{PhysicsPipeline, ChannelEventCollector};
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::components::{Collider, LoopState, Mesh, Physics, Position}; use crate::components::{Collider, LoopState, Mesh, Physics, Position, ImguiWindow};
use imgui::FontSource; use imgui::{FontSource, Condition};
use imgui::*;
use crate::physics::state::PhysicsState; use crate::physics::state::PhysicsState;
use crate::render::system::ImguiGenericOutputLine;
#[system] #[system]
@@ -73,14 +75,22 @@ pub fn run_physics(
} }
} }
#[system] #[system]
#[write_component(Camera)] #[write_component(Camera)]
#[write_component(CameraController)] #[write_component(CameraController)]
#[write_component(ImguiGenericOutputLine)]
pub fn update_camera(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) { pub fn update_camera(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) {
let mut query = <(&mut Camera, &mut CameraController)>::query(); let mut query = <(&mut Camera, &mut CameraController)>::query();
for (mut camera, controller) in query.iter_mut(world) { for (mut camera, controller) in query.iter_mut(world) {
controller.update_camera(&mut camera, loop_state.step_size) controller.update_camera(&mut camera, loop_state.step_size)
} }
let mut query = <(&mut Camera, &mut CameraController, &mut ImguiGenericOutputLine)>::query();
for (mut camera, controller, ui_entry) in query.iter_mut(world) {
ui_entry.label = format!("Camera: {:.2}, {:.2}, {:.2}", camera.position.x, camera.position.y, camera.position.z);
}
} }
#[system] #[system]
@@ -93,6 +103,7 @@ pub fn update_models(
#[resource] physics_state: &mut PhysicsState, #[resource] physics_state: &mut PhysicsState,
#[resource] physics_pipeline: &mut PhysicsPipeline, #[resource] physics_pipeline: &mut PhysicsPipeline,
) { ) {
// Make sure all the entities we care about are added to the system // Make sure all the entities we care about are added to the system
let mut query = <(&mut Collider, &mut Physics, &mut Mesh, &mut Position)>::query(); let mut query = <(&mut Collider, &mut Physics, &mut Mesh, &mut Position)>::query();
for (collider, physics, mesh, position) in query.iter_mut(world) { for (collider, physics, mesh, position) in query.iter_mut(world) {

View File

@@ -20,7 +20,6 @@ use rapier3d::parry::motion::RigidMotionComposition;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use wgpu::{BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, Device, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, CommandEncoder}; use wgpu::{BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, Device, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, CommandEncoder};
use winit_24::dpi::PhysicalSize; use winit_24::dpi::PhysicalSize;
use winit_24::platform::unix::x11::ffi::Time;
use winit_24::window::Window; use winit_24::window::Window;
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
@@ -74,8 +73,8 @@ impl RenderState {
const MAX_LIGHTS: usize = 10; const MAX_LIGHTS: usize = 10;
const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d { const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d {
width: 512, width: 1024,
height: 512, height: 1024,
depth: Self::MAX_LIGHTS as u32, depth: Self::MAX_LIGHTS as u32,
}; };
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
@@ -196,22 +195,12 @@ impl RenderState {
b: 0.5, b: 0.5,
a: 1.0, a: 1.0,
}, },
fov: 45.0, fov: 90.0,
depth: RangeCopy { depth: RangeCopy {
start: 1.0, start: 1.0,
end: 20.0, end: 200.0,
}, },
target_view: target.clone(), target_view: target.clone(),
pos: Position {
x: 0.0,
y: 0.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(-25.0),
z: Deg(0.0),
},
},
} }
} }

View File

@@ -1,4 +1,6 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::iter::Chain;
use std::slice::Iter;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::current; use std::thread::current;
use std::time::Duration; use std::time::Duration;
@@ -18,20 +20,24 @@ use legion::world::SubWorld;
use legion::*; use legion::*;
use rapier3d::parry::motion::RigidMotionComposition; use rapier3d::parry::motion::RigidMotionComposition;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use wgpu::{BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, Device, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, CommandEncoder}; use wgpu::{
BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device,
FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame,
TextureView, VertexState,
};
use winit_24::dpi::PhysicalSize; use winit_24::dpi::PhysicalSize;
use winit_24::platform::unix::x11::ffi::Time;
use winit_24::window::Window; use winit_24::window::Window;
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::components::{Mesh, Position, RangeCopy}; use crate::components::{ImguiWindow, LoopState, Mesh, Position, RangeCopy};
use crate::current_ui; use crate::current_ui;
use crate::geometry::{load_obj, Vertex}; use crate::geometry::{load_obj, Vertex};
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
use crate::light::{DirectionalLight, LightRaw}; use crate::light::{DirectionalLight, LightRaw};
use crate::render::state::{RenderState}; use crate::render::state::RenderState;
use crate::render::{push_debug_group_checked, insert_debug_marker_checked, pop_debug_group_checked, EntityUniforms}; use crate::render::{
insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms,
};
#[system] #[system]
#[write_component(Camera)] #[write_component(Camera)]
@@ -53,14 +59,128 @@ pub fn imgui_prepare(
unsafe { crate::CURRENT_UI = Some(std::mem::transmute(imgui_context.frame())) } unsafe { crate::CURRENT_UI = Some(std::mem::transmute(imgui_context.frame())) }
} }
fn run_imgui_render_step<G: 'static + Sized + Send + Sync>(world: &mut SubWorld, ui: &Ui) {
let mut component_query = <(&G)>::query();
let mut window_query = <(&ImguiWindow<G>)>::query();
let mut window_data = None;
let mut window_func = None;
for (window) in window_query.iter(world) {
window_data = Some((window.window)());
window_func = Some(window.func);
}
if window_data.is_some() {
let mut v = Vec::new();
for (component_state) in component_query.iter(world) {
v.push(component_state)
}
window_data
.unwrap()
.build(&ui, || (window_func.unwrap())(ui, v));
}
}
/// Go through each "global" window-data component and render it's data
#[system]
#[write_component(ImguiWindow<ImguiPerformanceProfilerLine>)]
#[write_component(ImguiPerformanceProfilerLine)]
#[write_component(ImguiWindow<ImguiGenericOutputLine>)]
#[write_component(ImguiGenericOutputLine)]
pub fn render_imgui(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) {
let ui = unsafe { crate::current_ui().unwrap() };
// Pull out the window associated with this type, and render each of the components in the sytem
run_imgui_render_step::<ImguiGenericOutputLine>(world, &ui);
run_imgui_render_step::<ImguiPerformanceProfilerLine>(world, &ui);
}
// This would be the shared state for all imgui generic output things
pub struct ImguiGenericOutputLine {
pub label: String,
}
impl ImguiGenericOutputLine {
pub fn new(label: String) -> ImguiGenericOutputLine {
ImguiGenericOutputLine { label }
}
}
// This would be the shared state for all imgui performance window things
pub struct ImguiPerformanceProfilerLine {
pub label: String,
list_of_fps: [f32; 400],
index: usize,
scale_min: f32,
pub scale_max: f32,
}
impl ImguiPerformanceProfilerLine {
fn add_sample(&mut self, sample: f32) {
self.list_of_fps[self.index] = sample;
if self.index >= 399 {
self.scale_max = self.list_of_fps.iter().cloned().fold(0. / 0., f32::max);
self.index = 0;
} else {
self.index += 1;
}
if self.scale_max < sample {
self.scale_max = sample;
}
}
pub fn iter_data_from_head(&self) -> Chain<Iter<f32>, Iter<f32>> {
let (left, right) = self.list_of_fps.split_at(self.index);
right.iter().chain(left.iter())
}
pub fn current_average_label(&self) -> (f32, String) {
let (left, right) = self.list_of_fps.split_at(self.index);
(
(left
.iter()
.rev()
.chain(right.iter().rev())
.take(50)
.sum::<f32>()
/ 50.0),
"FPS".to_string(),
)
}
pub fn new(label: String) -> ImguiPerformanceProfilerLine {
ImguiPerformanceProfilerLine {
label,
list_of_fps: [0.0; 400],
index: 0,
scale_min: 0.0,
scale_max: 0.0,
}
}
}
#[system]
#[write_component(ImguiPerformanceProfilerLine)]
pub fn render_performance_flag(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) {
let delta_time = loop_state.delta_time.as_secs_f32();
let mut query = <(&mut ImguiPerformanceProfilerLine)>::query();
for (mut profiler) in query.iter_mut(world) {
profiler.add_sample(delta_time);
}
}
#[system] #[system]
#[write_component(Camera)] #[write_component(Camera)]
#[write_component(Position)] #[write_component(Position)]
#[write_component(ImguiPerformanceProfilerLine)]
#[write_component(Point3<f32>)] #[write_component(Point3<f32>)]
#[write_component(Mesh)] #[write_component(Mesh)]
#[write_component(DirectionalLight)] #[write_component(DirectionalLight)]
pub fn render_test( pub fn render_test(
world: &mut SubWorld, world: &mut SubWorld,
#[resource] loop_state: &mut LoopState,
#[resource] renderer: &mut RenderState, #[resource] renderer: &mut RenderState,
#[resource] winit_window: &mut Window, #[resource] winit_window: &mut Window,
#[resource] imgui_context: &mut Arc<Mutex<ImguiContext>>, #[resource] imgui_context: &mut Arc<Mutex<ImguiContext>>,
@@ -72,7 +192,6 @@ pub fn render_test(
push_debug_group_checked("start render function", &mut encoder); push_debug_group_checked("start render function", &mut encoder);
let frame = renderer.get_current_frame(); let frame = renderer.get_current_frame();
// Update the camera uniform buffers, need to make it support selection of // Update the camera uniform buffers, need to make it support selection of
@@ -117,23 +236,25 @@ pub fn render_test(
if renderer.lights_are_dirty { if renderer.lights_are_dirty {
renderer.lights_are_dirty = false; renderer.lights_are_dirty = false;
let mut query = <(&mut DirectionalLight, &mut Point3<f32>)>::query(); let mut query = <(&mut DirectionalLight, &mut Position)>::query();
for (i, (light, pos)) in query.iter_mut(world).enumerate() { for (i, (light, pos)) in query.iter_mut(world).enumerate() {
renderer.queue.write_buffer( renderer.queue.write_buffer(
&renderer.light_uniform_buf, &renderer.light_uniform_buf,
(i * mem::size_of::<LightRaw>()) as wgpu::BufferAddress, (i * mem::size_of::<LightRaw>()) as wgpu::BufferAddress,
bytemuck::bytes_of(&light.to_raw()), bytemuck::bytes_of(&light.to_raw(&pos)),
); );
} }
} }
push_debug_group_checked("shadow passes", &mut encoder); push_debug_group_checked("shadow passes", &mut encoder);
let mut query = <(&mut DirectionalLight, &mut Point3<f32>)>::query(); let mut query = <(&mut DirectionalLight, &mut Position)>::query();
for (i, (light, pos)) in query.iter_mut(world).enumerate() { for (i, (light, pos)) in query.iter_mut(world).enumerate() {
insert_debug_marker_checked(&format!("shadow pass {} (light at position {:?})", i, pos), &mut encoder); insert_debug_marker_checked(
&format!("shadow pass {} (light at position {:?})", i, pos),
&mut encoder,
);
// The light uniform buffer already has the projection, // The light uniform buffer already has the projection,
// let's just copy it over to the shadow uniform buffer. // let's just copy it over to the shadow uniform buffer.
@@ -147,7 +268,6 @@ pub fn render_test(
insert_debug_marker_checked("render entities", &mut encoder); insert_debug_marker_checked("render entities", &mut encoder);
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("render pass"), label: Some("render pass"),
color_attachments: &[], color_attachments: &[],
@@ -221,17 +341,8 @@ pub fn render_test(
let mut imgui_context = &mut imgui_context.lock().unwrap().context; let mut imgui_context = &mut imgui_context.lock().unwrap().context;
let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform; let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform;
//imgui_state.context.io_mut().update_delta_time(Duration::new(0,160));
let ui = unsafe { crate::current_ui().unwrap() }; let ui = unsafe { crate::current_ui().unwrap() };
let window = imgui::Window::new(im_str!("Hello too"));
window
.size([400.0, 100.0], Condition::FirstUseEver)
.position([50.0, 50.0], Condition::FirstUseEver)
.build(&ui, || {
ui.text(im_str!("Frametime: {:?}", 10.0));
});
// ui.show_demo_window(&mut true); // ui.show_demo_window(&mut true);
imgui_platform.prepare_render(&ui, &winit_window); imgui_platform.prepare_render(&ui, &winit_window);

View File

@@ -17,11 +17,55 @@ use crate::components::{Collider, LoopState, Mesh, Physics, Position};
use crate::geometry::{load_obj, RawMesh}; use crate::geometry::{load_obj, RawMesh};
use std::io::Read; use std::io::Read;
pub struct EntityMeta {
#[derive(Deserialize, Clone)]
pub struct TomlBallPhysicsBodyDescription {
pub radius: String
}
#[derive(Deserialize, Clone)]
pub struct TomlCuboidPhysicsBodyDescription {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Deserialize, Clone)]
pub struct TomlPhysicsDescription {
pub body_status: String,
pub ball: Option<TomlBallPhysicsBodyDescription>,
pub cuboid: Option<TomlCuboidPhysicsBodyDescription>,
}
#[derive(Deserialize, Clone)]
pub struct TomlRotationDescription {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Deserialize, Clone)]
pub struct TomlPositionDescription {
pub x: f32,
pub y: f32,
pub z: f32,
pub rot: Option<TomlRotationDescription>,
}
#[derive(Deserialize, Clone)]
pub struct TomlEntityDescription {
pub name: String, pub name: String,
pub ent_type: String, #[serde(rename = "type")]
pub type_name: String,
pub mesh: Option<String>, pub mesh: Option<String>,
pub position: Option<Position> pub position: Option<TomlPositionDescription>,
pub physics: Option<TomlPhysicsDescription>,
}
#[derive(Deserialize, Clone)]
pub struct TomlEntityContainer {
pub entities: Vec<TomlEntityDescription>,
} }
pub struct RuntimeState { pub struct RuntimeState {
@@ -29,38 +73,15 @@ pub struct RuntimeState {
mesh_cache: HashMap<String, RawMesh>, mesh_cache: HashMap<String, RawMesh>,
} }
#[derive(Deserialize)]
pub struct TomlPositionDescription {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Deserialize)]
pub struct TomlEntityDescription {
pub name: String,
#[serde(rename = "type")]
pub type_name: String,
pub mesh: Option<String>,
pub position: Option<TomlPositionDescription>,
}
#[derive(Deserialize)]
pub struct TomlEntityContainer {
pub entities: Vec<TomlEntityDescription>,
}
impl RuntimeState { impl RuntimeState {
pub fn new() -> RuntimeState { pub fn new() -> RuntimeState {
// TODO: Hook this file to the gui
let mut file = fs::File::open("./conf/entity_spawns.toml").unwrap(); let mut file = fs::File::open("./conf/entity_spawns.toml").unwrap();
let mut content = String::new(); let mut content = String::new();
file.read_to_string(&mut content).unwrap(); file.read_to_string(&mut content).unwrap();
// TODO: gracefully fail
let mut settings : TomlEntityContainer = toml::from_str(content.as_str()).unwrap(); let mut settings : TomlEntityContainer = toml::from_str(content.as_str()).unwrap();
// settings
// // File::with_name(..) is shorthand for File::from(Path::new(..))
// .merge(File::with_name("conf/entity_spawns.toml"))
// .unwrap();
RuntimeState { RuntimeState {
config_db: settings, config_db: settings,
@@ -72,40 +93,8 @@ impl RuntimeState {
self.mesh_cache.get(mesh) self.mesh_cache.get(mesh)
} }
pub fn get_configured_entities(&mut self) -> Vec<EntityMeta> { pub fn get_entities(&mut self) -> Vec<TomlEntityDescription> {
let mut out = Vec::new(); self.config_db.entities.clone()
for entity in &self.config_db.entities {
let position = match &entity.position {
None => { None }
Some(pos) => {
Some(Position {
x: pos.x,
y: pos.y,
z: pos.z,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0)
}
})
}
};
// log::info!("{:?}", position);
// log::info!("{:?}", entity);
// log::info!("{:?}", entity.into_table());
// log::info!("{:?}", entity.into_array());
out.push(EntityMeta {
name: entity.name.clone(),
ent_type: entity.type_name.clone(),
mesh: entity.mesh.clone(),
position: position
});
}
out
} }
pub fn preload_meshes(&mut self, resources_path: PathBuf) { pub fn preload_meshes(&mut self, resources_path: PathBuf) {

View File

@@ -1,33 +1,119 @@
use std::f32::consts::PI;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Instant; use std::time::Instant;
use cgmath::{Euler, Quaternion, Deg, Rad, Point3}; use cgmath::{Deg, Euler, Point3, Quaternion, Rad};
use imgui::FontSource; use imgui::*;
use legion::*; use imgui::{Condition, FontSource, Ui};
use legion::IntoQuery;
use legion::systems::CommandBuffer; use legion::systems::CommandBuffer;
use legion::world::SubWorld; use legion::world::SubWorld;
use legion::IntoQuery;
use legion::*;
use nalgebra::Quaternion as naQuaternion; use nalgebra::Quaternion as naQuaternion;
use rapier3d::dynamics::{IntegrationParameters, JointSet, RigidBodyBuilder, RigidBodySet}; use rapier3d::dynamics::{
IntegrationParameters, JointSet, MassProperties, RigidBodyBuilder, RigidBodySet,
};
use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase}; use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase};
use rapier3d::na::{Isometry3, Vector, Vector3}; use rapier3d::na::{Isometry3, Vector, Vector3};
use rapier3d::pipeline::{ChannelEventCollector, PhysicsPipeline}; use rapier3d::pipeline::{ChannelEventCollector, PhysicsPipeline};
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::components::{Collider, LoopState, Mesh, Physics, Position}; use crate::components::{Collider, ImguiWindow, LoopState, Mesh, Physics, Position};
use crate::geometry::RawMesh; use crate::geometry::RawMesh;
use crate::physics::state::PhysicsState; use crate::physics::state::PhysicsState;
use crate::render::state::RenderState; use crate::render::state::RenderState;
use crate::render::system::{ImguiGenericOutputLine, ImguiPerformanceProfilerLine};
use crate::runtime::state::RuntimeState; use crate::runtime::state::RuntimeState;
use std::f32::consts::PI;
pub fn quad_color(color: [f32; 4]) -> [[f32; 4]; 4] {
[color, color, color, color]
}
#[system] #[system]
#[write_component(Mesh)] #[write_component(Mesh)]
pub fn runtime_load( pub fn runtime_load(
cmd: &mut CommandBuffer,
world: &mut SubWorld, world: &mut SubWorld,
#[resource] runtime_state: &mut RuntimeState, #[resource] runtime_state: &mut RuntimeState,
) { ) {
runtime_state.preload_meshes(PathBuf::from("./resources")); runtime_state.preload_meshes(PathBuf::from("./resources"));
let entity: Entity = cmd.push((ImguiWindow {
// a window that does everything for the performance profiler
window: || {
imgui::Window::new(im_str!("Performance Profiler"))
.size([400.0, 200.0], Condition::FirstUseEver)
.position([10.0, 10.0], Condition::FirstUseEver)
},
func: |ui: &Ui, a: Vec<&ImguiPerformanceProfilerLine>| {
// ui.text(im_str!("Performance Graph"));
let draw_list = ui.get_window_draw_list();
let top_left = ui.cursor_screen_pos();
let region_size = ui.content_region_avail();
let region_size = [region_size[0] * 0.80, region_size[1]];
// Fill rect
let qcolor = quad_color([0.5, 0.5, 1.0, 0.1]);
draw_list.add_rect_filled_multicolor(
top_left,
[top_left[0] + (region_size[0]), top_left[1] + region_size[1]],
qcolor[0],
qcolor[1],
qcolor[2],
qcolor[3],
);
for profiler_line in a {
let x_scale = (region_size[0]) / 400.0;
let y_scale = region_size[1] / profiler_line.scale_max;
profiler_line
.iter_data_from_head()
.fold((0, 0.0f32), |accum, &fps_val| {
let x1 = accum.0 as f32 * x_scale + top_left[0];
let y1 = top_left[1] + region_size[1] - accum.1 * y_scale;
let x2 = (accum.0 as f32 + 1.0) * x_scale + top_left[0];
let y2 = top_left[1] + region_size[1] - fps_val * y_scale;
let p1 = [x1, y1];
let p2 = [x2, y2];
draw_list
.add_line(p1, p2, [1.0, 1.0, 0.0, 0.8])
.thickness(1.0)
.build();
(accum.0 + 1, fps_val)
});
let text_x = (region_size[0] + top_left[0]);
let text_y = top_left[1] + region_size[1]
- profiler_line.current_average_label().0 * y_scale;
draw_list.add_text(
[text_x, text_y],
[1.0, 1.0, 0.0, 1.0],
format!(
"{} {:.0}",
profiler_line.current_average_label().1,
1.0 / profiler_line.current_average_label().0
),
);
}
},
},));
let entity: Entity = cmd.push((ImguiPerformanceProfilerLine::new("RenderFPS".to_string()),));
let entity: Entity = cmd.push((ImguiWindow {
// a window that does everything for the performance profiler
window: || {
imgui::Window::new(im_str!("Generic Output"))
.size([400.0, 500.0], Condition::FirstUseEver)
.position([50.0, 250.0], Condition::FirstUseEver)
},
func: |ui: &Ui, a: Vec<&ImguiGenericOutputLine>| {
for label in a {
ui.text(im_str!("{}", label.label));
}
},
},));
} }
#[system] #[system]
@@ -38,54 +124,48 @@ pub fn runtime_spawn(
#[resource] runtime_state: &mut RuntimeState, #[resource] runtime_state: &mut RuntimeState,
#[resource] renderer: &mut RenderState, #[resource] renderer: &mut RenderState,
) { ) {
for entity in &runtime_state.get_entities() {
for entity in runtime_state.get_configured_entities(){ match entity.type_name.as_ref() {
match entity.ent_type.as_ref() {
"PhysicsEntity" => { "PhysicsEntity" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.as_ref().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
continue; continue;
} }
Some(mesh) => mesh Some(mesh) => mesh,
}; };
let collider = ColliderBuilder::trimesh(
raw_mesh.vertices.iter().map(|v| v.position()).collect(),
raw_mesh.indices.clone(),
)
.build();
let collider = ColliderBuilder::capsule_y(2.0, 1.0).build();
let gpu_mesh_buffer = renderer
.upload_mesh_to_buffer(
raw_mesh,
Some(wgpu::Color {
r: 1.0,
g: 0.7,
b: 0.3,
a: 1.0,
}),
)
.unwrap();
let position = Position::from(entity.position.clone());
let mut dynamic_body = RigidBodyBuilder::new_dynamic() let mut dynamic_body = RigidBodyBuilder::new_dynamic()
.can_sleep(false) .can_sleep(false)
.mass(1.0) .mass(100.0)
.translation(0.0, 0.0, 0.0) .translation(position.x, position.y, position.z)
.build(); .build();
let collider = ColliderBuilder::trimesh(
raw_mesh.vertices
.iter()
.map(|v| v.position())
.collect(),
raw_mesh.indices.clone(),
).build();
let gpu_mesh_buffer = renderer.upload_mesh_to_buffer(
raw_mesh,
Some(wgpu::Color {
r: 1.0,
g: 0.7,
b: 0.3,
a: 1.0,
})
).unwrap();
let entity: Entity = cmd.push(( let entity: Entity = cmd.push((
Position { position,
x: 0.0,
y: 20.0,
z: 0.0,
rot: Euler {
x: Deg(25.0),
y: Deg(45.0),
z: Deg(15.0),
},
},
gpu_mesh_buffer, gpu_mesh_buffer,
Physics { Physics {
rigid_body: dynamic_body, rigid_body: dynamic_body,
@@ -95,52 +175,48 @@ pub fn runtime_spawn(
collider: collider, collider: collider,
collider_handle: None, collider_handle: None,
}, },
ImguiGenericOutputLine::new("wahoo! from a physics entity".to_string()),
)); ));
}, }
"Terrain" => { "Terrain" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.clone().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
continue; continue;
} }
Some(mesh) => mesh Some(mesh) => mesh,
}; };
let position = Position::from(entity.position.clone());
let mut static_body = RigidBodyBuilder::new_static() let mut static_body = RigidBodyBuilder::new_static()
.position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y())) .position(Isometry3::new(
Vector3::new(position.x, position.y, position.z),
Vector::y(),
))
.build(); .build();
let mesh_collider = ColliderBuilder::trimesh( let mesh_collider = ColliderBuilder::trimesh(
raw_mesh.vertices raw_mesh.vertices.iter().map(|v| v.position()).collect(),
.iter()
.map(|v| v.position())
.collect(),
raw_mesh.indices.clone(), raw_mesh.indices.clone(),
).build(); )
.build();
let gpu_mesh_buffer = renderer.upload_mesh_to_buffer(
raw_mesh,
Some(wgpu::Color {
r: 1.0,
g: 0.7,
b: 0.3,
a: 1.0,
})
).unwrap();
let gpu_mesh_buffer = renderer
.upload_mesh_to_buffer(
raw_mesh,
Some(wgpu::Color {
r: 1.0,
g: 0.7,
b: 0.3,
a: 1.0,
}),
)
.unwrap();
let entity: Entity = cmd.push(( let entity: Entity = cmd.push((
Position { position,
x: 0.0,
y: -8.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
gpu_mesh_buffer, gpu_mesh_buffer,
Physics { Physics {
rigid_body: static_body, rigid_body: static_body,
@@ -151,63 +227,52 @@ pub fn runtime_spawn(
collider_handle: None, collider_handle: None,
}, },
)); ));
}, }
"Camera" => { "Camera" => {
let position = Position::from(entity.position.clone());
let entity: Entity = cmd.push(( let entity: Entity = cmd.push((
Camera { Camera {
position: cgmath::Point3 { position: cgmath::Point3 {
x: 0.0, x: position.x,
y: 0.0, y: position.y,
z: 10.0, z: position.z,
}, },
yaw: Rad(-PI), yaw: Rad(PI / 2.0),
pitch: Rad(PI / 2.0), pitch: Rad(PI / 2.0 + 25.0),
}, },
CameraController::new(3.0, 1.0), CameraController::new(5.0, 1.0),
ImguiGenericOutputLine::new("wahoo! from a camera".to_string()),
)); ));
}, }
"Light" => { "Light" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.clone().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
continue; continue;
} }
Some(mesh) => mesh Some(mesh) => mesh,
}; };
let gpu_mesh_buffer = renderer.upload_mesh_to_buffer( let position = Position::from(entity.position.clone());
raw_mesh,
Some(wgpu::Color {
r: 1.0,
g: 0.7,
b: 0.3,
a: 1.0,
})
).unwrap();
let light_entity: Entity = cmd.push(( let gpu_mesh_buffer = renderer
Position { .upload_mesh_to_buffer(
x: 5.0, raw_mesh,
y: 10.0, Some(wgpu::Color {
z: 5.0, r: 1.0,
rot: Euler { g: 0.7,
x: Deg(0.0), b: 0.3,
y: Deg(-25.0), a: 1.0,
z: Deg(0.0), }),
}, )
}, .unwrap();
gpu_mesh_buffer,
renderer.create_light(), let light_entity: Entity =
)); cmd.push((position, gpu_mesh_buffer, renderer.create_light()));
} }
_ => {}
_ => {},
} }
} }
} }