mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 09:33:51 +00:00
Initial commit: wowee native WoW 3.3.5a client
This commit is contained in:
commit
ce6cb8f38e
147 changed files with 32347 additions and 0 deletions
187
include/pipeline/m2_loader.hpp
Normal file
187
include/pipeline/m2_loader.hpp
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline {
|
||||
|
||||
/**
|
||||
* M2 Model Format (WoW Character/Creature Models)
|
||||
*
|
||||
* M2 files contain:
|
||||
* - Skeletal animated meshes
|
||||
* - Multiple texture units and materials
|
||||
* - Animation sequences
|
||||
* - Bone hierarchy
|
||||
* - Particle emitters, ribbon emitters, etc.
|
||||
*
|
||||
* Reference: https://wowdev.wiki/M2
|
||||
*/
|
||||
|
||||
// Animation sequence data
|
||||
struct M2Sequence {
|
||||
uint32_t id; // Animation ID
|
||||
uint32_t variationIndex; // Sub-animation index
|
||||
uint32_t duration; // Length in milliseconds
|
||||
float movingSpeed; // Speed during animation
|
||||
uint32_t flags; // Animation flags
|
||||
int16_t frequency; // Probability weight
|
||||
uint32_t replayMin; // Minimum replay delay
|
||||
uint32_t replayMax; // Maximum replay delay
|
||||
uint32_t blendTime; // Blend time in ms
|
||||
glm::vec3 boundMin; // Bounding box
|
||||
glm::vec3 boundMax;
|
||||
float boundRadius; // Bounding sphere radius
|
||||
int16_t nextAnimation; // Next animation in chain
|
||||
uint16_t aliasNext; // Alias for next animation
|
||||
};
|
||||
|
||||
// Animation track with per-sequence keyframe data
|
||||
struct M2AnimationTrack {
|
||||
uint16_t interpolationType = 0; // 0=none, 1=linear, 2=hermite, 3=bezier
|
||||
int16_t globalSequence = -1; // -1 if not a global sequence
|
||||
|
||||
struct SequenceKeys {
|
||||
std::vector<uint32_t> timestamps; // Milliseconds
|
||||
std::vector<glm::vec3> vec3Values; // For translation/scale tracks
|
||||
std::vector<glm::quat> quatValues; // For rotation tracks
|
||||
};
|
||||
std::vector<SequenceKeys> sequences; // One per animation sequence
|
||||
|
||||
bool hasData() const { return !sequences.empty(); }
|
||||
};
|
||||
|
||||
// Bone data for skeletal animation
|
||||
struct M2Bone {
|
||||
int32_t keyBoneId; // Bone ID (-1 = not key bone)
|
||||
uint32_t flags; // Bone flags
|
||||
int16_t parentBone; // Parent bone index (-1 = root)
|
||||
uint16_t submeshId; // Submesh ID
|
||||
glm::vec3 pivot; // Pivot point
|
||||
|
||||
M2AnimationTrack translation; // Position keyframes per sequence
|
||||
M2AnimationTrack rotation; // Rotation keyframes per sequence
|
||||
M2AnimationTrack scale; // Scale keyframes per sequence
|
||||
};
|
||||
|
||||
// Vertex with skinning data
|
||||
struct M2Vertex {
|
||||
glm::vec3 position;
|
||||
uint8_t boneWeights[4]; // Bone weights (0-255)
|
||||
uint8_t boneIndices[4]; // Bone indices
|
||||
glm::vec3 normal;
|
||||
glm::vec2 texCoords[2]; // Two UV sets
|
||||
};
|
||||
|
||||
// Texture unit
|
||||
struct M2Texture {
|
||||
uint32_t type; // Texture type
|
||||
uint32_t flags; // Texture flags
|
||||
std::string filename; // Texture filename (from FileData or embedded)
|
||||
};
|
||||
|
||||
// Render batch (submesh)
|
||||
struct M2Batch {
|
||||
uint8_t flags;
|
||||
int8_t priorityPlane;
|
||||
uint16_t shader; // Shader ID
|
||||
uint16_t skinSectionIndex; // Submesh index
|
||||
uint16_t colorIndex; // Color animation index
|
||||
uint16_t materialIndex; // Material index
|
||||
uint16_t materialLayer; // Material layer
|
||||
uint16_t textureCount; // Number of textures
|
||||
uint16_t textureIndex; // First texture lookup index
|
||||
uint16_t textureUnit; // Texture unit
|
||||
uint16_t transparencyIndex; // Transparency animation index
|
||||
uint16_t textureAnimIndex; // Texture animation index
|
||||
|
||||
// Render data
|
||||
uint32_t indexStart; // First index
|
||||
uint32_t indexCount; // Number of indices
|
||||
uint32_t vertexStart; // First vertex
|
||||
uint32_t vertexCount; // Number of vertices
|
||||
|
||||
// Geoset info (from submesh)
|
||||
uint16_t submeshId = 0; // Submesh/geoset ID (determines body part group)
|
||||
uint16_t submeshLevel = 0; // Submesh level (0=base, 1+=LOD/alternate mesh)
|
||||
};
|
||||
|
||||
// Attachment point (bone-anchored position for weapons, effects, etc.)
|
||||
struct M2Attachment {
|
||||
uint32_t id; // 0=Head, 1=RightHand, 2=LeftHand, etc.
|
||||
uint16_t bone; // Bone index
|
||||
glm::vec3 position; // Offset from bone pivot
|
||||
};
|
||||
|
||||
// Complete M2 model structure
|
||||
struct M2Model {
|
||||
// Model metadata
|
||||
std::string name;
|
||||
uint32_t version;
|
||||
glm::vec3 boundMin; // Model bounding box
|
||||
glm::vec3 boundMax;
|
||||
float boundRadius; // Bounding sphere
|
||||
|
||||
// Geometry data
|
||||
std::vector<M2Vertex> vertices;
|
||||
std::vector<uint16_t> indices;
|
||||
|
||||
// Skeletal animation
|
||||
std::vector<M2Bone> bones;
|
||||
std::vector<M2Sequence> sequences;
|
||||
|
||||
// Rendering
|
||||
std::vector<M2Batch> batches;
|
||||
std::vector<M2Texture> textures;
|
||||
std::vector<uint16_t> textureLookup; // Batch texture index lookup
|
||||
|
||||
// Attachment points (for weapon/effect anchoring)
|
||||
std::vector<M2Attachment> attachments;
|
||||
std::vector<uint16_t> attachmentLookup; // attachment ID → index
|
||||
|
||||
// Flags
|
||||
uint32_t globalFlags;
|
||||
|
||||
bool isValid() const {
|
||||
return !vertices.empty() && !indices.empty();
|
||||
}
|
||||
};
|
||||
|
||||
class M2Loader {
|
||||
public:
|
||||
/**
|
||||
* Load M2 model from raw file data
|
||||
*
|
||||
* @param m2Data Raw M2 file bytes
|
||||
* @return Parsed M2 model
|
||||
*/
|
||||
static M2Model load(const std::vector<uint8_t>& m2Data);
|
||||
|
||||
/**
|
||||
* Load M2 skin file (contains submesh/batch data)
|
||||
*
|
||||
* @param skinData Raw M2 skin file bytes
|
||||
* @param model Model to populate with skin data
|
||||
* @return True if successful
|
||||
*/
|
||||
static bool loadSkin(const std::vector<uint8_t>& skinData, M2Model& model);
|
||||
|
||||
/**
|
||||
* Load external .anim file data into model bone tracks
|
||||
*
|
||||
* @param m2Data Original M2 file bytes (contains track headers)
|
||||
* @param animData Raw .anim file bytes
|
||||
* @param sequenceIndex Which sequence index this .anim file provides data for
|
||||
* @param model Model to patch with animation data
|
||||
*/
|
||||
static void loadAnimFile(const std::vector<uint8_t>& m2Data,
|
||||
const std::vector<uint8_t>& animData,
|
||||
uint32_t sequenceIndex,
|
||||
M2Model& model);
|
||||
};
|
||||
|
||||
} // namespace pipeline
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue