mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
bone transform wip
This commit is contained in:
parent
31fc82bbdb
commit
b731b7aab1
6 changed files with 67 additions and 23 deletions
|
|
@ -17,14 +17,11 @@ fn main() -> Result<(), vmdl::ModelError> {
|
||||||
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)?;
|
||||||
|
|
||||||
let models = mdl
|
for bone in mdl.bones {
|
||||||
.body_parts
|
dbg!(bone.flags);
|
||||||
.iter()
|
dbg!(bone.rot);
|
||||||
.flat_map(|part| part.models.iter())
|
dbg!(bone.quaternion);
|
||||||
.flat_map(|model| model.meshes.iter())
|
}
|
||||||
.map(|mesh| mesh.material)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
dbg!(mdl.textures, models, mdl.skin_table);
|
|
||||||
|
|
||||||
// let model = Model::from_parts(mdl, vtx, vvd);
|
// let model = Model::from_parts(mdl, vtx, vvd);
|
||||||
// for strip in model.vertex_strips() {
|
// for strip in model.vertex_strips() {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
let mut camera = Camera::new_perspective(
|
let mut camera = Camera::new_perspective(
|
||||||
window.viewport(),
|
window.viewport(),
|
||||||
vec3(2.0, 2.0, 5.0),
|
vec3(2.0, 2.0, 2.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),
|
||||||
|
|
@ -57,7 +57,6 @@ fn main() -> Result<(), Error> {
|
||||||
let mut gui = three_d::GUI::new(&context);
|
let mut gui = three_d::GUI::new(&context);
|
||||||
|
|
||||||
let loader = Loader::new().expect("loader");
|
let loader = Loader::new().expect("loader");
|
||||||
dbg!(&loader);
|
|
||||||
let skin_count = source_model.skin_tables().count();
|
let skin_count = source_model.skin_tables().count();
|
||||||
|
|
||||||
let cpu_models = (0..skin_count).map(|skin| model_to_model(&source_model, &loader, skin));
|
let cpu_models = (0..skin_count).map(|skin| model_to_model(&source_model, &loader, skin));
|
||||||
|
|
@ -232,21 +231,30 @@ fn main() -> Result<(), Error> {
|
||||||
// 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);
|
||||||
|
|
||||||
|
pub fn map_coords<C: Into<Vec3>>(vec: C) -> Vec3 {
|
||||||
|
let vec = vec.into();
|
||||||
|
Vec3 {
|
||||||
|
x: vec.y * UNIT_SCALE,
|
||||||
|
y: vec.z * UNIT_SCALE,
|
||||||
|
z: vec.x * UNIT_SCALE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
|
fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
|
||||||
let offset = model
|
let bounds = model.bounding_box();
|
||||||
.vertices()
|
|
||||||
.iter()
|
|
||||||
.map(|vert| vert.position.y)
|
|
||||||
.max_by(|a, b| a.total_cmp(b))
|
|
||||||
.unwrap();
|
|
||||||
let offset = Vector {
|
let offset = Vector {
|
||||||
x: 0.0,
|
x: -(bounds.1.x + bounds.0.x) / 2.0,
|
||||||
y: -offset / 2.0,
|
y: -(bounds.1.y + bounds.0.y) / 2.0,
|
||||||
z: 0.0,
|
z: -(bounds.1.z + bounds.0.z) / 2.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let skin = model.skin_tables().nth(skin).unwrap();
|
let skin = model.skin_tables().nth(skin).unwrap();
|
||||||
|
|
||||||
|
let transforms = model
|
||||||
|
.bones()
|
||||||
|
.map(|bone| Mat4::from(cgmath::Quaternion::from(bone.rot)))
|
||||||
|
.fold(Mat4::identity(), |a, b| a * b);
|
||||||
|
|
||||||
let geometries = model
|
let geometries = model
|
||||||
.meshes()
|
.meshes()
|
||||||
.map(|mesh| {
|
.map(|mesh| {
|
||||||
|
|
@ -256,7 +264,8 @@ fn model_to_model(model: &Model, loader: &Loader, skin: usize) -> CpuModel {
|
||||||
|
|
||||||
let positions: Vec<Vec3> = mesh
|
let positions: Vec<Vec3> = mesh
|
||||||
.vertices()
|
.vertices()
|
||||||
.map(|vertex| ((vertex.position + offset) * UNIT_SCALE * 10.0).into())
|
.map(|vertex| map_coords(vertex.position + offset) * 10.0)
|
||||||
|
.map(|vertex: Vec3| (transforms * vertex.extend(1.0)).truncate())
|
||||||
.collect();
|
.collect();
|
||||||
let normals: Vec<Vec3> = mesh.vertices().map(|vertex| vertex.normal.into()).collect();
|
let normals: Vec<Vec3> = mesh.vertices().map(|vertex| vertex.normal.into()).collect();
|
||||||
let uvs: Vec<Vec2> = mesh
|
let uvs: Vec<Vec2> = mesh
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub mod vtx;
|
||||||
pub mod vvd;
|
pub mod vvd;
|
||||||
|
|
||||||
pub use crate::mdl::Mdl;
|
pub use crate::mdl::Mdl;
|
||||||
use crate::mdl::TextureInfo;
|
use crate::mdl::{Bone, TextureInfo};
|
||||||
pub use crate::vtx::Vtx;
|
pub use crate::vtx::Vtx;
|
||||||
use crate::vvd::Vertex;
|
use crate::vvd::Vertex;
|
||||||
pub use crate::vvd::Vvd;
|
pub use crate::vvd::Vvd;
|
||||||
|
|
@ -137,6 +137,10 @@ impl Model {
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
self.mdl.name.as_str()
|
self.mdl.name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bones(&self) -> impl Iterator<Item = &Bone> {
|
||||||
|
self.mdl.bones.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SkinTable<'a> {
|
pub struct SkinTable<'a> {
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ mod raw;
|
||||||
|
|
||||||
pub use raw::header::*;
|
pub use raw::header::*;
|
||||||
pub use raw::header2::*;
|
pub use raw::header2::*;
|
||||||
|
pub use raw::*;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
use crate::mdl::raw::{BodyPartHeader, Bone, MeshHeader, MeshTexture, ModelHeader};
|
|
||||||
use crate::vvd::Vertex;
|
use crate::vvd::Vertex;
|
||||||
use crate::{
|
use crate::{
|
||||||
read_indexes, read_relative, read_relative_iter, FixedString, ModelError, ReadRelative,
|
read_indexes, read_relative, read_relative_iter, FixedString, ModelError, ReadRelative,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{ModelError, StringError};
|
use crate::{ModelError, StringError};
|
||||||
use arrayvec::ArrayString;
|
use arrayvec::ArrayString;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use cgmath::{Deg, Euler, Rad, Vector3};
|
use cgmath::{Deg, Euler, Rad, Rotation3, Vector3};
|
||||||
|
use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul};
|
||||||
|
|
@ -101,6 +102,23 @@ impl From<Quaternion> for cgmath::Quaternion<f32> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<cgmath::Quaternion<f32>> for Quaternion {
|
||||||
|
fn from(q: cgmath::Quaternion<f32>) -> Self {
|
||||||
|
Quaternion {
|
||||||
|
x: q.v.x,
|
||||||
|
y: q.v.y,
|
||||||
|
z: q.v.z,
|
||||||
|
w: q.s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Quaternion> for cgmath::Matrix4<f32> {
|
||||||
|
fn from(q: Quaternion) -> Self {
|
||||||
|
cgmath::Quaternion::from(q).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct RadianEuler {
|
pub struct RadianEuler {
|
||||||
|
|
@ -129,6 +147,21 @@ impl From<RadianEuler> for Euler<Deg<f32>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<RadianEuler> for cgmath::Quaternion<f32> {
|
||||||
|
fn from(value: RadianEuler) -> Self {
|
||||||
|
// angles are applied in roll, pitch, yaw order
|
||||||
|
cgmath::Quaternion::from_angle_y(Rad(value.x))
|
||||||
|
* cgmath::Quaternion::from_angle_x(Rad(value.y))
|
||||||
|
* cgmath::Quaternion::from_angle_z(Rad(-value.z))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RadianEuler> for Quaternion {
|
||||||
|
fn from(value: RadianEuler) -> Self {
|
||||||
|
cgmath::Quaternion::from(value).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fixed length, null-terminated string
|
/// Fixed length, null-terminated string
|
||||||
#[derive(Debug, Clone, Default, Copy)]
|
#[derive(Debug, Clone, Default, Copy)]
|
||||||
pub struct FixedString<const LEN: usize>(ArrayString<LEN>);
|
pub struct FixedString<const LEN: usize>(ArrayString<LEN>);
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ impl StripHeader {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
pub struct Vertex {
|
pub struct Vertex {
|
||||||
|
// these index into the mesh's vert[origMeshVertID]'s bones
|
||||||
pub bone_weight_indexes: [u8; 3],
|
pub bone_weight_indexes: [u8; 3],
|
||||||
pub bone_count: u8,
|
pub bone_count: u8,
|
||||||
pub original_mesh_vertex_id: u16,
|
pub original_mesh_vertex_id: u16,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue