wow_wmo/
wmo_types.rs

1use crate::types::{BoundingBox, Color, Vec3};
2use crate::version::WmoVersion;
3use crate::wmo_group_types::WmoGroupFlags;
4use bitflags::bitflags;
5
6/// Represents a WMO root file
7#[derive(Debug)]
8pub struct WmoRoot {
9    /// WMO version
10    pub version: WmoVersion,
11
12    /// List of materials
13    pub materials: Vec<WmoMaterial>,
14
15    /// List of groups
16    pub groups: Vec<WmoGroupInfo>,
17
18    /// List of portals
19    pub portals: Vec<WmoPortal>,
20
21    /// List of portal references
22    pub portal_references: Vec<WmoPortalReference>,
23
24    /// List of visible block lists
25    pub visible_block_lists: Vec<Vec<u16>>,
26
27    /// List of lights
28    pub lights: Vec<WmoLight>,
29
30    /// List of doodad definitions
31    pub doodad_defs: Vec<WmoDoodadDef>,
32
33    /// List of doodad sets
34    pub doodad_sets: Vec<WmoDoodadSet>,
35
36    /// Global bounding box
37    pub bounding_box: BoundingBox,
38
39    /// List of textures
40    pub textures: Vec<String>,
41
42    /// Model header info
43    pub header: WmoHeader,
44
45    /// Skybox model path, if any
46    pub skybox: Option<String>,
47}
48
49/// WMO header information
50#[derive(Debug, Clone)]
51pub struct WmoHeader {
52    /// Number of materials
53    pub n_materials: u32,
54
55    /// Number of groups
56    pub n_groups: u32,
57
58    /// Number of portals
59    pub n_portals: u32,
60
61    /// Number of lights
62    pub n_lights: u32,
63
64    /// Number of doodad names
65    pub n_doodad_names: u32,
66
67    /// Number of doodad defs
68    pub n_doodad_defs: u32,
69
70    /// Number of doodad sets
71    pub n_doodad_sets: u32,
72
73    /// Global WMO flags
74    pub flags: WmoFlags,
75
76    /// Ambient color
77    pub ambient_color: Color,
78}
79
80bitflags! {
81    /// Global WMO flags
82    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
83    pub struct WmoFlags: u32 {
84        /// Contains vertex colors
85        const HAS_VERTEX_COLORS = 0x01;
86        /// Outdoor
87        const OUTDOOR = 0x02;
88        /// Does not cast shadows on terrain
89        const NO_TERRAIN_SHADOWS = 0x04;
90        /// Contains groups with liquids
91        const HAS_LIQUIDS = 0x08;
92        /// Indoor map
93        const INDOOR_MAP = 0x10;
94        /// Contains skybox (introduced in WotLK)
95        const HAS_SKYBOX = 0x20;
96        /// Needs rendering during a special pass
97        const SPECIAL_PASS = 0x40;
98        /// Uses scene graph for rendering
99        const USE_SCENE_GRAPH = 0x80;
100        /// Shows minimap in outdoor
101        const SHOW_MINIMAP_OUTDOOR = 0x100;
102        /// Mount allowed inside this WMO
103        const MOUNT_ALLOWED = 0x200;
104    }
105}
106
107/// Represents a WMO material
108#[derive(Debug, Clone)]
109pub struct WmoMaterial {
110    /// Material flags
111    pub flags: WmoMaterialFlags,
112
113    /// Texture 1 index in MOTX chunk
114    pub shader: u32,
115
116    /// Blend mode
117    pub blend_mode: u32,
118
119    /// Texture 1 index in MOTX chunk
120    pub texture1: u32,
121
122    /// Emissive color
123    pub emissive_color: Color,
124
125    /// Sidn color
126    pub sidn_color: Color,
127
128    /// Framebuffer blend
129    pub framebuffer_blend: Color,
130
131    /// Texture 2 index in MOTX chunk
132    pub texture2: u32,
133
134    /// Diffuse color
135    pub diffuse_color: Color,
136
137    /// Ground type
138    pub ground_type: u32,
139}
140
141bitflags! {
142    /// WMO material flags
143    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
144    pub struct WmoMaterialFlags: u32 {
145        /// Unlit
146        const UNLIT = 0x01;
147        /// Unfogged
148        const UNFOGGED = 0x02;
149        /// Two-sided
150        const TWO_SIDED = 0x04;
151        /// Exterior light
152        const EXTERIOR_LIGHT = 0x08;
153        /// Window light
154        const WINDOW_LIGHT = 0x10;
155        /// Ignore vertex light
156        const IGNORE_VERTEX_LIGHT = 0x20;
157        /// Disable Z-buffer
158        const DISABLE_Z_BUFFER = 0x40;
159        /// Unused 1
160        const UNUSED1 = 0x80;
161        /// Shadow batch 1
162        const SHADOW_BATCH_1 = 0x100;
163        /// Shadow batch 2
164        const SHADOW_BATCH_2 = 0x200;
165        /// Unused 2
166        const UNUSED2 = 0x400;
167        /// Unused 3
168        const UNUSED3 = 0x800;
169    }
170}
171
172/// Represents information about a WMO group
173#[derive(Debug, Clone)]
174pub struct WmoGroupInfo {
175    /// Group flags
176    pub flags: WmoGroupFlags,
177
178    /// Bounding box
179    pub bounding_box: BoundingBox,
180
181    /// Group name (often contains a numeric index)
182    pub name: String,
183}
184
185/// Represents a WMO portal
186#[derive(Debug, Clone)]
187pub struct WmoPortal {
188    /// Portal vertices
189    pub vertices: Vec<Vec3>,
190
191    /// Normal vector
192    pub normal: Vec3,
193}
194
195/// Represents a WMO portal reference
196#[derive(Debug, Clone)]
197pub struct WmoPortalReference {
198    /// Portal index
199    pub portal_index: u16,
200
201    /// Group index
202    pub group_index: u16,
203
204    /// Side (0 or 1)
205    pub side: u16,
206}
207
208/// Represents a WMO light
209#[derive(Debug, Clone)]
210pub struct WmoLight {
211    /// Light type
212    pub light_type: WmoLightType,
213
214    /// Light position
215    pub position: Vec3,
216
217    /// Light color
218    pub color: Color,
219
220    /// Light intensity
221    pub intensity: f32,
222
223    /// Attenuation start
224    pub attenuation_start: f32,
225
226    /// Attenuation end
227    pub attenuation_end: f32,
228
229    /// Use attenuation
230    pub use_attenuation: bool,
231
232    /// Additional properties based on light type
233    pub properties: WmoLightProperties,
234}
235
236/// Type of WMO light
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
238pub enum WmoLightType {
239    /// Omnidirectional point light
240    Omni = 0,
241
242    /// Spotlight
243    Spot = 1,
244
245    /// Directional light
246    Directional = 2,
247
248    /// Ambient light
249    Ambient = 3,
250}
251
252impl WmoLightType {
253    /// Convert a raw value to a WmoLightType
254    pub fn from_raw(raw: u8) -> Option<Self> {
255        match raw {
256            0 => Some(Self::Omni),
257            1 => Some(Self::Spot),
258            2 => Some(Self::Directional),
259            3 => Some(Self::Ambient),
260            // Unknown light types default to Omni
261            _ => {
262                // Log warning but continue with default
263                tracing::warn!("Unknown light type {}, defaulting to Omni", raw);
264                Some(Self::Omni)
265            }
266        }
267    }
268}
269
270/// Additional light properties depending on light type
271#[derive(Debug, Clone)]
272pub enum WmoLightProperties {
273    /// Omni light properties (none)
274    Omni,
275
276    /// Spotlight properties
277    Spot {
278        /// Direction
279        direction: Vec3,
280
281        /// Hotspot angle (inner cone)
282        hotspot: f32,
283
284        /// Falloff angle (outer cone)
285        falloff: f32,
286    },
287
288    /// Directional light properties
289    Directional {
290        /// Direction
291        direction: Vec3,
292    },
293
294    /// Ambient light properties (none)
295    Ambient,
296}
297
298/// Represents a WMO doodad definition
299#[derive(Debug, Clone)]
300pub struct WmoDoodadDef {
301    /// Doodad name offset in MODN chunk
302    pub name_offset: u32,
303
304    /// Doodad position
305    pub position: Vec3,
306
307    /// Doodad orientation as quaternion
308    pub orientation: [f32; 4],
309
310    /// Doodad scale factor
311    pub scale: f32,
312
313    /// Doodad color
314    pub color: Color,
315
316    /// Doodad set index
317    pub set_index: u16,
318}
319
320/// Represents a WMO doodad set
321#[derive(Debug, Clone)]
322pub struct WmoDoodadSet {
323    /// Set name
324    pub name: String,
325
326    /// Start doodad index
327    pub start_doodad: u32,
328
329    /// Number of doodads in this set
330    pub n_doodads: u32,
331}