cyborg/src/main.rs

248 lines
7.0 KiB
Rust

use winit::{
event::*,
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
mod camera;
mod commands;
mod handle;
mod mesh;
mod model;
mod pool;
mod renderer;
mod scene;
mod shader;
use camera::*;
use model::*;
use renderer::Renderer;
use scene::*;
trait WorldState {
fn update(&mut self);
fn render(&self) -> Vec<MeshInstance>;
}
struct Grid {
meshes: Vec<MeshInstance>,
}
impl Grid {
fn new(ren: &mut Renderer) -> Self {
let model = GltfModel::load(ren);
let mut meshes = Vec::new();
for x in -5..5 {
for y in -5..5 {
let translation = glam::Vec3::new(x as f32, 0.0, y as f32) * 3.0;
let transform = glam::Mat4::from_translation(translation);
model.draw(&mut meshes, transform);
}
}
Self { meshes }
}
}
impl WorldState for Grid {
fn update(&mut self) {}
fn render(&self) -> Vec<MeshInstance> {
self.meshes.clone()
}
}
struct Planet {
speed: f32,
offset: f32,
radius: f32,
size: f32,
}
struct Planets {
start: std::time::Instant,
planets: Vec<Planet>,
model: GltfModel,
}
impl Planets {
fn new(ren: &mut Renderer) -> Self {
let start = std::time::Instant::now();
let model = GltfModel::load(ren);
let mut planets = Vec::new();
for i in 0..10 {
let i = i as f32;
planets.push(Planet {
speed: 1.618 * 1.5 / i,
offset: 0.0,
radius: i * 2.0,
size: 0.5,
});
}
Self {
start,
planets,
model,
}
}
}
impl WorldState for Planets {
fn update(&mut self) {}
fn render(&self) -> Vec<MeshInstance> {
let elapsed = self.start.elapsed().as_secs_f32();
let mut meshes = Vec::new();
for planet in self.planets.iter() {
let translation = glam::Vec3::new(0.0, 0.0, planet.radius);
let translation = glam::Mat4::from_translation(translation);
let theta = planet.speed * elapsed + planet.offset;
let rotation = glam::Mat4::from_rotation_y(theta);
self.model.draw(&mut meshes, rotation * translation);
}
meshes
}
}
async fn make_window_renderer(window: &winit::window::Window) -> Renderer {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::LowPower,
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await
.unwrap();
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
label: None,
},
None,
)
.await
.unwrap();
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
surface.configure(&device, &config);
Renderer::new(size, surface, device, queue, config)
}
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
let mut camera = Flycam::new(0.002, 10.0, 0.25);
let mut is_grabbed = false;
let mut ren = pollster::block_on(make_window_renderer(&window));
// let mut state: Box<dyn WorldState> = Box::new(Planets::new(&mut ren));
let mut state: Box<dyn WorldState> = Box::new(Grid::new(&mut ren));
let lights = vec![
PointLight {
center: glam::Vec3A::new(0.0, 5.0, 0.0),
intensity: glam::Vec3A::new(100.0, 100.0, 100.0),
},
PointLight {
center: glam::Vec3A::new(-7.0, 5.0, 7.0),
intensity: glam::Vec3A::new(100.0, 0.0, 0.0),
},
PointLight {
center: glam::Vec3A::new(7.0, 5.0, 7.0),
intensity: glam::Vec3A::new(0.0, 100.0, 0.0),
},
PointLight {
center: glam::Vec3A::new(0.0, 5.0, -7.0),
intensity: glam::Vec3A::new(0.0, 0.0, 100.0),
},
];
event_loop.run(move |event, _, control_flow| match event {
Event::RedrawRequested(_) => {
let scene = Scene { meshes: &state.render(), point_lights: &lights };
match ren.render(&camera, &scene) {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost) => ren.resize(ren.size),
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(e) => println!("error: {:?}", e),
};
},
Event::MainEventsCleared => {
camera.update();
state.update();
window.request_redraw();
}
Event::DeviceEvent { ref event, .. } => match event {
DeviceEvent::MouseMotion { delta } => {
if is_grabbed {
camera.process_mouse(delta.0, delta.1);
}
}
_ => {}
},
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => match event {
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 {
camera.process_keyboard(*key, *state);
}
}
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;
}
}
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(physical_size) => {
ren.resize(*physical_size);
camera.resize(physical_size.width, physical_size.height);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
ren.resize(**new_inner_size);
camera.resize(new_inner_size.width, new_inner_size.height);
}
_ => {}
},
_ => {}
});
}