Skip to content

Commit 1234e11

Browse files
committed
Model: Expose vertex streams
This is needed in Novus to properly emulate the game's rendering system. Later on I'll revamp the Model to only include streams.
1 parent f6c2b98 commit 1234e11

File tree

2 files changed

+67
-21
lines changed

2 files changed

+67
-21
lines changed

src/model.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ use binrw::BinReaderExt;
1111
use binrw::{binrw, BinWrite, BinWriterExt};
1212

1313
use crate::common_file_operations::{read_bool_from, write_bool_as};
14-
use crate::model_vertex_declarations::{
15-
vertex_element_parser, vertex_element_writer, VertexDeclaration, VertexType, VertexUsage,
16-
VERTEX_ELEMENT_SIZE,
17-
};
14+
use crate::model_vertex_declarations::{vertex_element_parser, vertex_element_writer, VertexDeclaration, VertexType, VertexUsage, VERTEX_ELEMENT_SIZE};
1815
use crate::{ByteBuffer, ByteSpan};
1916

2017
pub const NUM_VERTICES: u32 = 17;
@@ -290,9 +287,9 @@ struct ShapeValue {
290287
#[allow(dead_code)]
291288
#[br(import {file_header: &ModelFileHeader})]
292289
#[brw(little)]
293-
struct ModelData {
290+
pub struct ModelData {
294291
#[br(args { vertex_declaration_count: file_header.vertex_declaration_count })]
295-
header: ModelHeader,
292+
pub header: ModelHeader,
296293

297294
#[br(count = header.element_id_count)]
298295
element_ids: Vec<ElementId>,
@@ -373,7 +370,7 @@ struct ElementId {
373370
rotate: [f32; 3],
374371
}
375372

376-
#[derive(Clone, Copy, PartialEq)]
373+
#[derive(Clone, Copy, PartialEq, Debug)]
377374
#[repr(C)]
378375
pub struct Vertex {
379376
pub position: [f32; 3],
@@ -403,47 +400,50 @@ impl Default for Vertex {
403400
}
404401
}
405402

406-
#[derive(Clone, Copy)]
403+
#[derive(Debug, Clone, Copy)]
407404
#[repr(C)]
408405
pub struct NewShapeValue {
409406
pub base_index: u32,
410407
pub replacing_vertex: Vertex,
411408
}
412409

413-
#[derive(Clone, Copy)]
410+
#[derive(Debug, Clone, Copy)]
414411
#[repr(C)]
415412
pub struct SubMesh {
416413
submesh_index: usize,
417414
pub index_count: u32,
418415
pub index_offset: u32,
419416
}
420417

421-
#[derive(Clone)]
418+
#[derive(Debug, Clone)]
422419
pub struct Shape {
423420
pub name: String,
424421
pub morphed_vertices: Vec<Vertex>,
425422
}
426423

427424
/// Corresponds to a "Mesh" in an LOD
428-
#[derive(Clone)]
425+
#[derive(Debug, Clone)]
429426
pub struct Part {
430427
mesh_index: u16,
431428
pub vertices: Vec<Vertex>,
429+
/// Indexed by VertexElement::stream
430+
pub vertex_streams: Vec<Vec<u8>>,
431+
pub vertex_stream_strides: Vec<usize>,
432432
pub indices: Vec<u16>,
433433
pub material_index: u16,
434434
pub submeshes: Vec<SubMesh>,
435435
pub shapes: Vec<Shape>,
436436
}
437437

438-
#[derive(Clone)]
438+
#[derive(Debug, Clone)]
439439
pub struct Lod {
440440
pub parts: Vec<Part>,
441441
}
442442

443-
#[derive(Clone)]
443+
#[derive(Debug, Clone)]
444444
pub struct MDL {
445445
file_header: ModelFileHeader,
446-
model_data: ModelData,
446+
pub model_data: ModelData,
447447

448448
pub lods: Vec<Lod>,
449449
pub affected_bone_names: Vec<String>,
@@ -551,13 +551,7 @@ impl MDL {
551551
MDL::read_byte_float4(&mut cursor).unwrap();
552552
}
553553
VertexType::Byte4 => {
554-
let bytes = MDL::read_byte4(&mut cursor).unwrap();
555-
vertices[k as usize].bone_weight = [
556-
f32::from(bytes[0]),
557-
f32::from(bytes[1]),
558-
f32::from(bytes[2]),
559-
f32::from(bytes[3]),
560-
];
554+
vertices[k as usize].bone_weight = MDL::read_tangent(&mut cursor).unwrap();
561555
}
562556
VertexType::UnsignedShort4 => {
563557
let bytes = MDL::read_unsigned_short4(&mut cursor).unwrap();
@@ -779,13 +773,42 @@ impl MDL {
779773
}
780774
}
781775

776+
let mut vertex_streams = vec![];
777+
let mut vertex_stream_strides = vec![];
778+
let mesh = &model.meshes[j as usize];
779+
for stream in 0..mesh.vertex_stream_count {
780+
let mut vertex_data = vec![];
781+
let stride = mesh.vertex_buffer_strides[stream as usize];
782+
for z in 0..mesh.vertex_count {
783+
// TODO: read the entire vertex data into a buffer
784+
// Handle the offsets within Novus itself
785+
cursor
786+
.seek(SeekFrom::Start(
787+
(model.lods[i as usize].vertex_data_offset
788+
+ model.meshes[j as usize].vertex_buffer_offsets
789+
[stream as usize]
790+
+ (z as u32 * stride as u32)) as u64,
791+
))
792+
.ok()?;
793+
794+
for _ in 0..stride {
795+
vertex_data.push(cursor.read_le::<u8>().ok()?);
796+
}
797+
}
798+
799+
vertex_streams.push(vertex_data);
800+
vertex_stream_strides.push(mesh.vertex_buffer_strides[stream as usize] as usize);
801+
}
802+
782803
parts.push(Part {
783804
mesh_index: j,
784805
vertices,
785806
indices,
786807
material_index,
787808
submeshes,
788809
shapes,
810+
vertex_streams,
811+
vertex_stream_strides
789812
});
790813
}
791814

@@ -1019,6 +1042,13 @@ impl MDL {
10191042

10201043
match element.vertex_usage {
10211044
VertexUsage::Position => match element.vertex_type {
1045+
VertexType::Single4 => {
1046+
MDL::write_single4(
1047+
&mut cursor,
1048+
&MDL::pad_slice(&vert.position, 1.0),
1049+
)
1050+
.ok()?;
1051+
}
10221052
VertexType::Half4 => {
10231053
MDL::write_half4(
10241054
&mut cursor,
@@ -1041,6 +1071,10 @@ impl MDL {
10411071
MDL::write_byte_float4(&mut cursor, &vert.bone_weight)
10421072
.ok()?;
10431073
}
1074+
VertexType::Byte4 => {
1075+
MDL::write_byte_float42(&mut cursor, &vert.bone_weight)
1076+
.ok()?; // TODO: WRONG!
1077+
}
10441078
_ => {
10451079
panic!(
10461080
"Unexpected vertex type for blendweight: {:#?}",

src/model_file_operations.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ impl MDL {
3232
])
3333
}
3434

35+
pub(crate) fn write_byte_float42<T: BinWriterExt>(
36+
cursor: &mut T,
37+
vec: &[f32; 4],
38+
) -> BinResult<()> {
39+
cursor.write_le::<[u8; 4]>(&[
40+
(vec[0]).round() as u8,
41+
(vec[1]).round() as u8,
42+
(vec[2]).round() as u8,
43+
(vec[3]).round() as u8,
44+
])
45+
}
46+
3547
pub(crate) fn read_tangent(cursor: &mut Cursor<ByteSpan>) -> Option<[f32; 4]> {
3648
Some([
3749
(f32::from(cursor.read_le::<u8>().ok()?) * 2.0 / MAX_BYTE_FLOAT - 1.0),

0 commit comments

Comments
 (0)