rakata_formats/bwm/
ascii_writer.rs

1//! BWM ASCII writer implementation.
2//!
3//! This module provides an ASCII serializer for the KotOR walkmesh format,
4//! compatible with the game's `LoadMeshText` parser.
5
6use std::io::Write;
7
8use super::ascii_reader::BwmAsciiError;
9use super::{Bwm, BwmType};
10
11/// Writes a BWM to an ASCII writer.
12pub fn write_bwm_ascii<W: Write>(writer: &mut W, bwm: &Bwm) -> Result<(), BwmAsciiError> {
13    writeln!(writer, "node aabb")?;
14
15    // Position
16    writeln!(
17        writer,
18        "  position {} {} {}",
19        bwm.position.x, bwm.position.y, bwm.position.z
20    )?;
21
22    // Orientation (Default identity as we don't store it)
23    writeln!(writer, "  orientation 0.0 0.0 0.0 1.0")?;
24
25    // Vertices
26    writeln!(writer, "  verts {}", bwm.vertices.len())?;
27    for v in &bwm.vertices {
28        writeln!(writer, "    {} {} {}", v.x, v.y, v.z)?;
29    }
30
31    // Faces
32    writeln!(writer, "  faces {}", bwm.faces.len())?;
33    for face in &bwm.faces {
34        // Output format: v1 v2 v3 adj1 adj2 adj3 adj4 material
35        // ASCII format requires 4 adjacency indices, but the engine recomputes them.
36        // We write `-1` placeholders.
37
38        writeln!(
39            writer,
40            "    {} {} {} -1 -1 -1 -1 {}",
41            face.vertex_indices[0],
42            face.vertex_indices[1],
43            face.vertex_indices[2],
44            face.material_id
45        )?;
46    }
47
48    // AABB
49    // Only if AreaModel
50    if bwm.walkmesh_type.known() == Some(BwmType::AreaModel) && !bwm.aabb_nodes.is_empty() {
51        writeln!(writer, "  aabb")?;
52        for node in &bwm.aabb_nodes {
53            // Output only leaf nodes (containing faces) to the ASCII AABB list.
54            // The game rebuilds the tree structure from these leaves on load.
55            if node.face_index != 0xFFFFFFFF {
56                // Write raw bounding box values. The game applies epsilon expansion on load.
57                writeln!(
58                    writer,
59                    "    {} {} {} {} {} {} {}",
60                    node.bb_min.x,
61                    node.bb_min.y,
62                    node.bb_min.z,
63                    node.bb_max.x,
64                    node.bb_max.y,
65                    node.bb_max.z,
66                    node.face_index
67                )?;
68            }
69        }
70    }
71
72    writeln!(writer, "endnode")?;
73
74    Ok(())
75}