2009-07-08 22:01:15 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2006, 2010 Sven Eberhardt
|
2011-09-01 14:58:52 +00:00
|
|
|
* Copyright (c) 2009-2011 Armin Burgmeier
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2010 Benjamin Herr
|
|
|
|
* Copyright (c) 2010 Nicolas Hake
|
2009-07-08 22:01:15 +00:00
|
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
|
|
*
|
|
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
|
|
* to OpenClonk.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
* See isc_license.txt for full license and disclaimer.
|
|
|
|
*
|
|
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
|
|
* See clonk_trademark_license.txt for full license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INC_StdMesh
|
|
|
|
#define INC_StdMesh
|
|
|
|
|
|
|
|
#include <StdMeshMaterial.h>
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
class StdCompiler;
|
|
|
|
|
2010-03-02 16:12:28 +00:00
|
|
|
// OGRE mesh
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-01-05 16:20:46 +00:00
|
|
|
struct StdMeshVector
|
|
|
|
{
|
|
|
|
float x, y, z;
|
2010-01-05 21:35:30 +00:00
|
|
|
|
|
|
|
static StdMeshVector Zero();
|
|
|
|
static StdMeshVector UnitScale();
|
|
|
|
static StdMeshVector Translate(float dx, float dy, float dz);
|
2010-01-05 16:20:46 +00:00
|
|
|
static StdMeshVector Cross(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct StdMeshVertex
|
|
|
|
{
|
|
|
|
// Match GL_T2F_N3F_V3F
|
|
|
|
float u, v;
|
|
|
|
float nx, ny, nz;
|
|
|
|
float x, y, z;
|
|
|
|
|
2010-01-05 21:35:30 +00:00
|
|
|
//void Normalize();
|
2010-01-05 16:20:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct StdMeshQuaternion
|
|
|
|
{
|
|
|
|
float w;
|
2010-01-25 04:00:59 +00:00
|
|
|
// union
|
|
|
|
// {
|
|
|
|
// struct { float x, y, z; };
|
|
|
|
// StdMeshVector v;
|
|
|
|
// };
|
|
|
|
float x, y, z;
|
2010-01-05 16:20:46 +00:00
|
|
|
|
2010-01-05 21:35:30 +00:00
|
|
|
static StdMeshQuaternion Zero();
|
|
|
|
static StdMeshQuaternion AngleAxis(float theta, const StdMeshVector& axis);
|
|
|
|
|
2010-01-05 16:20:46 +00:00
|
|
|
float LenSqr() const { return w*w+x*x+y*y+z*z; }
|
2010-01-05 21:35:30 +00:00
|
|
|
void Normalize();
|
2010-01-05 16:20:46 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
static StdMeshQuaternion Nlerp(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs, float w);
|
|
|
|
//static StdMeshQuaternion Slerp(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs, float w);
|
2010-01-05 16:20:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct StdMeshTransformation
|
|
|
|
{
|
|
|
|
StdMeshVector scale;
|
|
|
|
StdMeshQuaternion rotate;
|
|
|
|
StdMeshVector translate;
|
|
|
|
|
|
|
|
static StdMeshTransformation Zero();
|
|
|
|
static StdMeshTransformation Identity();
|
2010-01-05 21:35:30 +00:00
|
|
|
static StdMeshTransformation Inverse(const StdMeshTransformation& transform);
|
|
|
|
static StdMeshTransformation Translate(float dx, float dy, float dz);
|
|
|
|
static StdMeshTransformation Scale(float sx, float sy, float sz);
|
|
|
|
static StdMeshTransformation Rotate(float angle, float rx, float ry, float rz);
|
2010-01-22 18:27:02 +00:00
|
|
|
|
|
|
|
// TODO: Might add path parameter if necessary
|
|
|
|
static StdMeshTransformation Nlerp(const StdMeshTransformation& lhs, const StdMeshTransformation& rhs, float w);
|
|
|
|
//static StdMeshQuaternion Slerp(const StdMeshTransformation& lhs, const StdMeshTransformation& rhs, float w);
|
2010-01-05 16:20:46 +00:00
|
|
|
};
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
class StdMeshMatrix
|
|
|
|
{
|
|
|
|
public:
|
2010-01-05 16:20:46 +00:00
|
|
|
static StdMeshMatrix Zero();
|
|
|
|
static StdMeshMatrix Identity();
|
|
|
|
static StdMeshMatrix Inverse(const StdMeshMatrix& mat);
|
|
|
|
static StdMeshMatrix Translate(float dx, float dy, float dz);
|
|
|
|
static StdMeshMatrix Scale(float sx, float sy, float sz);
|
|
|
|
static StdMeshMatrix Rotate(float angle, float rx, float ry, float rz);
|
|
|
|
static StdMeshMatrix Transform(const StdMeshTransformation& transform);
|
|
|
|
static StdMeshMatrix TransformInverse(const StdMeshTransformation& transform);
|
2009-08-01 19:36:13 +00:00
|
|
|
|
|
|
|
float& operator()(int i, int j) { return a[i][j]; }
|
|
|
|
float operator()(int i, int j) const { return a[i][j]; }
|
|
|
|
|
2010-01-29 14:58:33 +00:00
|
|
|
float Determinant() const;
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
private:
|
2009-08-01 19:36:13 +00:00
|
|
|
// 3x3 orthogonal + translation in last column
|
|
|
|
float a[3][4];
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshMatrix operator*(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
|
|
|
StdMeshMatrix operator*(float lhs, const StdMeshMatrix& rhs);
|
|
|
|
StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs);
|
2010-06-08 22:55:34 +00:00
|
|
|
StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
|
|
|
StdMeshQuaternion operator-(const StdMeshQuaternion& rhs);
|
|
|
|
StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshQuaternion& operator*=(StdMeshQuaternion& lhs, float rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, float rhs);
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshQuaternion operator*(float lhs, const StdMeshQuaternion& rhs);
|
|
|
|
StdMeshQuaternion& operator+=(StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshQuaternion operator+(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
2010-01-22 18:27:02 +00:00
|
|
|
StdMeshQuaternion operator-(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshTransformation operator*(const StdMeshTransformation& lhs, const StdMeshTransformation& rhs);
|
|
|
|
|
|
|
|
StdMeshVector operator-(const StdMeshVector& rhs);
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshVector& operator+=(StdMeshVector& lhs, const StdMeshVector& rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshVector operator+(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
|
|
|
StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshVector& operator*=(StdMeshVector& lhs, float rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshVector operator*(const StdMeshVector& lhs, float rhs);
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshVector operator*(float lhs, const StdMeshVector& rhs);
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshVector operator/(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
|
|
|
StdMeshVector operator/(float lhs, const StdMeshVector& rhs);
|
|
|
|
StdMeshVector operator/(const StdMeshVector& lhs, float rhs);
|
|
|
|
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshVector operator*(const StdMeshMatrix& lhs, const StdMeshVector& rhs); // does not apply translation part
|
2010-01-05 16:20:46 +00:00
|
|
|
StdMeshVector operator*(const StdMeshQuaternion& lhs, const StdMeshVector& rhs);
|
|
|
|
|
|
|
|
StdMeshVertex& operator+=(StdMeshVertex& lhs, const StdMeshVertex& rhs);
|
|
|
|
StdMeshVertex operator+(const StdMeshVertex& lhs, const StdMeshVertex& rhs);
|
|
|
|
StdMeshVertex operator*(float lhs, const StdMeshVertex& rhs);
|
|
|
|
StdMeshVertex operator*(const StdMeshVertex& lhs, float rhs);
|
|
|
|
StdMeshVertex operator*(const StdMeshMatrix& lhs, const StdMeshVertex& rhs);
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
class StdMeshBone
|
|
|
|
{
|
2009-08-01 19:36:13 +00:00
|
|
|
friend class StdMesh;
|
2010-03-02 16:12:28 +00:00
|
|
|
friend class StdMeshLoader;
|
2009-07-08 22:01:15 +00:00
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshBone() {}
|
2009-07-09 22:18:26 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
unsigned int Index; // Index in master bone table
|
|
|
|
int ID; // Bone ID
|
2010-01-10 21:02:40 +00:00
|
|
|
StdCopyStrBuf Name; // Bone name
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
// Bone transformation
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshTransformation Transformation;
|
2009-08-01 19:36:13 +00:00
|
|
|
// Inverse transformation
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshTransformation InverseTransformation;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
const StdMeshBone* GetParent() const { return Parent; }
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const StdMeshBone& GetChild(size_t i) const { return *Children[i]; }
|
|
|
|
size_t GetNumChildren() const { return Children.size(); }
|
2009-07-08 22:01:15 +00:00
|
|
|
|
|
|
|
private:
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshBone* Parent; // Parent bone
|
|
|
|
std::vector<StdMeshBone*> Children; // Children. Not owned.
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshBone(const StdMeshBone&); // non-copyable
|
|
|
|
StdMeshBone& operator=(const StdMeshBone&); // non-assignable
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class StdMeshVertexBoneAssignment
|
|
|
|
{
|
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
unsigned int BoneIndex;
|
|
|
|
float Weight;
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class StdMeshFace
|
|
|
|
{
|
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
unsigned int Vertices[3];
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Keyframe, specifies transformation for one bone in a particular frame
|
|
|
|
class StdMeshKeyFrame
|
|
|
|
{
|
|
|
|
public:
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshTransformation Transformation;
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Animation track, specifies transformation for one bone for each keyframe
|
|
|
|
class StdMeshTrack
|
|
|
|
{
|
2010-09-09 20:40:07 +00:00
|
|
|
friend class StdMesh;
|
2010-03-02 16:12:28 +00:00
|
|
|
friend class StdMeshLoader;
|
2009-07-08 22:01:15 +00:00
|
|
|
public:
|
2010-01-05 21:35:30 +00:00
|
|
|
StdMeshTransformation GetTransformAt(float time) const;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
|
|
|
private:
|
2009-08-01 19:36:13 +00:00
|
|
|
std::map<float, StdMeshKeyFrame> Frames;
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Animation, consists of one Track for each animated Bone
|
|
|
|
class StdMeshAnimation
|
|
|
|
{
|
2010-09-09 20:40:07 +00:00
|
|
|
friend class StdMesh;
|
2010-03-02 16:12:28 +00:00
|
|
|
friend class StdMeshLoader;
|
2009-08-01 19:36:13 +00:00
|
|
|
friend class StdMeshInstance;
|
2009-07-08 22:01:15 +00:00
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshAnimation() {}
|
|
|
|
StdMeshAnimation(const StdMeshAnimation& other);
|
|
|
|
~StdMeshAnimation();
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshAnimation& operator=(const StdMeshAnimation& other);
|
2009-07-09 22:18:26 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdCopyStrBuf Name;
|
|
|
|
float Length;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-03-21 18:34:22 +00:00
|
|
|
private:
|
2009-08-01 19:36:13 +00:00
|
|
|
std::vector<StdMeshTrack*> Tracks; // bone-indexed
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
2009-07-10 20:02:32 +00:00
|
|
|
struct StdMeshBox
|
|
|
|
{
|
2009-08-01 19:36:13 +00:00
|
|
|
float x1, y1, z1;
|
|
|
|
float x2, y2, z2;
|
2009-07-10 20:02:32 +00:00
|
|
|
};
|
|
|
|
|
2010-01-11 23:54:36 +00:00
|
|
|
class StdSubMesh
|
|
|
|
{
|
|
|
|
friend class StdMesh;
|
2010-03-02 16:12:28 +00:00
|
|
|
friend class StdMeshLoader;
|
2011-08-17 21:50:33 +00:00
|
|
|
friend class StdMeshMaterialUpdate;
|
2010-01-11 23:54:36 +00:00
|
|
|
public:
|
|
|
|
// Remember bone assignments for vertices
|
|
|
|
class Vertex: public StdMeshVertex
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::vector<StdMeshVertexBoneAssignment> BoneAssignments;
|
|
|
|
};
|
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const Vertex& GetVertex(size_t i) const { return Vertices[i]; }
|
|
|
|
size_t GetNumVertices() const { return Vertices.size(); }
|
2010-01-11 23:54:36 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const StdMeshFace& GetFace(size_t i) const { return Faces[i]; }
|
|
|
|
size_t GetNumFaces() const { return Faces.size(); }
|
2010-01-11 23:54:36 +00:00
|
|
|
|
|
|
|
const StdMeshMaterial& GetMaterial() const { return *Material; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
StdSubMesh();
|
|
|
|
|
|
|
|
std::vector<Vertex> Vertices;
|
|
|
|
std::vector<StdMeshFace> Faces;
|
|
|
|
|
|
|
|
const StdMeshMaterial* Material;
|
|
|
|
};
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
class StdMesh
|
|
|
|
{
|
2010-03-02 16:12:28 +00:00
|
|
|
friend class StdMeshLoader;
|
2011-08-17 21:50:33 +00:00
|
|
|
friend class StdMeshMaterialUpdate;
|
2011-08-19 22:01:08 +00:00
|
|
|
friend class StdMeshUpdate;
|
2011-08-17 21:50:33 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMesh();
|
2010-03-02 16:12:28 +00:00
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
~StdMesh();
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const StdSubMesh& GetSubMesh(size_t i) const { return SubMeshes[i]; }
|
|
|
|
size_t GetNumSubMeshes() const { return SubMeshes.size(); }
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const StdMeshBone& GetBone(size_t i) const { return *Bones[i]; }
|
|
|
|
size_t GetNumBones() const { return Bones.size(); }
|
2010-01-29 21:18:18 +00:00
|
|
|
const StdMeshBone* GetBoneByName(const StdStrBuf& name) const;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
const StdMeshAnimation* GetAnimationByName(const StdStrBuf& name) const;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
const StdMeshBox& GetBoundingBox() const { return BoundingBox; }
|
2010-03-17 20:15:00 +00:00
|
|
|
float GetBoundingRadius() const { return BoundingRadius; }
|
2009-07-10 20:02:32 +00:00
|
|
|
|
2010-09-09 20:40:07 +00:00
|
|
|
// TODO: This code should maybe better be placed in StdMeshLoader...
|
|
|
|
void MirrorAnimation(const StdStrBuf& name, const StdMeshAnimation& animation);
|
2010-12-04 22:33:05 +00:00
|
|
|
void PostInit();
|
2010-09-09 20:40:07 +00:00
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
private:
|
2009-08-01 19:36:13 +00:00
|
|
|
void AddMasterBone(StdMeshBone* bone);
|
2009-07-09 22:18:26 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMesh(const StdMesh& other); // non-copyable
|
|
|
|
StdMesh& operator=(const StdMesh& other); // non-assignable
|
2009-07-09 22:18:26 +00:00
|
|
|
|
2010-01-11 23:54:36 +00:00
|
|
|
std::vector<StdSubMesh> SubMeshes;
|
2009-08-01 19:36:13 +00:00
|
|
|
std::vector<StdMeshBone*> Bones; // Master Bone Table
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
std::map<StdCopyStrBuf, StdMeshAnimation> Animations;
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshBox BoundingBox;
|
2010-03-17 20:15:00 +00:00
|
|
|
float BoundingRadius;
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
class StdSubMeshInstance
|
|
|
|
{
|
|
|
|
friend class StdMeshInstance;
|
2011-08-17 21:50:33 +00:00
|
|
|
friend class StdMeshMaterialUpdate;
|
2010-03-16 22:31:53 +00:00
|
|
|
public:
|
2011-10-15 19:35:39 +00:00
|
|
|
|
|
|
|
enum FaceOrdering
|
|
|
|
{
|
|
|
|
FO_Fixed, // don't reorder, keep faces as in mesh
|
|
|
|
FO_FarthestToNearest,
|
|
|
|
FO_NearestToFarthest
|
|
|
|
};
|
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
StdSubMeshInstance(const StdSubMesh& submesh);
|
|
|
|
|
|
|
|
// 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* GetVertices() const { return &Vertices[0]; }
|
2010-04-20 16:20:24 +00:00
|
|
|
size_t GetNumVertices() const { return Vertices.size(); }
|
2010-03-16 22:31:53 +00:00
|
|
|
|
|
|
|
// Get face of instance. The instance faces are the same as the mesh faces,
|
|
|
|
// with the exception that they are differently ordered, depending on the
|
|
|
|
// current FaceOrdering. See FaceOrdering in StdMeshInstance.
|
|
|
|
const StdMeshFace* GetFaces() const { return &Faces[0]; }
|
2010-04-20 16:20:24 +00:00
|
|
|
size_t GetNumFaces() const { return Faces.size(); }
|
2010-03-16 22:31:53 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
unsigned int GetTexturePhase(size_t pass, size_t texunit) const { return PassData[pass].TexUnits[texunit].Phase; }
|
|
|
|
double GetTexturePosition(size_t pass, size_t texunit) const { return PassData[pass].TexUnits[texunit].Position; }
|
2010-03-16 22:31:53 +00:00
|
|
|
|
2010-03-17 22:04:56 +00:00
|
|
|
void SetMaterial(const StdMeshMaterial& material);
|
2010-03-16 22:31:53 +00:00
|
|
|
const StdMeshMaterial& GetMaterial() const { return *Material; }
|
2011-10-15 19:35:39 +00:00
|
|
|
|
|
|
|
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
2010-03-16 22:31:53 +00:00
|
|
|
protected:
|
2011-10-15 19:35:39 +00:00
|
|
|
void SetFaceOrdering(const StdSubMesh& submesh, FaceOrdering ordering);
|
|
|
|
void SetFaceOrderingForClrModulation(const StdSubMesh& submesh, uint32_t clrmod);
|
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
// Vertices transformed according to current animation
|
|
|
|
// Faces sorted according to current face ordering
|
|
|
|
// TODO: We can skip these if we decide to either
|
|
|
|
// a) recompute Vertex positions each frame or
|
|
|
|
// b) compute them on the GPU
|
|
|
|
std::vector<StdMeshVertex> Vertices;
|
|
|
|
std::vector<StdMeshFace> Faces;
|
|
|
|
|
|
|
|
const StdMeshMaterial* Material;
|
|
|
|
|
|
|
|
struct TexUnit // Runtime texunit data
|
|
|
|
{
|
2010-03-17 19:19:14 +00:00
|
|
|
// Frame animation
|
2010-03-16 22:31:53 +00:00
|
|
|
float PhaseDelay;
|
|
|
|
unsigned int Phase;
|
2010-03-17 19:19:14 +00:00
|
|
|
|
|
|
|
// Coordinate transformation animation
|
|
|
|
// This is never reset so use double to make sure we have enough precision
|
|
|
|
double Position;
|
2010-03-16 22:31:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Pass // Runtime pass data
|
|
|
|
{
|
|
|
|
std::vector<TexUnit> TexUnits;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<Pass> PassData;
|
2011-10-15 19:35:39 +00:00
|
|
|
FaceOrdering CurrentFaceOrdering; // NoSave
|
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
private:
|
|
|
|
StdSubMeshInstance(const StdSubMeshInstance& other); // noncopyable
|
|
|
|
StdSubMeshInstance& operator=(const StdSubMeshInstance& other); // noncopyable
|
|
|
|
};
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
class StdMeshInstance
|
|
|
|
{
|
2011-08-17 21:50:33 +00:00
|
|
|
friend class StdMeshMaterialUpdate;
|
2011-08-19 22:01:08 +00:00
|
|
|
friend class StdMeshUpdate;
|
2009-07-08 22:01:15 +00:00
|
|
|
public:
|
2009-08-01 19:36:13 +00:00
|
|
|
StdMeshInstance(const StdMesh& mesh);
|
2010-01-10 21:02:40 +00:00
|
|
|
~StdMeshInstance();
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2011-10-15 19:35:39 +00:00
|
|
|
typedef StdSubMeshInstance::FaceOrdering FaceOrdering;
|
2009-07-23 23:52:18 +00:00
|
|
|
|
2011-10-15 19:35:39 +00:00
|
|
|
//FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
2009-08-01 19:36:13 +00:00
|
|
|
void SetFaceOrdering(FaceOrdering ordering);
|
2010-06-08 22:55:34 +00:00
|
|
|
void SetFaceOrderingForClrModulation(uint32_t clrmod);
|
2009-07-23 23:52:18 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
// Provider for animation position or weight.
|
|
|
|
class ValueProvider
|
|
|
|
{
|
|
|
|
public:
|
2010-02-02 18:25:51 +00:00
|
|
|
ValueProvider(): Value(Fix0) {}
|
2010-01-22 18:27:02 +00:00
|
|
|
virtual ~ValueProvider() {}
|
|
|
|
|
|
|
|
// Return false if the corresponding node is to be removed or true
|
|
|
|
// otherwise.
|
|
|
|
virtual bool Execute() = 0;
|
|
|
|
|
2010-05-04 15:35:18 +00:00
|
|
|
C4Real Value; // Current provider value
|
2010-01-22 18:27:02 +00:00
|
|
|
};
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
// Serializable value providers need to be registered with SerializeableValueProvider::Register.
|
|
|
|
// They also need to implement a default constructor and a compile func
|
|
|
|
class SerializableValueProvider: public ValueProvider
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct IDBase;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Pointer for deterministic initialization
|
|
|
|
static std::vector<IDBase*>* IDs;
|
|
|
|
|
|
|
|
public:
|
|
|
|
struct IDBase
|
|
|
|
{
|
|
|
|
typedef SerializableValueProvider*(*NewFunc)();
|
|
|
|
protected:
|
|
|
|
IDBase(const char* name, const std::type_info& type, NewFunc newfunc):
|
|
|
|
name(name), type(type), newfunc(newfunc)
|
|
|
|
{
|
|
|
|
if(!IDs) IDs = new std::vector<IDBase*>;
|
|
|
|
IDs->push_back(this);
|
|
|
|
}
|
|
|
|
|
2010-12-07 22:43:00 +00:00
|
|
|
virtual ~IDBase()
|
|
|
|
{
|
|
|
|
assert(IDs);
|
|
|
|
IDs->erase(std::find(IDs->begin(), IDs->end(), this));
|
|
|
|
if (!IDs->size()) { delete IDs; IDs = NULL; }
|
|
|
|
}
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
public:
|
|
|
|
const char* name;
|
|
|
|
const std::type_info& type;
|
|
|
|
NewFunc newfunc;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct ID: IDBase
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
static SerializableValueProvider* CreateFunc() { return new T; }
|
|
|
|
|
|
|
|
public:
|
|
|
|
ID(const char* name):
|
|
|
|
IDBase(name, typeid(T), CreateFunc) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const IDBase* Lookup(const char* name)
|
|
|
|
{
|
|
|
|
if(!IDs) return NULL;
|
|
|
|
for(unsigned int i = 0; i < IDs->size(); ++i)
|
|
|
|
if(strcmp((*IDs)[i]->name, name) == 0)
|
|
|
|
return (*IDs)[i];
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const IDBase* Lookup(const std::type_info& type)
|
|
|
|
{
|
|
|
|
if(!IDs) return NULL;
|
|
|
|
for(unsigned int i = 0; i < IDs->size(); ++i)
|
|
|
|
if((*IDs)[i]->type == type)
|
|
|
|
return (*IDs)[i];
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void CompileFunc(StdCompiler* pComp);
|
|
|
|
virtual void DenumeratePointers() {}
|
|
|
|
};
|
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
// A node in the animation tree
|
|
|
|
// Can be either a leaf node, or interpolation between two other nodes
|
|
|
|
class AnimationNode
|
2009-12-30 20:41:56 +00:00
|
|
|
{
|
2010-01-22 18:27:02 +00:00
|
|
|
friend class StdMeshInstance;
|
2011-08-19 22:01:08 +00:00
|
|
|
friend class StdMeshUpdate;
|
2010-01-22 18:27:02 +00:00
|
|
|
public:
|
|
|
|
enum NodeType { LeafNode, LinearInterpolationNode };
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
AnimationNode();
|
2010-01-22 18:27:02 +00:00
|
|
|
AnimationNode(const StdMeshAnimation* animation, ValueProvider* position);
|
|
|
|
AnimationNode(AnimationNode* child_left, AnimationNode* child_right, ValueProvider* weight);
|
|
|
|
~AnimationNode();
|
|
|
|
|
|
|
|
bool GetBoneTransform(unsigned int bone, StdMeshTransformation& transformation);
|
2009-12-30 20:41:56 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
int GetSlot() const { return Slot; }
|
|
|
|
unsigned int GetNumber() const { return Number; }
|
|
|
|
NodeType GetType() const { return Type; }
|
|
|
|
AnimationNode* GetParent() { return Parent; }
|
2009-12-30 20:41:56 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
const StdMeshAnimation* GetAnimation() const { assert(Type == LeafNode); return Leaf.Animation; }
|
|
|
|
ValueProvider* GetPositionProvider() { assert(Type == LeafNode); return Leaf.Position; }
|
2010-05-04 15:35:18 +00:00
|
|
|
C4Real GetPosition() const { assert(Type == LeafNode); return Leaf.Position->Value; }
|
2009-12-30 20:41:56 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
AnimationNode* GetLeftChild() { assert(Type == LinearInterpolationNode); return LinearInterpolation.ChildLeft; }
|
|
|
|
AnimationNode* GetRightChild() { assert(Type == LinearInterpolationNode); return LinearInterpolation.ChildRight; }
|
|
|
|
ValueProvider* GetWeightProvider() { assert(Type == LinearInterpolationNode); return LinearInterpolation.Weight; }
|
2010-05-04 15:35:18 +00:00
|
|
|
C4Real GetWeight() const { assert(Type == LinearInterpolationNode); return LinearInterpolation.Weight->Value; }
|
2010-01-22 18:27:02 +00:00
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
void CompileFunc(StdCompiler* pComp, const StdMesh* Mesh);
|
|
|
|
void DenumeratePointers();
|
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
protected:
|
|
|
|
int Slot;
|
|
|
|
unsigned int Number;
|
|
|
|
NodeType Type;
|
2010-04-01 21:00:05 +00:00
|
|
|
AnimationNode* Parent; // NoSave
|
2010-01-22 18:27:02 +00:00
|
|
|
|
|
|
|
union
|
|
|
|
{
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
const StdMeshAnimation* Animation;
|
|
|
|
ValueProvider* Position;
|
|
|
|
} Leaf;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
AnimationNode* ChildLeft;
|
|
|
|
AnimationNode* ChildRight;
|
|
|
|
ValueProvider* Weight;
|
|
|
|
} LinearInterpolation;
|
|
|
|
};
|
2009-12-30 20:41:56 +00:00
|
|
|
};
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
|
|
|
AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
|
|
|
void StopAnimation(AnimationNode* node);
|
|
|
|
|
|
|
|
AnimationNode* GetAnimationNodeByNumber(unsigned int number);
|
|
|
|
AnimationNode* GetRootAnimationForSlot(int slot);
|
2010-03-28 17:58:21 +00:00
|
|
|
// child bone transforms are dirty (saves matrix inversion for unanimated attach children).
|
2010-01-22 18:27:02 +00:00
|
|
|
// Set new value providers for a node's position or weight - cannot be in
|
|
|
|
// class AnimationNode since we need to mark BoneTransforms dirty.
|
|
|
|
void SetAnimationPosition(AnimationNode* node, ValueProvider* position);
|
|
|
|
void SetAnimationWeight(AnimationNode* node, ValueProvider* weight);
|
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
// Update animations; call once a frame
|
|
|
|
// dt is used for texture animation, skeleton animation is updated via value providers
|
|
|
|
void ExecuteAnimation(float dt);
|
2009-07-08 22:01:15 +00:00
|
|
|
|
2010-08-31 21:44:56 +00:00
|
|
|
enum AttachMeshFlags {
|
|
|
|
AM_None = 0,
|
|
|
|
AM_DrawBefore = 1 << 0
|
|
|
|
};
|
|
|
|
|
2010-01-29 21:18:18 +00:00
|
|
|
class AttachedMesh
|
2010-01-10 21:02:40 +00:00
|
|
|
{
|
2010-01-29 21:18:18 +00:00
|
|
|
friend class StdMeshInstance;
|
2011-08-19 22:01:08 +00:00
|
|
|
friend class StdMeshUpdate;
|
2010-01-29 21:18:18 +00:00
|
|
|
public:
|
2010-04-01 21:00:05 +00:00
|
|
|
// The job of this class is to help serialize the Child and OwnChild members of AttachedMesh
|
|
|
|
class Denumerator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~Denumerator() {}
|
|
|
|
|
|
|
|
virtual void CompileFunc(StdCompiler* pComp, AttachedMesh* attach) = 0;
|
|
|
|
virtual void DenumeratePointers(AttachedMesh* attach) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Denumerator*(*DenumeratorFactoryFunc)();
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static Denumerator* DenumeratorFactory() { return new T; }
|
|
|
|
|
|
|
|
AttachedMesh();
|
|
|
|
AttachedMesh(unsigned int number, StdMeshInstance* parent, StdMeshInstance* child, bool own_child, Denumerator* denumerator,
|
2010-08-31 21:44:56 +00:00
|
|
|
unsigned int parent_bone, unsigned int child_bone, const StdMeshMatrix& transform, uint32_t flags);
|
2010-01-29 21:18:18 +00:00
|
|
|
~AttachedMesh();
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
uint32_t Number;
|
|
|
|
StdMeshInstance* Parent; // NoSave (set by parent)
|
|
|
|
StdMeshInstance* Child;
|
|
|
|
bool OwnChild; // NoSave
|
|
|
|
Denumerator* ChildDenumerator;
|
2010-01-29 21:18:18 +00:00
|
|
|
|
|
|
|
bool SetParentBone(const StdStrBuf& bone);
|
|
|
|
bool SetChildBone(const StdStrBuf& bone);
|
|
|
|
void SetAttachTransformation(const StdMeshMatrix& transformation);
|
|
|
|
const StdMeshMatrix& GetFinalTransformation() const { return FinalTrans; }
|
2010-08-31 21:44:56 +00:00
|
|
|
uint32_t GetFlags() const { return Flags; }
|
2010-01-29 21:18:18 +00:00
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
void CompileFunc(StdCompiler* pComp, DenumeratorFactoryFunc Factory);
|
|
|
|
void DenumeratePointers();
|
|
|
|
|
2010-01-29 21:18:18 +00:00
|
|
|
private:
|
2010-01-10 21:02:40 +00:00
|
|
|
unsigned int ParentBone;
|
|
|
|
unsigned int ChildBone;
|
2010-01-29 21:18:18 +00:00
|
|
|
StdMeshMatrix AttachTrans;
|
2010-08-31 21:44:56 +00:00
|
|
|
uint32_t Flags;
|
2010-01-29 21:18:18 +00:00
|
|
|
|
|
|
|
// Cache final attach transformation, updated in UpdateBoneTransform
|
2010-04-01 21:00:05 +00:00
|
|
|
StdMeshMatrix FinalTrans; // NoSave
|
|
|
|
bool FinalTransformDirty; // NoSave; Whether FinalTrans is up to date or not
|
2010-01-10 21:02:40 +00:00
|
|
|
};
|
2010-01-22 18:27:02 +00:00
|
|
|
|
2010-01-29 21:18:18 +00:00
|
|
|
typedef std::vector<AttachedMesh*> AttachedMeshList;
|
2010-01-10 21:02:40 +00:00
|
|
|
typedef AttachedMeshList::const_iterator AttachedMeshIter;
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
// Create a new instance and attach it to this mesh. Takes ownership of denumerator
|
2010-08-31 21:44:56 +00:00
|
|
|
AttachedMesh* AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity(), uint32_t flags = AM_None);
|
2010-04-01 21:00:05 +00:00
|
|
|
// Attach an instance to this instance. Takes ownership of denumerator. If own_child is true deletes instance on detach.
|
2010-08-31 21:44:56 +00:00
|
|
|
AttachedMesh* AttachMesh(StdMeshInstance& instance, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity(), uint32_t flags = AM_None, bool own_child = false);
|
2010-01-10 21:02:40 +00:00
|
|
|
// Removes attachment with given number
|
|
|
|
bool DetachMesh(unsigned int number);
|
|
|
|
// Returns attached mesh with given number
|
2010-01-29 21:18:18 +00:00
|
|
|
AttachedMesh* GetAttachedMeshByNumber(unsigned int number) const;
|
2010-01-10 21:02:40 +00:00
|
|
|
|
|
|
|
// To iterate through attachments
|
|
|
|
AttachedMeshIter AttachedMeshesBegin() const { return AttachChildren.begin(); }
|
|
|
|
AttachedMeshIter AttachedMeshesEnd() const { return AttachChildren.end(); }
|
2010-01-29 21:18:18 +00:00
|
|
|
AttachedMesh* GetAttachParent() const { return AttachParent; }
|
2010-01-10 21:02:40 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
size_t GetNumSubMeshes() const { return SubMeshInstances.size(); }
|
|
|
|
StdSubMeshInstance& GetSubMesh(size_t i) { return *SubMeshInstances[i]; }
|
|
|
|
const StdSubMeshInstance& GetSubMesh(size_t i) const { return *SubMeshInstances[i]; }
|
2009-07-23 23:52:18 +00:00
|
|
|
|
2010-04-20 16:20:24 +00:00
|
|
|
const StdMeshMatrix& GetBoneTransform(size_t i) const { return BoneTransforms[i]; }
|
2009-07-10 19:57:11 +00:00
|
|
|
|
2010-01-29 21:18:18 +00:00
|
|
|
// Update bone transformation matrices, vertex positions and final attach transformations of attached children.
|
|
|
|
// This is called recursively for attached children, so there is no need to call it on attached children only
|
2010-06-08 22:55:34 +00:00
|
|
|
// which would also not update its attach transformation. Call this once before rendering. Returns true if the
|
|
|
|
// mesh was deformed since the last execution, or false otherwise.
|
|
|
|
bool UpdateBoneTransforms();
|
|
|
|
|
|
|
|
// Orders faces according to current face ordering. Clal this once before rendering if one of the following is true:
|
|
|
|
//
|
|
|
|
// a) the call to UpdateBoneTransforms returns true
|
|
|
|
// b) a submesh's material was changed
|
|
|
|
// c) the global transformation changed since previous call to ReorderFaces()
|
|
|
|
// d) some other obscure state change occurred (?)
|
|
|
|
//
|
|
|
|
// global_trans is a global transformation that is applied when rendering the mesh, and this is used
|
|
|
|
// to correctly do face ordering.
|
|
|
|
//
|
|
|
|
// TODO: Should maybe introduce a FaceOrderingDirty flag
|
|
|
|
void ReorderFaces(StdMeshMatrix* global_trans);
|
2010-01-06 01:11:56 +00:00
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
void CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory);
|
|
|
|
void DenumeratePointers();
|
|
|
|
|
2011-08-19 22:01:08 +00:00
|
|
|
const StdMesh& GetMesh() const { assert(Mesh != NULL); return *Mesh; }
|
2010-01-10 21:02:40 +00:00
|
|
|
|
2010-01-06 01:11:56 +00:00
|
|
|
protected:
|
2010-01-22 18:27:02 +00:00
|
|
|
typedef std::vector<AnimationNode*> AnimationNodeList;
|
|
|
|
|
|
|
|
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create);
|
|
|
|
bool ExecuteAnimationNode(AnimationNode* node);
|
2009-07-23 23:52:18 +00:00
|
|
|
|
2011-08-19 22:01:08 +00:00
|
|
|
const StdMesh* Mesh;
|
|
|
|
|
2010-01-22 18:27:02 +00:00
|
|
|
AnimationNodeList AnimationNodes; // for simple lookup of animation nodes by their unique number
|
|
|
|
AnimationNodeList AnimationStack; // contains top level nodes only, ordered by slot number
|
2009-08-01 19:36:13 +00:00
|
|
|
std::vector<StdMeshMatrix> BoneTransforms;
|
2009-12-30 20:41:56 +00:00
|
|
|
|
2010-03-16 22:31:53 +00:00
|
|
|
std::vector<StdSubMeshInstance*> SubMeshInstances;
|
2010-01-06 01:11:56 +00:00
|
|
|
|
2010-01-10 21:02:40 +00:00
|
|
|
// Not asymptotically efficient, but we do not expect many attached meshes anyway.
|
|
|
|
// In theory map would fit better, but it's probably not worth the extra overhead.
|
2010-01-29 21:18:18 +00:00
|
|
|
std::vector<AttachedMesh*> AttachChildren;
|
2010-01-10 21:02:40 +00:00
|
|
|
AttachedMesh* AttachParent;
|
|
|
|
|
2010-01-06 01:11:56 +00:00
|
|
|
bool BoneTransformsDirty;
|
2010-01-10 21:02:40 +00:00
|
|
|
private:
|
|
|
|
StdMeshInstance(const StdMeshInstance& other); // noncopyable
|
|
|
|
StdMeshInstance& operator=(const StdMeshInstance& other); // noncopyable
|
2009-07-08 22:01:15 +00:00
|
|
|
};
|
|
|
|
|
2010-04-01 21:00:05 +00:00
|
|
|
inline void CompileNewFuncCtx(StdMeshInstance::SerializableValueProvider *&pStruct, StdCompiler *pComp, const StdMeshInstance::SerializableValueProvider::IDBase& rID)
|
|
|
|
{
|
|
|
|
std::auto_ptr<StdMeshInstance::SerializableValueProvider> temp(rID.newfunc());
|
|
|
|
pComp->Value(*temp);
|
|
|
|
pStruct = temp.release();
|
|
|
|
}
|
|
|
|
|
2009-07-08 22:01:15 +00:00
|
|
|
#endif
|