use std::collections::HashMap;
use crate::types::{BoundingBox, Color, Vec3};
use crate::version::WmoVersion;
use crate::wmo_group_types::WmoGroupFlags;
use bitflags::bitflags;
#[derive(Debug)]
pub struct WmoRoot {
pub version: WmoVersion,
pub materials: Vec<WmoMaterial>,
pub groups: Vec<WmoGroupInfo>,
pub portals: Vec<WmoPortal>,
pub portal_references: Vec<WmoPortalReference>,
pub visible_block_lists: Vec<Vec<u16>>,
pub lights: Vec<WmoLight>,
pub doodad_defs: Vec<WmoDoodadDef>,
pub doodad_sets: Vec<WmoDoodadSet>,
pub bounding_box: BoundingBox,
pub textures: Vec<String>,
pub texture_offset_index_map: HashMap<u32, u32>,
pub header: WmoHeader,
pub skybox: Option<String>,
pub convex_volume_planes: Option<WmoConvexVolumePlanes>,
}
#[derive(Debug, Clone)]
pub struct WmoHeader {
pub n_materials: u32,
pub n_groups: u32,
pub n_portals: u32,
pub n_lights: u32,
pub n_doodad_names: u32,
pub n_doodad_defs: u32,
pub n_doodad_sets: u32,
pub flags: WmoFlags,
pub ambient_color: Color,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WmoFlags: u32 {
const HAS_VERTEX_COLORS = 0x01;
const OUTDOOR = 0x02;
const NO_TERRAIN_SHADOWS = 0x04;
const HAS_LIQUIDS = 0x08;
const INDOOR_MAP = 0x10;
const HAS_SKYBOX = 0x20;
const SPECIAL_PASS = 0x40;
const USE_SCENE_GRAPH = 0x80;
const SHOW_MINIMAP_OUTDOOR = 0x100;
const MOUNT_ALLOWED = 0x200;
}
}
#[derive(Debug, Clone)]
pub struct WmoMaterial {
pub flags: WmoMaterialFlags,
pub shader: u32,
pub blend_mode: u32,
pub texture1: u32,
pub emissive_color: Color,
pub sidn_color: Color,
pub framebuffer_blend: Color,
pub texture2: u32,
pub diffuse_color: Color,
pub ground_type: u32,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WmoMaterialFlags: u32 {
const UNLIT = 0x01;
const UNFOGGED = 0x02;
const TWO_SIDED = 0x04;
const EXTERIOR_LIGHT = 0x08;
const WINDOW_LIGHT = 0x10;
const CLAMP_S = 0x20;
const CLAMP_T = 0x40;
const UNUSED1 = 0x80;
const SHADOW_BATCH_1 = 0x100;
const SHADOW_BATCH_2 = 0x200;
const UNUSED2 = 0x400;
const UNUSED3 = 0x800;
}
}
impl WmoMaterial {
pub fn get_texture1_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
texture_offset_index_map
.get(&self.texture1)
.copied()
.unwrap()
}
pub fn get_texture2_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
texture_offset_index_map
.get(&self.texture2)
.copied()
.unwrap()
}
}
#[derive(Debug, Clone)]
pub struct WmoGroupInfo {
pub flags: WmoGroupFlags,
pub bounding_box: BoundingBox,
pub name: String,
}
#[derive(Debug, Clone)]
pub struct WmoPortal {
pub vertices: Vec<Vec3>,
pub normal: Vec3,
}
#[derive(Debug, Clone)]
pub struct WmoPortalReference {
pub portal_index: u16,
pub group_index: u16,
pub side: u16,
}
#[derive(Debug, Clone)]
pub struct WmoLight {
pub light_type: WmoLightType,
pub position: Vec3,
pub color: Color,
pub intensity: f32,
pub attenuation_start: f32,
pub attenuation_end: f32,
pub use_attenuation: bool,
pub properties: WmoLightProperties,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WmoLightType {
Omni = 0,
Spot = 1,
Directional = 2,
Ambient = 3,
}
impl WmoLightType {
pub fn from_raw(raw: u8) -> Option<Self> {
match raw {
0 => Some(Self::Omni),
1 => Some(Self::Spot),
2 => Some(Self::Directional),
3 => Some(Self::Ambient),
_ => {
tracing::warn!("Unknown light type {}, defaulting to Omni", raw);
Some(Self::Omni)
}
}
}
}
#[derive(Debug, Clone)]
pub enum WmoLightProperties {
Omni,
Spot {
direction: Vec3,
hotspot: f32,
falloff: f32,
},
Directional {
direction: Vec3,
},
Ambient,
}
#[derive(Debug, Clone)]
pub struct WmoDoodadDef {
pub name_offset: u32,
pub position: Vec3,
pub orientation: [f32; 4],
pub scale: f32,
pub color: Color,
pub set_index: u16,
}
#[derive(Debug, Clone)]
pub struct WmoDoodadSet {
pub name: String,
pub start_doodad: u32,
pub n_doodads: u32,
}
#[derive(Debug, Clone)]
pub struct WmoConvexVolumePlane {
pub normal: Vec3,
pub distance: f32,
pub flags: u32,
}
#[derive(Debug, Clone)]
pub struct WmoConvexVolumePlanes {
pub planes: Vec<WmoConvexVolumePlane>,
}