From 16bd81ffad8a1d4ea9a9c62a468185d543826c10 Mon Sep 17 00:00:00 2001 From: Armin Burgmeier Date: Fri, 10 Jul 2009 21:57:11 +0200 Subject: [PATCH] Implemented StdMeshInstance --- standard/inc/StdMesh.h | 19 ++++++--- standard/src/StdMesh.cpp | 91 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/standard/inc/StdMesh.h b/standard/inc/StdMesh.h index e190c4835..8195652d4 100644 --- a/standard/inc/StdMesh.h +++ b/standard/inc/StdMesh.h @@ -114,12 +114,10 @@ public: // *this = trans * *this void Transform(const StdMeshMatrix& trans); -#if 0 // *this *= f; void Mul(float f); // *this += other; void Add(const StdMeshVertex& other); -#endif }; class StdMeshFace @@ -150,6 +148,7 @@ private: class StdMeshAnimation { friend class StdMesh; + friend class StdMeshInstance; public: StdMeshAnimation() {} StdMeshAnimation(const StdMeshAnimation& other); @@ -166,6 +165,7 @@ private: class StdMesh { + friend class StdMeshInstance; public: StdMesh(); ~StdMesh(); @@ -184,7 +184,7 @@ public: const StdMeshBone& GetBone(unsigned int i) const { return *Bones[i]; } unsigned int GetNumBones() const { return Bones.size(); } - const StdMeshAnimation& GetAnimationByName(const char* name); + const StdMeshAnimation* GetAnimationByName(const StdStrBuf& name) const; const StdMeshMaterial& GetMaterial() const { return *Material; } private: @@ -214,17 +214,26 @@ class StdMeshInstance public: StdMeshInstance(const StdMesh& mesh); - void SetAnimation(const StdStrBuf& animation); - const StdMeshAnimation& GetAnimation() const; + void SetAnimation(const StdStrBuf& animation_name); + void UnsetAnimation(); + + const StdMeshAnimation* GetAnimation() const { return Animation; } void SetPosition(float position); + float GetPosition() const { return Position; } // Get vertex of instance, with current animation applied. This needs to // go elsewhere if/when we want to calculate this on the hardware. const StdMeshVertex& GetVertex(unsigned int i) const { return Vertices[i]; } unsigned int GetNumVertices() const { return Vertices.size(); } + const StdMesh& Mesh; + protected: + const StdMeshAnimation* Animation; + float Position; + + std::vector BoneTransforms; std::vector Vertices; }; diff --git a/standard/src/StdMesh.cpp b/standard/src/StdMesh.cpp index 9e3d0b5e9..a583ca714 100644 --- a/standard/src/StdMesh.cpp +++ b/standard/src/StdMesh.cpp @@ -224,7 +224,6 @@ void StdMeshVertex::Transform(const StdMeshMatrix& trans) nz = trans(2,0)*old.nx + trans(2,1)*old.ny + trans(2,2)*old.nz; } -#if 0 void StdMeshVertex::Mul(float f) { x *= f; @@ -249,7 +248,6 @@ void StdMeshVertex::Add(const StdMeshVertex& other) ny += other.ny; nz += other.nz; } -#endif StdMeshMatrix StdMeshTrack::GetTransformAt(float time) const { @@ -610,4 +608,93 @@ void StdMesh::AddMasterBone(StdMeshBone* bone) AddMasterBone(bone->Children[i]); } +const StdMeshAnimation* StdMesh::GetAnimationByName(const StdStrBuf& name) const +{ + std::map::const_iterator iter = Animations.find(name); + if(iter == Animations.end()) return NULL; + return &iter->second; +} + +StdMeshInstance::StdMeshInstance(const StdMesh& mesh): + Mesh(mesh), Animation(NULL), Position(0.0f), + BoneTransforms(Mesh.GetNumBones()), Vertices(Mesh.GetNumVertices()) +{ + for(unsigned int i = 0; i < Mesh.GetNumVertices(); ++i) + Vertices[i] = Mesh.GetVertex(i); +} + +void StdMeshInstance::SetAnimation(const StdStrBuf& animation_name) +{ + Animation = Mesh.GetAnimationByName(animation_name); + SetPosition(0.0f); +} + +void StdMeshInstance::UnsetAnimation() +{ + Animation = NULL; + + // Reset instance vertices + for(unsigned int i = 0; i < Mesh.GetNumVertices(); ++i) + Vertices[i] = Mesh.GetVertex(i); +} + +void StdMeshInstance::SetPosition(float position) +{ + assert(Animation); + Position = position; + + // Compute transformation matrix for each bone. + for(unsigned int i = 0; i < BoneTransforms.size(); ++i) + { + StdMeshTrack* track = Animation->Tracks[i]; + if(track) + { + BoneTransforms[i] = track->GetTransformAt(position); + } + else + { + // No track for this bone, so use parent transformation + const StdMeshBone* parent = Mesh.GetBone(i).GetParent(); + if(parent) + { + // Parent should already have been processed, because the bone indices + // are supposed to be hierarchically ordered. + assert(parent->Index < i); + BoneTransforms[i] = BoneTransforms[parent->Index]; + } + else + { + BoneTransforms[i].SetIdentity(); + } + } + } + + // Compute transformation for each vertex. We could later think about + // doing this on the GPU using a vertex shader. This would then probably + // need to go to CStdGL::PerformMesh and CStdD3D::PerformMesh. + for(unsigned int i = 0; i < Vertices.size(); ++i) + { + const StdMesh::Vertex& vertex = Mesh.Vertices[i]; + if(!vertex.BoneAssignments.empty()) + { + Vertices[i].x = Vertices[i].y = Vertices[i].z = 0.0f; + Vertices[i].nx = Vertices[i].ny = Vertices[i].nz = 0.0f; + Vertices[i].u = vertex.u; Vertices[i].v = vertex.v; + + for(unsigned int j = 0; j < vertex.BoneAssignments.size(); ++j) + { + const StdMeshVertexBoneAssignment& assignment = vertex.BoneAssignments[j]; + StdMeshVertex vtx = vertex; + vtx.Transform(BoneTransforms[assignment.BoneIndex]); + vtx.Mul(assignment.Weight); + Vertices[i].Add(vtx); + } + } + else + { + Vertices[i] = vertex; + } + } +} + // vim: et ts=2 sw=2