mirror of
https://codeberg.org/icewind/vmdl.git
synced 2026-06-03 16:44:11 +02:00
texture paths
This commit is contained in:
parent
1fa7a67515
commit
cd5ec8492e
8 changed files with 99 additions and 8 deletions
|
|
@ -16,7 +16,7 @@ fn main() -> Result<(), vmdl::ModelError> {
|
|||
let _vtx = Vtx::read(&data)?;
|
||||
let data = fs::read(path.with_extension("vvd"))?;
|
||||
let _vvd = Vvd::read(&data)?;
|
||||
dbg!(mdl.body_parts);
|
||||
dbg!(mdl.textures, mdl.texture_paths);
|
||||
|
||||
// let model = Model::from_parts(mdl, vtx, vvd);
|
||||
// for strip in model.vertex_strips() {
|
||||
|
|
|
|||
13
src/error.rs
13
src/error.rs
|
|
@ -1,3 +1,4 @@
|
|||
use std::string::FromUtf8Error;
|
||||
use thiserror::Error;
|
||||
|
||||
#[non_exhaustive]
|
||||
|
|
@ -20,3 +21,15 @@ pub enum StringError {
|
|||
#[error("String is not null-terminated")]
|
||||
NotNullTerminated,
|
||||
}
|
||||
|
||||
impl From<FromUtf8Error> for StringError {
|
||||
fn from(value: FromUtf8Error) -> Self {
|
||||
StringError::NonUTF8(value.utf8_error())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FromUtf8Error> for ModelError {
|
||||
fn from(value: FromUtf8Error) -> Self {
|
||||
StringError::NonUTF8(value.utf8_error()).into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
src/lib.rs
20
src/lib.rs
|
|
@ -141,10 +141,28 @@ trait ReadRelative: Sized {
|
|||
fn read(data: &[u8], header: Self::Header) -> Result<Self, ModelError>;
|
||||
}
|
||||
|
||||
impl<T: Readable> ReadRelative for T {
|
||||
trait ReadableRelative: Readable {}
|
||||
|
||||
impl ReadableRelative for u8 {}
|
||||
impl ReadableRelative for u16 {}
|
||||
impl ReadableRelative for u32 {}
|
||||
impl ReadableRelative for i8 {}
|
||||
impl ReadableRelative for i16 {}
|
||||
impl ReadableRelative for i32 {}
|
||||
|
||||
impl<T: ReadableRelative> ReadRelative for T {
|
||||
type Header = T;
|
||||
|
||||
fn read(_data: &[u8], header: Self::Header) -> Result<Self, ModelError> {
|
||||
Ok(header)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReadRelative for String {
|
||||
type Header = ();
|
||||
|
||||
fn read(data: &[u8], _header: Self::Header) -> Result<Self, ModelError> {
|
||||
let bytes = data.iter().copied().take_while(|byte| *byte != 0).collect();
|
||||
String::from_utf8(bytes).map_err(ModelError::from)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@ pub use raw::header::*;
|
|||
pub use raw::header2::*;
|
||||
use std::mem::size_of;
|
||||
|
||||
use crate::mdl::raw::{BodyPartHeader, Bone, MeshHeader, ModelHeader};
|
||||
use crate::mdl::raw::{BodyPartHeader, Bone, MeshHeader, MeshTexture, ModelHeader};
|
||||
use crate::vvd::Vertex;
|
||||
use crate::{read_indexes, read_relative, FixedString, ModelError, ReadRelative, Readable};
|
||||
use crate::{
|
||||
read_indexes, read_relative, read_relative_iter, FixedString, ModelError, ReadRelative,
|
||||
Readable,
|
||||
};
|
||||
|
||||
type Result<T> = std::result::Result<T, ModelError>;
|
||||
|
||||
|
|
@ -15,11 +18,22 @@ pub struct Mdl {
|
|||
pub header: StudioHeader,
|
||||
pub bones: Vec<Bone>,
|
||||
pub body_parts: Vec<BodyPart>,
|
||||
pub textures: Vec<TextureInfo>,
|
||||
pub texture_paths: Vec<String>,
|
||||
}
|
||||
|
||||
impl Mdl {
|
||||
pub fn read(data: &[u8]) -> Result<Self> {
|
||||
let header = <StudioHeader as Readable>::read(data)?;
|
||||
let textures = read_relative_iter(data, header.texture_indexes())
|
||||
.collect::<Result<Vec<TextureInfo>>>()?;
|
||||
let texture_dirs_indexes =
|
||||
read_relative_iter(data, header.texture_dir_indexes()).collect::<Result<Vec<u32>>>()?;
|
||||
let texture_paths = read_relative::<String, _>(
|
||||
data,
|
||||
texture_dirs_indexes.into_iter().map(|index| index as usize),
|
||||
)?;
|
||||
|
||||
let bones = read_indexes(header.bone_indexes(), data).collect::<Result<_>>()?;
|
||||
Ok(Mdl {
|
||||
bones,
|
||||
|
|
@ -34,6 +48,8 @@ impl Mdl {
|
|||
BodyPart::read(data, header)
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
textures,
|
||||
texture_paths,
|
||||
header,
|
||||
})
|
||||
}
|
||||
|
|
@ -94,3 +110,18 @@ impl ReadRelative for Mesh {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextureInfo {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl ReadRelative for TextureInfo {
|
||||
type Header = MeshTexture;
|
||||
|
||||
fn read(data: &[u8], header: Self::Header) -> Result<Self> {
|
||||
Ok(TextureInfo {
|
||||
name: String::read(&data[header.name_index as usize..], ())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,11 +229,19 @@ impl StudioHeader {
|
|||
}
|
||||
|
||||
pub fn texture_indexes(&self) -> impl Iterator<Item = usize> {
|
||||
index_range(self.texture_offset, self.texture_count, 1)
|
||||
index_range(
|
||||
self.texture_offset,
|
||||
self.texture_count,
|
||||
size_of::<MeshTexture>(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn texture_dir_indexes(&self) -> impl Iterator<Item = usize> {
|
||||
index_range(self.texture_dir_offset, self.texture_dir_count, 1)
|
||||
index_range(
|
||||
self.texture_dir_offset,
|
||||
self.texture_dir_count,
|
||||
size_of::<u32>(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn body_part_indexes(&self) -> impl Iterator<Item = usize> {
|
||||
|
|
|
|||
|
|
@ -146,3 +146,18 @@ pub struct MeshVertexData {
|
|||
model_vertex_data: i32,
|
||||
lod_vertex_count: [i32; 8],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
#[allow(dead_code)]
|
||||
pub struct MeshTexture {
|
||||
pub name_index: i32, // relative offset to this struct
|
||||
pub flags: i32,
|
||||
pub used: i32,
|
||||
_padding: i32,
|
||||
pub material_ptr: i32,
|
||||
pub client_material_ptr: i32,
|
||||
_padding2: [i32; 10],
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(size_of::<MeshTexture>(), 16 * 4);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{index_range, Pod};
|
||||
use crate::{index_range, Pod, ReadableRelative};
|
||||
use bitflags::bitflags;
|
||||
use bytemuck::Zeroable;
|
||||
use std::mem::size_of;
|
||||
|
|
@ -215,4 +215,6 @@ pub struct Vertex {
|
|||
pub bone_id: [u8; 3],
|
||||
}
|
||||
|
||||
impl ReadableRelative for Vertex {}
|
||||
|
||||
static_assertions::const_assert_eq!(size_of::<Vertex>(), 9);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{index_range, Vector};
|
||||
use crate::{index_range, ReadableRelative, Vector};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use std::mem::size_of;
|
||||
|
||||
|
|
@ -51,6 +51,8 @@ pub struct VertexFileFixup {
|
|||
pub vertex_count: i32,
|
||||
}
|
||||
|
||||
impl ReadableRelative for VertexFileFixup {}
|
||||
|
||||
#[derive(Debug, Clone, Zeroable, Pod, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
|
|
@ -60,6 +62,8 @@ pub struct Vertex {
|
|||
pub texture_coordinates: [f32; 2],
|
||||
}
|
||||
|
||||
impl ReadableRelative for Vertex {}
|
||||
|
||||
static_assertions::const_assert_eq!(size_of::<Vertex>(), 48);
|
||||
|
||||
#[derive(Debug, Clone, Zeroable, Pod, Copy)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue