update threed

This commit is contained in:
Robin Appelman 2022-12-06 16:21:03 +01:00
commit 89529579be
4 changed files with 133 additions and 102 deletions

View file

@ -15,9 +15,9 @@ bytemuck = { version = "1.12.3", features = ["derive"] }
cgmath = "0.18.0" cgmath = "0.18.0"
[dev-dependencies] [dev-dependencies]
three-d = "0.10.2" three-d = { version = "0.14.0", features = ["egui-gui"] }
miette = { version = "4.7.1", features = ["fancy"] } miette = { version = "5.5.0", features = ["fancy"] }
criterion = "0.3" criterion = "0.4.0"
iai = "0.1" iai = "0.1"
[[bench]] [[bench]]

View file

@ -4,7 +4,6 @@ use std::path::PathBuf;
use vmdl::mdl::Mdl; use vmdl::mdl::Mdl;
use vmdl::vtx::Vtx; use vmdl::vtx::Vtx;
use vmdl::vvd::Vvd; use vmdl::vvd::Vvd;
use vmdl::Model;
fn main() -> Result<(), vmdl::ModelError> { fn main() -> Result<(), vmdl::ModelError> {
let mut args = args(); let mut args = args();
@ -14,9 +13,9 @@ fn main() -> Result<(), vmdl::ModelError> {
let data = fs::read(&path)?; let data = fs::read(&path)?;
let mdl = Mdl::read(&data)?; let mdl = Mdl::read(&data)?;
let data = fs::read(path.with_extension("dx90.vtx"))?; let data = fs::read(path.with_extension("dx90.vtx"))?;
let vtx = Vtx::read(&data)?; let _vtx = Vtx::read(&data)?;
let data = fs::read(path.with_extension("vvd"))?; let data = fs::read(path.with_extension("vvd"))?;
let vvd = Vvd::read(&data)?; let _vvd = Vvd::read(&data)?;
dbg!(mdl.body_parts); dbg!(mdl.body_parts);
// let model = Model::from_parts(mdl, vtx, vvd); // let model = Model::from_parts(mdl, vtx, vvd);

View file

@ -16,6 +16,20 @@ enum Error {
Mdl(#[from] vmdl::ModelError), Mdl(#[from] vmdl::ModelError),
#[error(transparent)] #[error(transparent)]
IO(#[from] std::io::Error), IO(#[from] std::io::Error),
#[error(transparent)]
Render(#[from] RendererError),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum DebugType {
POSITION,
NORMAL,
COLOR,
DEPTH,
ORM,
UV,
NONE,
} }
fn main() -> Result<(), Error> { fn main() -> Result<(), Error> {
@ -33,25 +47,32 @@ fn main() -> Result<(), Error> {
..Default::default() ..Default::default()
}) })
.unwrap(); .unwrap();
let context = window.gl().unwrap(); let context = window.gl();
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
let mut camera = Camera::new_perspective( let mut camera = Camera::new_perspective(
&context, window.viewport(),
window.viewport().unwrap(),
vec3(2.0, 2.0, 5.0), vec3(2.0, 2.0, 5.0),
vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0), vec3(0.0, 1.0, 0.0),
degrees(90.0), degrees(90.0),
0.01, 0.01,
300.0, 300.0,
) );
.unwrap();
let mut control = OrbitControl::new(*camera.target(), 1.0, 100.0); let mut control = OrbitControl::new(*camera.target(), 1.0, 100.0);
let mut gui = three_d::GUI::new(&context).unwrap(); let mut gui = three_d::GUI::new(&context);
let cpu_mesh = model_to_mesh(&model); let cpu_mesh = model_to_mesh(&model);
let material = PhysicalMaterial { let ph_material = PhysicalMaterial {
albedo: Color {
r: 128,
g: 128,
b: 128,
a: 255,
},
..Default::default()
};
let material = CpuMaterial {
albedo: Color { albedo: Color {
r: 128, r: 128,
g: 128, g: 128,
@ -61,25 +82,24 @@ fn main() -> Result<(), Error> {
..Default::default() ..Default::default()
}; };
let mut model = three_d::Model::new_with_material(&context, &cpu_mesh, material)?; let model: three_d::Model<PhysicalMaterial> = three_d::Model::new(&context, &CpuModel {
model.set_transformation(Mat4::from_angle_x(degrees(-90.0))); materials: vec![material],
geometries: vec![cpu_mesh],
})?;
let mut lights = Lights { let mut directional = [
ambient: Some(AmbientLight { DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(1.0, -1.0, 0.0)),
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(1.0, 1.0, 0.0)),
];
let mut ambient = AmbientLight {
color: Color::WHITE, color: Color::WHITE,
intensity: 0.2, intensity: 0.2,
..Default::default() ..Default::default()
}),
directional: vec![
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(1.0, -1.0, 0.0))?,
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(1.0, 1.0, 0.0))?,
],
..Default::default()
}; };
// main loop // main loop
let mut shadows_enabled = true; let mut shadows_enabled = true;
let mut directional_intensity = lights.directional[0].intensity(); let mut directional_intensity = directional[0].intensity;
let mut depth_max = 30.0; let mut depth_max = 30.0;
let mut fov = 60.0; let mut fov = 60.0;
let mut debug_type = DebugType::NONE; let mut debug_type = DebugType::NONE;
@ -88,26 +108,26 @@ fn main() -> Result<(), Error> {
let mut change = frame_input.first_frame; let mut change = frame_input.first_frame;
let mut panel_width = frame_input.viewport.width; let mut panel_width = frame_input.viewport.width;
change |= gui change |= gui
.update(&mut frame_input, |gui_context| { .update(&mut frame_input.events, frame_input.accumulated_time, frame_input.viewport, frame_input.device_pixel_ratio, |gui_context| {
use three_d::egui::*; use three_d::egui::*;
SidePanel::left("side_panel").show(gui_context, |ui| { SidePanel::left("side_panel").show(gui_context, |ui| {
ui.heading("Debug Panel"); ui.heading("Debug Panel");
ui.label("Light options"); ui.label("Light options");
ui.add( ui.add(
Slider::new(&mut lights.ambient.as_mut().unwrap().intensity, 0.0..=1.0) Slider::new(&mut ambient.intensity, 0.0..=1.0)
.text("Ambient intensity"), .text("Ambient intensity"),
); );
ui.add( ui.add(
Slider::new(&mut directional_intensity, 0.0..=1.0) Slider::new(&mut directional_intensity, 0.0..=1.0)
.text("Directional intensity"), .text("Directional intensity"),
); );
lights.directional[0].set_intensity(directional_intensity); directional[0].intensity = directional_intensity;
lights.directional[1].set_intensity(directional_intensity); directional[1].intensity = directional_intensity;
if ui.checkbox(&mut shadows_enabled, "Shadows").clicked() { if ui.checkbox(&mut shadows_enabled, "Shadows").clicked() {
if !shadows_enabled { if !shadows_enabled {
lights.directional[0].clear_shadow_map(); directional[0].clear_shadow_map();
lights.directional[1].clear_shadow_map(); directional[1].clear_shadow_map();
} }
} }
@ -129,8 +149,7 @@ fn main() -> Result<(), Error> {
ui.add(Label::new(format!("\tz: {}", camera.position().z))); ui.add(Label::new(format!("\tz: {}", camera.position().z)));
}); });
panel_width = gui_context.used_size().x as u32; panel_width = gui_context.used_size().x as u32;
}) });
.unwrap();
let viewport = Viewport { let viewport = Viewport {
x: panel_width as i32, x: panel_width as i32,
@ -138,74 +157,77 @@ fn main() -> Result<(), Error> {
width: frame_input.viewport.width - panel_width, width: frame_input.viewport.width - panel_width,
height: frame_input.viewport.height, height: frame_input.viewport.height,
}; };
change |= camera.set_viewport(viewport).unwrap(); change |= camera.set_viewport(viewport);
change |= control change |= control
.handle_events(&mut camera, &mut frame_input.events) .handle_events(&mut camera, &mut frame_input.events);
.unwrap();
// Draw // Draw
{ {
camera camera
.set_perspective_projection(degrees(fov), camera.z_near(), camera.z_far()) .set_perspective_projection(degrees(fov), camera.z_near(), camera.z_far());
.unwrap();
if shadows_enabled { if shadows_enabled {
lights.directional[0] directional[0]
.generate_shadow_map(4.0, 1024, 1024, &[&model]) .generate_shadow_map(1024, model.iter().map(|gm| &gm.geometry));
.unwrap(); directional[1]
lights.directional[1] .generate_shadow_map(1024, model.iter().map(|gm| &gm.geometry));
.generate_shadow_map(4.0, 1024, 1024, &[&model])
.unwrap();
} }
let lights = &[
&ambient as &dyn Light,
&directional[0],
&directional[1],
];
// Light pass // Light pass
Screen::write(&context, ClearState::default(), || { let screen = frame_input.screen();
let target = screen.clear(ClearState::default());
match debug_type { match debug_type {
DebugType::NORMAL => { DebugType::NORMAL => {
model.render_with_material( target.render_with_material(
&NormalMaterial::from_physical_material(&model.material), &NormalMaterial::from_physical_material(&ph_material),
&camera, &camera,
&lights, model.iter().map(|gm| &gm.geometry),
)?; lights,
)
} }
DebugType::DEPTH => { DebugType::DEPTH => {
let mut depth_material = DepthMaterial::default(); let mut depth_material = DepthMaterial::default();
depth_material.max_distance = Some(depth_max); depth_material.max_distance = Some(depth_max);
model.render_with_material(&depth_material, &camera, &lights)?; target.render_with_material(&depth_material, &camera, model.iter().map(|gm| &gm.geometry), lights)
} }
DebugType::ORM => { DebugType::ORM => {
model.render_with_material( target.render_with_material(
&ORMMaterial::from_physical_material(&model.material), &ORMMaterial::from_physical_material(&ph_material),
&camera, &camera,
&lights, model.iter().map(|gm| &gm.geometry),
)?; lights,
)
} }
DebugType::POSITION => { DebugType::POSITION => {
let position_material = PositionMaterial::default(); let position_material = PositionMaterial::default();
model.render_with_material(&position_material, &camera, &lights)?; target.render_with_material(&position_material, &camera, model.iter().map(|gm| &gm.geometry), lights)
} }
DebugType::UV => { DebugType::UV => {
let uv_material = UVMaterial::default(); let uv_material = UVMaterial::default();
model.render_with_material(&uv_material, &camera, &lights)?; target.render_with_material(&uv_material, &camera, model.iter().map(|gm| &gm.geometry), lights)
} }
DebugType::COLOR => { DebugType::COLOR => {
model.render_with_material( target.render_with_material(
&ColorMaterial::from_physical_material(&model.material), &ColorMaterial::from_physical_material(&ph_material),
&camera, &camera,
&lights, model.iter().map(|gm| &gm.geometry),
)?; lights,
)
} }
DebugType::NONE => forward_pipeline.render_pass(&camera, &[&model], &lights)?, DebugType::NONE => target.render(&camera, &model, lights),
}; }.write(|| gui.render());
gui.render()?;
Ok(())
})
.unwrap();
} }
let _ = change; let _ = change;
FrameOutput::default() FrameOutput::default()
})?; });
Ok(()) Ok(())
} }
@ -223,7 +245,7 @@ fn load(path: &Path) -> Result<Model, vmdl::ModelError> {
// 1 hammer unit is ~1.905cm // 1 hammer unit is ~1.905cm
const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0); const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
fn model_to_mesh(model: &Model) -> CPUMesh { fn model_to_mesh(model: &Model) -> CpuMesh {
let offset = model let offset = model
.vertices() .vertices()
.iter() .iter()
@ -236,19 +258,17 @@ fn model_to_mesh(model: &Model) -> CPUMesh {
z: -offset / 2.0, z: -offset / 2.0,
}; };
let positions: Vec<f32> = model let positions: Vec<Vec3> = model
.vertices() .vertices()
.iter() .iter()
.flat_map(|vertex| { .map(|vertex| {
(vertex.position + offset) ((vertex.position + offset) * UNIT_SCALE * 10.0).into()
.iter()
.map(|pos| pos * UNIT_SCALE * 10.0)
}) })
.collect(); .collect();
let normals: Vec<f32> = model let normals: Vec<Vec3> = model
.vertices() .vertices()
.iter() .iter()
.flat_map(|vertex| vertex.normal.iter()) .map(|vertex| vertex.normal.into())
.collect(); .collect();
let indices = Indices::U32( let indices = Indices::U32(
model model
@ -257,10 +277,10 @@ fn model_to_mesh(model: &Model) -> CPUMesh {
.collect(), .collect(),
); );
CPUMesh { CpuMesh {
positions, positions: Positions::F32(positions),
normals: Some(normals), normals: Some(normals),
indices: Some(indices), indices,
..Default::default() ..Default::default()
} }
} }

View file

@ -3,7 +3,7 @@ use arrayvec::ArrayString;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use std::fmt; use std::fmt;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::Add; use std::ops::{Add, Mul};
use cgmath::Vector3; use cgmath::Vector3;
#[derive(Debug, Clone, Copy, Zeroable, Pod)] #[derive(Debug, Clone, Copy, Zeroable, Pod)]
@ -74,6 +74,18 @@ impl Add<Vector> for Vector {
} }
} }
impl Mul<f32> for Vector {
type Output = Vector;
fn mul(self, rhs: f32) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
#[derive(Debug, Clone, Copy, Zeroable, Pod)] #[derive(Debug, Clone, Copy, Zeroable, Pod)]
#[repr(C)] #[repr(C)]
pub struct Quaternion { pub struct Quaternion {