Implemented 3D support and camera
This commit is contained in:
parent
03c061839c
commit
08e49e1b22
@ -36,7 +36,7 @@ pub async fn run() {
|
||||
sim.step(dt * timewarp as f64);
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_millis(1));
|
||||
thread::sleep(Duration::from_nanos(1));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
57
solar_engine/src/camera.rs
Normal file
57
solar_engine/src/camera.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use cgmath::{Matrix4, Point3, Vector3, Deg, perspective, InnerSpace, Rotation, Quaternion, Rotation3, Rad};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Camera {
|
||||
pub eye: Point3<f32>,
|
||||
pub target: Point3<f32>,
|
||||
pub up: Vector3<f32>,
|
||||
pub fov_y: Deg<f32>,
|
||||
pub aspect: f32,
|
||||
pub znear: f32,
|
||||
pub zfar: f32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(aspect: f32) -> Self {
|
||||
Self {
|
||||
eye: Point3::new(0.0, 0.0, 5.0),
|
||||
target: Point3::new(0.0, 0.0, 0.0),
|
||||
up: Vector3::unit_y(),
|
||||
fov_y: Deg(45.0),
|
||||
aspect,
|
||||
znear: 0.1,
|
||||
zfar: 100.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_view_projection_matrix(&self) -> Matrix4<f32> {
|
||||
let view = Matrix4::look_at_rh(self.eye, self.target, self.up);
|
||||
let proj = perspective(self.fov_y, self.aspect, self.znear, self.zfar);
|
||||
proj * view
|
||||
}
|
||||
|
||||
pub fn rotate_yaw_pitch(&mut self, yaw: f32, pitch: f32) {
|
||||
let dir = (self.target - self.eye).normalize();
|
||||
|
||||
let horizontal = Vector3::unit_y().cross(dir).normalize();
|
||||
let vertical = horizontal.cross(dir).normalize();
|
||||
|
||||
let pitch_q = Quaternion::from_axis_angle(vertical, Rad(pitch.to_radians()));
|
||||
let yaw_q = Quaternion::from_axis_angle(Vector3::unit_y(), Rad(yaw.to_radians()));
|
||||
|
||||
let rotation = yaw_q * pitch_q;
|
||||
let rotated = rotation.rotate_vector(dir).normalize();
|
||||
|
||||
let distance = (self.target - self.eye).magnitude();
|
||||
self.eye = self.target - rotated * distance;
|
||||
}
|
||||
|
||||
pub fn zoom(&mut self, amount: f32) {
|
||||
let dir = (self.target - self.eye).normalize();
|
||||
self.eye += dir * amount;
|
||||
}
|
||||
|
||||
pub fn set_aspect(&mut self, aspect: f32) {
|
||||
self.aspect = aspect;
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ mod state;
|
||||
mod render;
|
||||
mod application;
|
||||
mod input;
|
||||
mod camera;
|
||||
|
||||
pub use body::Body;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct Globals {
|
||||
pub(crate) aspect_ratio: f32,
|
||||
pub view_proj: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
|
||||
@ -17,7 +17,7 @@ struct VSOutput {
|
||||
};
|
||||
|
||||
struct Globals {
|
||||
aspect_ratio: f32,
|
||||
view_proj: mat4x4<f32>,
|
||||
}
|
||||
|
||||
@group(0) @binding(0)
|
||||
@ -32,14 +32,7 @@ fn vs_main(vertex: VertexInput, instance: InstanceInput) -> VSOutput {
|
||||
instance.model_row2,
|
||||
instance.model_row3
|
||||
);
|
||||
|
||||
let projection = mat4x4<f32>(
|
||||
vec4<f32>(1.0 / globals.aspect_ratio, 0.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||
vec4<f32>(0.0, 0.0, 0.0, 1.0),
|
||||
);
|
||||
out.position = projection * model * vec4<f32>(vertex.position, 1.0);
|
||||
out.position = globals.view_proj * model * vec4<f32>(vertex.position, 1.0);
|
||||
out.color = instance.color;
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
use std::cmp::max;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc};
|
||||
use cgmath::{perspective, Deg, Matrix4, Point3, Vector3};
|
||||
use log::info;
|
||||
use pollster::FutureExt;
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu::{Adapter, Device, Instance, PresentMode, Queue, Surface, SurfaceCapabilities, SurfaceConfiguration};
|
||||
use winit::dpi::PhysicalSize;
|
||||
use winit::window::{Window};
|
||||
use crate::camera::Camera;
|
||||
use crate::render::{create_circle_vertices, Geometry, Globals, InstanceRaw, RenderInstance, SampleCount, Shape, Vertex};
|
||||
|
||||
pub struct State<'a> {
|
||||
@ -27,6 +29,8 @@ pub struct State<'a> {
|
||||
geometries: HashMap<Shape, Geometry>,
|
||||
global_bind_group: wgpu::BindGroup,
|
||||
global_buffer: wgpu::Buffer,
|
||||
|
||||
camera: Camera,
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
@ -44,8 +48,12 @@ impl<'a> State<'a> {
|
||||
let sample_count = SampleCount(Self::probe_msaa_support(&device, &config));
|
||||
info!("MSAA sample count: {}", sample_count.0);
|
||||
|
||||
let aspect = config.width as f32 / config.height as f32;
|
||||
let camera = Camera::new(aspect);
|
||||
let view_proj = camera.build_view_projection_matrix();
|
||||
|
||||
let globals = Globals {
|
||||
aspect_ratio: config.width as f32 / config.height as f32,
|
||||
view_proj: view_proj.into(),
|
||||
};
|
||||
let global_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Global Uniform Buffer"),
|
||||
@ -99,6 +107,7 @@ impl<'a> State<'a> {
|
||||
global_buffer,
|
||||
instances,
|
||||
instance_buffer,
|
||||
camera,
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,8 +297,11 @@ impl<'a> State<'a> {
|
||||
|
||||
self.surface.configure(&self.device, &self.config);
|
||||
|
||||
self.camera.set_aspect(self.config.width as f32 / self.config.height as f32);
|
||||
let view_proj = self.camera.build_view_projection_matrix();
|
||||
|
||||
let new_globals = Globals {
|
||||
aspect_ratio: self.config.width as f32 / self.config.height as f32,
|
||||
view_proj: view_proj.into(),
|
||||
};
|
||||
self.queue.write_buffer(&self.global_buffer, 0, bytemuck::cast_slice(&[new_globals]));
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user