cyborg/src/main.rs

319 lines
10 KiB
Rust
Raw Normal View History

2022-05-11 19:00:30 +00:00
use cyborg::camera::Camera;
use cyborg::pass::{mesh, RenderPassBox};
2022-04-28 03:14:58 +00:00
use cyborg::shader;
use cyborg::storage::mesh::*;
2022-05-11 19:00:30 +00:00
use cyborg::viewport::*;
use cyborg::Renderer;
use legion::*;
2022-05-12 19:35:59 +00:00
use rand::prelude::*;
2022-04-18 23:40:51 +00:00
use std::sync::Arc;
use winit::{
event::*,
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
2022-04-18 07:59:26 +00:00
2022-05-12 19:35:59 +00:00
struct DeltaTime {
pub dt: f32,
last_update: std::time::Instant,
}
impl Default for DeltaTime {
fn default() -> Self {
DeltaTime {
dt: 0.0,
last_update: std::time::Instant::now(),
}
}
}
struct SpawnDistributions {
theta: rand::distributions::Uniform<f32>,
radius: rand::distributions::Uniform<f32>,
up: rand::distributions::Uniform<f32>,
}
impl Default for SpawnDistributions {
fn default() -> Self {
Self {
theta: rand::distributions::Uniform::new(0.0, std::f32::consts::TAU),
radius: rand::distributions::Uniform::new(4.0, 5.0),
up: rand::distributions::Uniform::new(10.0, 15.0),
}
}
}
struct Particle {
position: glam::Vec3A,
mass: f32,
}
struct Velocity {
linear: glam::Vec3A,
}
#[system]
fn update_dt(#[resource] dt: &mut DeltaTime) {
dt.dt = dt.last_update.elapsed().as_secs_f32();
dt.last_update = std::time::Instant::now();
}
#[system(for_each)]
fn apply_gravity(#[resource] dt: &DeltaTime, velocity: &mut Velocity) {
const GRAVITY: f32 = 6.0;
velocity.linear.y -= GRAVITY * dt.dt;
}
#[system(for_each)]
fn move_particles(#[resource] dt: &DeltaTime, particle: &mut Particle, velocity: &Velocity) {
particle.position += velocity.linear * (dt.dt / particle.mass);
// TODO angular velocity
}
#[system(for_each)]
fn respawn_particles(
#[resource] distributions: &SpawnDistributions,
particle: &mut Particle,
velocity: &mut Velocity,
) {
if particle.position.y < -10.0 {
particle.position = glam::Vec3A::ZERO;
let rng = &mut rand::thread_rng();
velocity.linear.y = distributions.up.sample(rng);
let theta = distributions.theta.sample(rng);
let radius = distributions.radius.sample(rng);
velocity.linear.x = theta.sin() * radius;
velocity.linear.z = theta.cos() * radius;
}
}
#[system(for_each)]
fn update_transforms(transform: &mut cyborg::scene::Transform, particle: &Particle) {
transform.transform = glam::Mat4::from_translation(particle.position.into());
}
#[system(for_each)]
fn update_debug(
draw_list: &mut cyborg::scene::DebugDrawList,
velocity: &Velocity,
) {
draw_list.clear();
draw_list.indices.extend_from_slice(&[0, 1]);
let color = [1.0, 1.0, 1.0];
draw_list.vertices.push(cyborg::scene::DebugVertex {
position: [0.0, 0.0, 0.0],
color,
});
draw_list.vertices.push(cyborg::scene::DebugVertex {
position: velocity.linear.to_array(),
color,
});
}
fn build_update_schedule() -> Schedule {
let mut builder = Schedule::builder();
builder.add_system(update_dt_system());
builder.add_system(apply_gravity_system());
builder.add_system(move_particles_system());
builder.add_system(respawn_particles_system());
builder.add_system(update_transforms_system());
builder.add_system(update_debug_system());
builder.build()
}
2022-04-05 04:21:14 +00:00
fn main() {
2022-04-18 07:59:26 +00:00
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
2022-05-11 19:10:46 +00:00
let viewport = pollster::block_on(WinitViewport::from_window(&window));
2022-04-18 07:59:26 +00:00
2022-05-11 19:00:30 +00:00
let mut world = World::new(Default::default());
let mut resources = Resources::default();
2022-05-12 19:35:59 +00:00
resources.insert::<DeltaTime>(Default::default());
resources.insert::<SpawnDistributions>(Default::default());
let mut update_schedule = build_update_schedule();
2022-05-11 19:00:30 +00:00
let renderer = Renderer::new(viewport.device.clone(), viewport.queue.clone());
resources.insert(renderer);
2022-04-23 03:42:33 +00:00
2022-05-11 19:00:30 +00:00
resources.insert(viewport.get_info().to_owned());
2022-04-23 03:42:33 +00:00
2022-05-11 19:00:30 +00:00
let mut flycam = cyborg::camera::Flycam::new(0.002, 10.0, 0.25);
let mut is_grabbed = false;
2022-04-28 03:14:58 +00:00
2022-05-11 19:00:30 +00:00
let shader_store = Arc::new(shader::ShaderStore::new(viewport.device.clone()));
2022-04-28 03:14:58 +00:00
let shaders_dir = std::env::current_dir().unwrap();
let shaders_dir = shaders_dir.join("shaders/");
let shader_watcher = shader::ShaderWatcher::new(shader_store.to_owned(), shaders_dir).unwrap();
2022-04-28 03:14:58 +00:00
let mesh_forward = shader_watcher.add_file("mesh_forward.wgsl").unwrap();
let mesh_skinning = shader_watcher.add_file("mesh_skinning.wgsl").unwrap();
2022-05-11 19:00:30 +00:00
let mesh_shaders = mesh::ShaderInfo {
store: shader_store.clone(),
forward: mesh_forward,
skinning: mesh_skinning,
};
2022-05-11 19:00:30 +00:00
resources.insert(mesh_shaders);
let mut render_schedule = Schedule::builder();
cyborg::legion::build_renderer(&mut resources, &mut render_schedule);
let mut render_schedule = render_schedule.build();
2022-04-23 03:42:33 +00:00
let example_vertices = vec![
2022-05-11 19:00:30 +00:00
mesh::Vertex {
position: [-0.5, 0.0, 0.5],
tan_frame: 0,
},
2022-05-11 19:00:30 +00:00
mesh::Vertex {
position: [0.5, 0.0, 0.5],
tan_frame: 0,
},
2022-05-11 19:00:30 +00:00
mesh::Vertex {
position: [0.0, -0.5, -0.5],
tan_frame: 0,
},
mesh::Vertex {
position: [0.0, 0.5, -0.5],
tan_frame: 0,
},
];
2022-05-11 19:00:30 +00:00
let mesh_pass = resources.get::<RenderPassBox<mesh::MeshPass>>().unwrap();
let attributes = mesh_pass.get_attributes();
2022-05-11 19:00:30 +00:00
let example_vertices = AttrBuffer {
id: attributes.vertex,
count: example_vertices.len(),
data: bytemuck::cast_slice(&example_vertices).to_vec(),
};
2022-05-12 19:35:59 +00:00
let example_indices: Vec<mesh::Index> = vec![0, 1, 2, 1, 2, 3, 2, 3, 0, 0, 1, 3];
let example_indices = AttrBuffer {
id: attributes.index,
count: example_indices.len(),
data: bytemuck::cast_slice(&example_indices).to_vec(),
};
let mut example_mesh = MeshBuffer::default();
example_mesh.attributes.push(example_vertices);
example_mesh.attributes.push(example_indices);
let example_mesh = mesh_pass.get_mesh_pool().load(example_mesh).unwrap();
2022-05-11 19:00:30 +00:00
drop(mesh_pass);
2022-05-12 19:35:59 +00:00
let r = 6;
for x in -r..r {
for y in -r..r {
for z in -r..r {
let translation = glam::Vec3::new(x as f32, y as f32, z as f32);
let transform = glam::Mat4::from_translation(translation);
2022-05-11 19:00:30 +00:00
world.push((
2022-05-12 14:16:32 +00:00
cyborg::scene::Mesh {
2022-05-11 19:00:30 +00:00
mesh: example_mesh.clone(),
},
2022-05-11 20:44:44 +00:00
cyborg::scene::Transform { transform },
2022-05-12 19:35:59 +00:00
cyborg::scene::DebugDrawList::default(),
Particle {
position: translation.into(),
mass: 1.0,
},
Velocity {
linear: glam::Vec3A::ZERO,
},
2022-05-11 19:00:30 +00:00
));
}
}
}
2022-05-11 19:00:30 +00:00
let viewport_entity = world.push((viewport, flycam.get_camera()));
2022-04-05 04:21:14 +00:00
2022-04-18 07:59:26 +00:00
event_loop.run(move |event, _, control_flow| match event {
2022-04-18 08:21:19 +00:00
Event::RedrawRequested(_) => {
2022-05-11 19:00:30 +00:00
let mut viewport_entry = world.entry_mut(viewport_entity).unwrap();
let viewport = viewport_entry.get_component_mut::<WinitViewport>().unwrap();
2022-04-25 02:44:51 +00:00
match viewport.acquire() {
2022-04-18 23:40:51 +00:00
Err(wgpu::SurfaceError::Lost) => viewport.resize(viewport.size),
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(e) => eprintln!("error: {:?}", e),
Ok(_) => {
2022-05-11 19:00:30 +00:00
render_schedule.execute(&mut world, &mut resources);
2022-04-25 02:44:51 +00:00
}
}
2022-04-18 08:21:19 +00:00
}
Event::MainEventsCleared => {
2022-05-12 19:35:59 +00:00
update_schedule.execute(&mut world, &mut resources);
shader_watcher.watch();
flycam.update();
2022-04-18 08:21:19 +00:00
window.request_redraw();
2022-05-11 19:00:30 +00:00
let mut viewport_entry = world.entry_mut(viewport_entity).unwrap();
let camera = viewport_entry.get_component_mut::<Camera>().unwrap();
let _ = std::mem::replace(camera, flycam.get_camera());
2022-04-18 08:21:19 +00:00
}
2022-04-23 03:42:33 +00:00
Event::DeviceEvent { ref event, .. } => match event {
DeviceEvent::MouseMotion { delta } => {
if is_grabbed {
flycam.process_mouse(delta.0, delta.1);
2022-04-23 03:42:33 +00:00
}
}
_ => {}
},
2022-04-18 07:59:26 +00:00
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => match event {
2022-04-23 03:42:33 +00:00
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => {
if *state == ElementState::Pressed && *key == VirtualKeyCode::Escape {
if is_grabbed {
window.set_cursor_grab(false).unwrap();
window.set_cursor_visible(true);
is_grabbed = false;
}
} else {
flycam.process_keyboard(*key, *state);
2022-04-23 03:42:33 +00:00
}
}
WindowEvent::MouseInput {
button: MouseButton::Left,
state: ElementState::Pressed,
..
} => {
if !is_grabbed {
window.set_cursor_grab(true).unwrap();
window.set_cursor_visible(false);
is_grabbed = true;
}
}
2022-04-18 07:59:26 +00:00
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
2022-04-18 23:40:51 +00:00
WindowEvent::Resized(physical_size) => {
2022-05-11 19:00:30 +00:00
let mut viewport_entry = world.entry_mut(viewport_entity).unwrap();
let viewport = viewport_entry.get_component_mut::<WinitViewport>().unwrap();
2022-04-18 23:40:51 +00:00
viewport.resize(*physical_size);
2022-05-11 19:10:46 +00:00
flycam.resize(physical_size.width, physical_size.height);
2022-04-18 23:40:51 +00:00
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
2022-05-11 19:00:30 +00:00
let mut viewport_entry = world.entry_mut(viewport_entity).unwrap();
let viewport = viewport_entry.get_component_mut::<WinitViewport>().unwrap();
2022-04-18 23:40:51 +00:00
viewport.resize(**new_inner_size);
2022-05-11 19:10:46 +00:00
flycam.resize(new_inner_size.width, new_inner_size.height);
2022-04-18 23:40:51 +00:00
}
2022-04-18 07:59:26 +00:00
_ => {}
2022-04-18 23:40:51 +00:00
},
2022-04-18 07:59:26 +00:00
_ => {}
});
2022-04-05 04:21:14 +00:00
}