mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
update threed
This commit is contained in:
parent
9765b2171a
commit
89529579be
4 changed files with 133 additions and 102 deletions
|
|
@ -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]]
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
164
examples/view.rs
164
examples/view.rs
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue