openclonk/standard/inc/StdMesh.h

252 lines
6.2 KiB
C++

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2009 Armin Burgmeier
* 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>
// Loader for OGRE meshes. Currently supports XML files only.
class StdMeshError: public std::exception
{
public:
StdMeshError(const StdStrBuf& message, const char* file, unsigned int line);
virtual ~StdMeshError() throw() {}
virtual const char* what() const throw() { return Buf.getData(); }
protected:
StdStrBuf Buf;
};
// Interface to load skeleton files. Given a filename occuring in the
// mesh file, this should load the skeleton file from wherever the mesh file
// was loaded from, for example from a C4Group. Return default-construted
// StdStrBuf with NULL data in case of error.
class StdMeshSkeletonLoader
{
public:
virtual StdStrBuf LoadSkeleton(const char* filename) = 0;
};
class StdMeshMatrix
{
public:
void SetIdentity();
void SetTranslate(float dx, float dy, float dz);
void SetScale(float sx, float sy, float sz);
void SetRotate(float angle, float rx, float ry, float rz);
float& operator()(int i, int j) { return a[i][j]; }
float operator()(int i, int j) const { return a[i][j]; }
// *this *= other
void Mul(const StdMeshMatrix& other);
void Mul(float f);
// *this += other
void Add(const StdMeshMatrix& other);
// *this = other * *this
void Transform(const StdMeshMatrix& other);
private:
// 3x3 orthogonal + translation in last column
float a[3][4];
};
class StdMeshBone
{
friend class StdMesh;
public:
StdMeshBone() {}
unsigned int Index; // Index in master bone table
int ID; // Bone ID
StdStrBuf Name; // Bone name
// Bone transformation
StdMeshMatrix Trans;
// Inverse transformation
StdMeshMatrix InverseTrans;
const StdMeshBone* GetParent() const { return Parent; }
const StdMeshBone& GetChild(unsigned int i) const { return *Children[i]; }
unsigned int GetNumChildren() const { return Children.size(); }
private:
StdMeshBone* Parent; // Parent bone
std::vector<StdMeshBone*> Children; // Children. Not owned.
StdMeshBone(const StdMeshBone&); // non-copyable
StdMeshBone& operator=(const StdMeshBone&); // non-assignable
};
class StdMeshVertexBoneAssignment
{
public:
unsigned int BoneIndex;
float Weight;
};
class StdMeshVertex
{
public:
float x, y, z;
float nx, ny, nz;
float u, v;
// *this = trans * *this
void Transform(const StdMeshMatrix& trans);
// *this *= f;
void Mul(float f);
// *this += other;
void Add(const StdMeshVertex& other);
};
class StdMeshFace
{
public:
unsigned int Vertices[3];
};
// Keyframe, specifies transformation for one bone in a particular frame
class StdMeshKeyFrame
{
public:
StdMeshMatrix Trans;
};
// Animation track, specifies transformation for one bone for each keyframe
class StdMeshTrack
{
friend class StdMesh;
public:
StdMeshMatrix GetTransformAt(float time) const;
private:
std::map<float, StdMeshKeyFrame> Frames;
};
// Animation, consists of one Track for each animated Bone
class StdMeshAnimation
{
friend class StdMesh;
friend class StdMeshInstance;
public:
StdMeshAnimation() {}
StdMeshAnimation(const StdMeshAnimation& other);
~StdMeshAnimation();
StdMeshAnimation& operator=(const StdMeshAnimation& other);
StdStrBuf Name;
float Length;
private:
std::vector<StdMeshTrack*> Tracks; // bone-indexed
};
struct StdMeshBox
{
float x1, y1, z1;
float x2, y2, z2;
};
class StdMesh
{
friend class StdMeshInstance;
public:
StdMesh();
~StdMesh();
// filename is only used to show it in error messages. The model is
// loaded from xml_data.
// Throws StdMeshError.
void InitXML(const char* filename, const char* xml_data, StdMeshSkeletonLoader& skel_loader, const StdMeshMatManager& manager);
const StdMeshVertex& GetVertex(unsigned int i) const { return Vertices[i]; }
unsigned int GetNumVertices() const { return Vertices.size(); }
const StdMeshFace& GetFace(unsigned int i) const { return Faces[i]; }
unsigned int GetNumFaces() const { return Faces.size(); }
const StdMeshBone& GetBone(unsigned int i) const { return *Bones[i]; }
unsigned int GetNumBones() const { return Bones.size(); }
const StdMeshAnimation* GetAnimationByName(const StdStrBuf& name) const;
const StdMeshMaterial& GetMaterial() const { return *Material; }
const StdMeshBox& GetBoundingBox() const { return BoundingBox; }
private:
void AddMasterBone(StdMeshBone* bone);
StdMesh(const StdMesh& other); // non-copyable
StdMesh& operator=(const StdMesh& other); // non-assignable
// Remember bone assignments for vertices
class Vertex: public StdMeshVertex
{
public:
std::vector<StdMeshVertexBoneAssignment> BoneAssignments;
};
std::vector<Vertex> Vertices;
std::vector<StdMeshFace> Faces;
std::vector<StdMeshBone*> Bones; // Master Bone Table
std::map<StdStrBuf, StdMeshAnimation> Animations;
StdMeshBox BoundingBox;
const StdMeshMaterial* Material;
};
class StdMeshInstance
{
public:
StdMeshInstance(const StdMesh& mesh);
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<StdMeshMatrix> BoneTransforms;
std::vector<StdMeshVertex> Vertices;
};
#endif
// vim: et ts=2 sw=2