311 lines
8.1 KiB
C++
311 lines
8.1 KiB
C++
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
|
// This file is part of the "Irrlicht Engine".
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
#ifndef __C_X_FILE_READER_H_INCLUDED__
|
|
#define __C_X_FILE_READER_H_INCLUDED__
|
|
|
|
#include "IReadFile.h"
|
|
#include "irrString.h"
|
|
#include "matrix4.h"
|
|
#include "SColor.h"
|
|
#include "irrArray.h"
|
|
#include "vector2d.h"
|
|
#include "quaternion.h"
|
|
|
|
//#define _XREADER_DEBUG
|
|
|
|
namespace irr
|
|
{
|
|
namespace scene
|
|
{
|
|
|
|
//! This is a .x file reader. It only reads data from uncompressed .x files.
|
|
class CXFileReader : public virtual IUnknown
|
|
{
|
|
public:
|
|
|
|
struct SXAnimationSet;
|
|
struct SXFrame;
|
|
|
|
CXFileReader(io::IReadFile* file);
|
|
~CXFileReader();
|
|
|
|
//! Returns an error occured during reading the file
|
|
bool errorHappened() const;
|
|
|
|
//! Returns if the loaded mesh is static
|
|
bool isStaticMesh() const;
|
|
|
|
//! returns count of animations
|
|
s32 getAnimationSetCount() const;
|
|
|
|
//! returns a specific animation set
|
|
SXAnimationSet& getAnimationSet(s32 i);
|
|
|
|
//! returns array of root frames
|
|
core::array<SXFrame> & getRootFrames();
|
|
|
|
struct SXMaterial
|
|
{
|
|
video::SColorf FaceColor; // note: RGBA
|
|
f32 Power;
|
|
video::SColorf Specular; // RGB
|
|
video::SColorf Emissive; // RGB
|
|
core::stringc TextureFileName;
|
|
};
|
|
|
|
struct SXMeshMaterialList
|
|
{
|
|
core::array<s32> FaceIndices; // index of material for each face
|
|
core::array<SXMaterial> Materials; // material array
|
|
};
|
|
|
|
struct SXTemplateMaterial
|
|
{
|
|
core::stringc Name; // template name from Xfile
|
|
SXMaterial Material; // material
|
|
};
|
|
|
|
struct SXIndexedColor
|
|
{
|
|
s32 Index;
|
|
video::SColorf Color;
|
|
};
|
|
|
|
struct SXSkinMeshHeader
|
|
{
|
|
s32 MaxSkinWeightsPerVertex; // Maximum number of transforms that affect a vertex in the mesh.
|
|
s32 MaxSkinWeightsPerFace; // Maximum number of unique transforms that affect the three vertices of any face.
|
|
s32 BoneCount; // Number of bones that affect vertices in this mesh.
|
|
};
|
|
|
|
struct SXWeight
|
|
{
|
|
SXWeight() {};
|
|
SXWeight(s32 vtidx): VertexIndex(vtidx) {}
|
|
|
|
s32 VertexIndex;
|
|
f32 Weight;
|
|
|
|
bool operator <(const SXWeight& other) const
|
|
{
|
|
return VertexIndex < other.VertexIndex;
|
|
}
|
|
};
|
|
|
|
struct SXSkinWeight
|
|
{
|
|
core::stringc TransformNodeName; // name of the bone
|
|
core::array< SXWeight > Weights;
|
|
core::matrix4 MatrixOffset; // transforms the mesh vertices to the space of the bone
|
|
// When concatenated to the bone's transform, this provides the
|
|
// world space coordinates of the mesh as affected by the bone
|
|
};
|
|
|
|
struct SXMesh
|
|
{
|
|
// this mesh contains triangulated texture data.
|
|
// because in an .x file, faces can be made of more than 3
|
|
// vertices, the indices data structure is triangulated during the
|
|
// loading process. The IndexCountPerFace array is filled during
|
|
// this triangulation process and stores how much indices belong to
|
|
// every face. This data structure can be ignored, because all data
|
|
// in this structure is triangulated.
|
|
|
|
core::stringc Name;
|
|
core::array<core::vector3df> Vertices;
|
|
core::array< s32 > Indices; // triangle indices
|
|
|
|
// optional:
|
|
|
|
core::array<core::vector2df> TextureCoords;
|
|
core::array<core::vector3df> Normals;
|
|
core::array<s32> NormalIndices; // amount is equal to Indices amount
|
|
|
|
core::array< s32 > IndexCountPerFace; // default 3, but could be more
|
|
core::array< SXIndexedColor > VertexColors;
|
|
core::array< SXSkinWeight > SkinWeights;
|
|
SXMeshMaterialList MaterialList;
|
|
SXSkinMeshHeader SkinMeshHeader;
|
|
};
|
|
|
|
struct SXFrame
|
|
{
|
|
SXFrame() : iLevel(0), pParent(0) { }
|
|
|
|
int iLevel;
|
|
SXFrame * pParent;
|
|
core::stringc Name;
|
|
core::matrix4 LocalMatrix;
|
|
core::matrix4 GlobalMatrix;
|
|
|
|
core::array<SXMesh> Meshes;
|
|
core::array<SXFrame> ChildFrames;
|
|
};
|
|
|
|
struct SXAnimationKey
|
|
{
|
|
SXAnimationKey() : keyType(-1), numberOfKeys(0), time(0), data(0) { }
|
|
|
|
void del()
|
|
{
|
|
delete [] time;
|
|
|
|
switch(keyType)
|
|
{
|
|
case -1: break;
|
|
case 0 : delete [] (core::quaternion*)data; break;
|
|
case 1 :
|
|
case 2 : delete [] (core::vector3df*)data; break;
|
|
case 3 :
|
|
case 4 : delete [] (core::matrix4*)data; break;
|
|
}
|
|
}
|
|
|
|
void init()
|
|
{
|
|
time = new s32[numberOfKeys];
|
|
|
|
switch(keyType)
|
|
{
|
|
case 0 : data = new core::quaternion[numberOfKeys]; break;
|
|
case 1 :
|
|
case 2 : data = new core::vector3df[numberOfKeys]; break;
|
|
case 3 :
|
|
case 4 : data = new core::matrix4[numberOfKeys]; break;
|
|
}
|
|
|
|
}
|
|
|
|
core::matrix4& getMatrix(s32 nr) const
|
|
{
|
|
return ((core::matrix4*)data)[nr];
|
|
}
|
|
|
|
core::vector3df& getVector(s32 nr) const
|
|
{
|
|
return ((core::vector3df*)data)[nr];
|
|
}
|
|
|
|
core::quaternion& getQuaternion(s32 nr) const
|
|
{
|
|
return ((core::quaternion*)data)[nr];
|
|
}
|
|
|
|
s32 keyType; // 0=rotation, 1=scale, 2=position, 3=matrix
|
|
s32 numberOfKeys;
|
|
|
|
s32* time;
|
|
void* data;
|
|
};
|
|
|
|
struct SXAnimation
|
|
{
|
|
core::stringc FrameName;
|
|
core::array<SXAnimationKey> Keys;
|
|
|
|
// optional, from AnimationOptions:
|
|
bool closed; // default true
|
|
bool linearPositionQuality; // if false: spline position quality
|
|
};
|
|
|
|
struct SXAnimationSet
|
|
{
|
|
core::stringc AnimationName;
|
|
core::array<SXAnimation> Animations;
|
|
};
|
|
|
|
private:
|
|
|
|
//! Parses the file
|
|
bool parseFile();
|
|
|
|
//! Reads file into memory
|
|
bool readFileIntoMemory(io::IReadFile* file);
|
|
|
|
//! Parses the next Data object in the file
|
|
bool parseDataObject();
|
|
|
|
//! places pointer to next begin of a token, and ignores comments
|
|
void findNextNoneWhiteSpace();
|
|
|
|
//! places pointer to next begin of a token, which must be a number,
|
|
// and ignores comments
|
|
void findNextNoneWhiteSpaceNumber();
|
|
|
|
//! returns next parseable token. Returns empty string if no token there
|
|
core::stringc getNextToken();
|
|
|
|
//! reads header of dataobject including the opening brace.
|
|
//! returns false if error happened, and writes name of object
|
|
//! if there is one
|
|
bool readHeadOfDataObject(core::stringc* outname=0);
|
|
|
|
//! checks for two following semicolons, returns false if they are not there
|
|
bool checkForTwoFollowingSemicolons();
|
|
|
|
//! reads a x file style string
|
|
bool getNextTokenAsString(core::stringc& out);
|
|
|
|
inline u16 readBinWord();
|
|
inline u32 readBinDWord();
|
|
inline s32 readInt();
|
|
inline f32 readFloat();
|
|
inline bool readVector2(core::vector2df& vec);
|
|
inline bool readVector3(core::vector3df& vec);
|
|
inline bool readRGB(video::SColorf& color);
|
|
inline bool readRGBA(video::SColorf& color);
|
|
|
|
bool parseDataObjectTemplate();
|
|
bool parseDataObjectFrame(SXFrame &frame);
|
|
bool parseDataObjectTransformationMatrix(core::matrix4 &mat);
|
|
bool parseDataObjectMesh(SXMesh &mesh);
|
|
bool parseDataObjectMeshNormals(core::array<core::vector3df>& normals,
|
|
core::array< s32 >& normalIndices, s32 triangulatedIndexCount,
|
|
core::array< s32 >& indexCountPerFace);
|
|
bool parseDataObjectMeshTextureCoords(core::array<core::vector2df>& textureCoords);
|
|
bool parseDataObjectMeshVertexColors(core::array<SXIndexedColor>& vertexColors);
|
|
bool parseDataObjectMeshMaterialList(SXMeshMaterialList& materiallist,
|
|
s32 triangulatedIndexCount, core::array< s32 >& indexCountPerFace);
|
|
bool parseDataObjectMaterial(SXMaterial& material);
|
|
bool parseDataObjectTextureFilename(core::stringc& texturename);
|
|
bool parseDataObjectSkinMeshHeader(SXSkinMeshHeader& header);
|
|
bool parseDataObjectSkinWeights(SXSkinWeight& weights);
|
|
bool parseDataObjectAnimationSet(SXAnimationSet& set);
|
|
bool parseDataObjectAnimation(SXAnimation& anim);
|
|
bool parseDataObjectAnimationKey(SXAnimationKey& animkey);
|
|
bool parseUnknownDataObject();
|
|
|
|
void readUntilEndOfLine();
|
|
|
|
void computeGlobalFrameMatrices(SXFrame& frame, const SXFrame* const parent);
|
|
void optimizeFrames( SXFrame * pgFrame, SXFrame * pgParent );
|
|
bool validateMesh(SXFrame* frame);
|
|
|
|
s32 MajorVersion;
|
|
s32 MinorVersion;
|
|
bool binary;
|
|
s32 binaryNumCount;
|
|
|
|
c8* Buffer;
|
|
s32 Size;
|
|
c8 FloatSize;
|
|
const c8* P;
|
|
c8* End;
|
|
|
|
bool ErrorHappened;
|
|
|
|
bool m_bFrameRemoved;
|
|
SXFrame * m_pgCurFrame;
|
|
core::array<SXFrame>RootFrames;
|
|
core::array<SXAnimationSet> AnimationSets;
|
|
core::array<SXTemplateMaterial> TemplateMaterials;
|
|
};
|
|
|
|
} // end namespace scene
|
|
} // end namespace irr
|
|
|
|
#endif
|
|
|