forked from Mirrors/openclonk
Changed indentation of StdMesh*.{h,cpp} from spaces to tabs
parent
4c186f821c
commit
12ddf2b889
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2009 Armin Burgmeier
|
||||
* 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
|
||||
|
@ -26,13 +26,13 @@
|
|||
class StdMeshError: public std::exception
|
||||
{
|
||||
public:
|
||||
StdMeshError(const StdStrBuf& message, const char* file, unsigned int line);
|
||||
virtual ~StdMeshError() throw() {}
|
||||
StdMeshError(const StdStrBuf& message, const char* file, unsigned int line);
|
||||
virtual ~StdMeshError() throw() {}
|
||||
|
||||
virtual const char* what() const throw() { return Buf.getData(); }
|
||||
virtual const char* what() const throw() { return Buf.getData(); }
|
||||
|
||||
protected:
|
||||
StdStrBuf Buf;
|
||||
StdStrBuf Buf;
|
||||
};
|
||||
|
||||
// Interface to load skeleton files. Given a filename occuring in the
|
||||
|
@ -42,228 +42,228 @@ protected:
|
|||
class StdMeshSkeletonLoader
|
||||
{
|
||||
public:
|
||||
virtual StdStrBuf LoadSkeleton(const char* filename) = 0;
|
||||
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);
|
||||
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]; }
|
||||
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
|
||||
void Mul(const StdMeshMatrix& other);
|
||||
void Mul(float f);
|
||||
// *this += other
|
||||
void Add(const StdMeshMatrix& other);
|
||||
|
||||
// *this = other * *this
|
||||
void Transform(const StdMeshMatrix& other);
|
||||
// *this = other * *this
|
||||
void Transform(const StdMeshMatrix& other);
|
||||
private:
|
||||
// 3x3 orthogonal + translation in last column
|
||||
float a[3][4];
|
||||
// 3x3 orthogonal + translation in last column
|
||||
float a[3][4];
|
||||
};
|
||||
|
||||
class StdMeshBone
|
||||
{
|
||||
friend class StdMesh;
|
||||
friend class StdMesh;
|
||||
public:
|
||||
StdMeshBone() {}
|
||||
StdMeshBone() {}
|
||||
|
||||
unsigned int Index; // Index in master bone table
|
||||
int ID; // Bone ID
|
||||
StdStrBuf Name; // Bone name
|
||||
unsigned int Index; // Index in master bone table
|
||||
int ID; // Bone ID
|
||||
StdStrBuf Name; // Bone name
|
||||
|
||||
// Bone transformation
|
||||
StdMeshMatrix Trans;
|
||||
// Inverse transformation
|
||||
StdMeshMatrix InverseTrans;
|
||||
// Bone transformation
|
||||
StdMeshMatrix Trans;
|
||||
// Inverse transformation
|
||||
StdMeshMatrix InverseTrans;
|
||||
|
||||
const StdMeshBone* GetParent() const { return Parent; }
|
||||
const StdMeshBone* GetParent() const { return Parent; }
|
||||
|
||||
const StdMeshBone& GetChild(unsigned int i) const { return *Children[i]; }
|
||||
unsigned int GetNumChildren() const { return Children.size(); }
|
||||
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* Parent; // Parent bone
|
||||
std::vector<StdMeshBone*> Children; // Children. Not owned.
|
||||
|
||||
StdMeshBone(const StdMeshBone&); // non-copyable
|
||||
StdMeshBone& operator=(const StdMeshBone&); // non-assignable
|
||||
StdMeshBone(const StdMeshBone&); // non-copyable
|
||||
StdMeshBone& operator=(const StdMeshBone&); // non-assignable
|
||||
};
|
||||
|
||||
class StdMeshVertexBoneAssignment
|
||||
{
|
||||
public:
|
||||
unsigned int BoneIndex;
|
||||
float Weight;
|
||||
unsigned int BoneIndex;
|
||||
float Weight;
|
||||
};
|
||||
|
||||
class StdMeshVertex
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
float nx, ny, nz;
|
||||
float u, v;
|
||||
float x, y, z;
|
||||
float nx, ny, nz;
|
||||
float u, v;
|
||||
|
||||
// *this = trans * *this
|
||||
void Transform(const StdMeshMatrix& trans);
|
||||
// *this = trans * *this
|
||||
void Transform(const StdMeshMatrix& trans);
|
||||
|
||||
// *this *= f;
|
||||
void Mul(float f);
|
||||
// *this += other;
|
||||
void Add(const StdMeshVertex& other);
|
||||
// *this *= f;
|
||||
void Mul(float f);
|
||||
// *this += other;
|
||||
void Add(const StdMeshVertex& other);
|
||||
};
|
||||
|
||||
class StdMeshFace
|
||||
{
|
||||
public:
|
||||
unsigned int Vertices[3];
|
||||
unsigned int Vertices[3];
|
||||
};
|
||||
|
||||
// Keyframe, specifies transformation for one bone in a particular frame
|
||||
class StdMeshKeyFrame
|
||||
{
|
||||
public:
|
||||
StdMeshMatrix Trans;
|
||||
StdMeshMatrix Trans;
|
||||
};
|
||||
|
||||
// Animation track, specifies transformation for one bone for each keyframe
|
||||
class StdMeshTrack
|
||||
{
|
||||
friend class StdMesh;
|
||||
friend class StdMesh;
|
||||
public:
|
||||
StdMeshMatrix GetTransformAt(float time) const;
|
||||
StdMeshMatrix GetTransformAt(float time) const;
|
||||
|
||||
private:
|
||||
std::map<float, StdMeshKeyFrame> Frames;
|
||||
std::map<float, StdMeshKeyFrame> Frames;
|
||||
};
|
||||
|
||||
// Animation, consists of one Track for each animated Bone
|
||||
class StdMeshAnimation
|
||||
{
|
||||
friend class StdMesh;
|
||||
friend class StdMeshInstance;
|
||||
friend class StdMesh;
|
||||
friend class StdMeshInstance;
|
||||
public:
|
||||
StdMeshAnimation() {}
|
||||
StdMeshAnimation(const StdMeshAnimation& other);
|
||||
~StdMeshAnimation();
|
||||
StdMeshAnimation() {}
|
||||
StdMeshAnimation(const StdMeshAnimation& other);
|
||||
~StdMeshAnimation();
|
||||
|
||||
StdMeshAnimation& operator=(const StdMeshAnimation& other);
|
||||
StdMeshAnimation& operator=(const StdMeshAnimation& other);
|
||||
|
||||
StdCopyStrBuf Name;
|
||||
float Length;
|
||||
StdCopyStrBuf Name;
|
||||
float Length;
|
||||
|
||||
private:
|
||||
std::vector<StdMeshTrack*> Tracks; // bone-indexed
|
||||
std::vector<StdMeshTrack*> Tracks; // bone-indexed
|
||||
};
|
||||
|
||||
struct StdMeshBox
|
||||
{
|
||||
float x1, y1, z1;
|
||||
float x2, y2, z2;
|
||||
float x1, y1, z1;
|
||||
float x2, y2, z2;
|
||||
};
|
||||
|
||||
class StdMesh
|
||||
{
|
||||
friend class StdMeshInstance;
|
||||
friend class StdMeshInstance;
|
||||
public:
|
||||
StdMesh();
|
||||
~StdMesh();
|
||||
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);
|
||||
// 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 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 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 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 StdMeshAnimation* GetAnimationByName(const StdStrBuf& name) const;
|
||||
const StdMeshMaterial& GetMaterial() const { return *Material; }
|
||||
|
||||
const StdMeshBox& GetBoundingBox() const { return BoundingBox; }
|
||||
const StdMeshBox& GetBoundingBox() const { return BoundingBox; }
|
||||
|
||||
private:
|
||||
void AddMasterBone(StdMeshBone* bone);
|
||||
void AddMasterBone(StdMeshBone* bone);
|
||||
|
||||
StdMesh(const StdMesh& other); // non-copyable
|
||||
StdMesh& operator=(const StdMesh& other); // non-assignable
|
||||
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;
|
||||
};
|
||||
// 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::vector<Vertex> Vertices;
|
||||
std::vector<StdMeshFace> Faces;
|
||||
std::vector<StdMeshBone*> Bones; // Master Bone Table
|
||||
|
||||
std::map<StdCopyStrBuf, StdMeshAnimation> Animations;
|
||||
std::map<StdCopyStrBuf, StdMeshAnimation> Animations;
|
||||
|
||||
StdMeshBox BoundingBox;
|
||||
const StdMeshMaterial* Material;
|
||||
StdMeshBox BoundingBox;
|
||||
const StdMeshMaterial* Material;
|
||||
};
|
||||
|
||||
class StdMeshInstance
|
||||
{
|
||||
public:
|
||||
StdMeshInstance(const StdMesh& mesh);
|
||||
StdMeshInstance(const StdMesh& mesh);
|
||||
|
||||
enum FaceOrdering {
|
||||
FO_Fixed, // don't reorder, keep faces as in mesh
|
||||
FO_FarthestToNearest,
|
||||
FO_NearestToFarthest
|
||||
};
|
||||
enum FaceOrdering {
|
||||
FO_Fixed, // don't reorder, keep faces as in mesh
|
||||
FO_FarthestToNearest,
|
||||
FO_NearestToFarthest
|
||||
};
|
||||
|
||||
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
||||
void SetFaceOrdering(FaceOrdering ordering);
|
||||
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
||||
void SetFaceOrdering(FaceOrdering ordering);
|
||||
|
||||
bool SetAnimationByName(const StdStrBuf& animation_name);
|
||||
void SetAnimation(const StdMeshAnimation& animation);
|
||||
void UnsetAnimation();
|
||||
bool SetAnimationByName(const StdStrBuf& animation_name);
|
||||
void SetAnimation(const StdMeshAnimation& animation);
|
||||
void UnsetAnimation();
|
||||
|
||||
const StdMeshAnimation* GetAnimation() const { return Animation; }
|
||||
const StdMeshAnimation* GetAnimation() const { return Animation; }
|
||||
|
||||
void SetPosition(float position);
|
||||
float GetPosition() const { return Position; }
|
||||
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(); }
|
||||
// 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(); }
|
||||
|
||||
// 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 also SetFaceOrdering.
|
||||
const StdMeshFace& GetFace(unsigned int i) const { return *Faces[i]; }
|
||||
unsigned int GetNumFaces() const { return Faces.size(); }
|
||||
// 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 also SetFaceOrdering.
|
||||
const StdMeshFace& GetFace(unsigned int i) const { return *Faces[i]; }
|
||||
unsigned int GetNumFaces() const { return Faces.size(); }
|
||||
|
||||
const StdMesh& Mesh;
|
||||
const StdMesh& Mesh;
|
||||
|
||||
protected:
|
||||
void ReorderFaces();
|
||||
void ReorderFaces();
|
||||
|
||||
FaceOrdering CurrentFaceOrdering;
|
||||
const StdMeshAnimation* Animation;
|
||||
float Position;
|
||||
FaceOrdering CurrentFaceOrdering;
|
||||
const StdMeshAnimation* Animation;
|
||||
float Position;
|
||||
|
||||
std::vector<StdMeshMatrix> BoneTransforms;
|
||||
std::vector<StdMeshVertex> Vertices;
|
||||
std::vector<const StdMeshFace*> Faces;
|
||||
std::vector<StdMeshMatrix> BoneTransforms;
|
||||
std::vector<StdMeshVertex> Vertices;
|
||||
std::vector<const StdMeshFace*> Faces;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,13 +35,13 @@ class StdMeshMaterialParserCtx;
|
|||
class StdMeshMaterialError: public std::exception
|
||||
{
|
||||
public:
|
||||
StdMeshMaterialError(const StdStrBuf& message, const char* file, unsigned int line);
|
||||
virtual ~StdMeshMaterialError() throw() {}
|
||||
StdMeshMaterialError(const StdStrBuf& message, const char* file, unsigned int line);
|
||||
virtual ~StdMeshMaterialError() throw() {}
|
||||
|
||||
virtual const char* what() const throw() { return Buf.getData(); }
|
||||
virtual const char* what() const throw() { return Buf.getData(); }
|
||||
|
||||
protected:
|
||||
StdCopyStrBuf Buf;
|
||||
StdCopyStrBuf Buf;
|
||||
};
|
||||
|
||||
// Interface to load textures. Given a texture filename occuring in the
|
||||
|
@ -50,100 +50,100 @@ protected:
|
|||
class StdMeshMaterialTextureLoader
|
||||
{
|
||||
public:
|
||||
virtual bool LoadTexture(const char* filename, CPNGFile& dest) = 0;
|
||||
virtual bool LoadTexture(const char* filename, CPNGFile& dest) = 0;
|
||||
};
|
||||
|
||||
class StdMeshMaterialTextureUnit
|
||||
{
|
||||
public:
|
||||
// Ref-counted texture. When a meterial inherits from one which contains
|
||||
// a TextureUnit, then they will share the same CTexRef.
|
||||
class TexRef
|
||||
{
|
||||
public:
|
||||
TexRef(unsigned int size);
|
||||
~TexRef();
|
||||
// Ref-counted texture. When a meterial inherits from one which contains
|
||||
// a TextureUnit, then they will share the same CTexRef.
|
||||
class TexRef
|
||||
{
|
||||
public:
|
||||
TexRef(unsigned int size);
|
||||
~TexRef();
|
||||
|
||||
unsigned int RefCount;
|
||||
CTexRef Tex;
|
||||
};
|
||||
unsigned int RefCount;
|
||||
CTexRef Tex;
|
||||
};
|
||||
|
||||
StdMeshMaterialTextureUnit();
|
||||
StdMeshMaterialTextureUnit(const StdMeshMaterialTextureUnit& other);
|
||||
~StdMeshMaterialTextureUnit();
|
||||
StdMeshMaterialTextureUnit();
|
||||
StdMeshMaterialTextureUnit(const StdMeshMaterialTextureUnit& other);
|
||||
~StdMeshMaterialTextureUnit();
|
||||
|
||||
StdMeshMaterialTextureUnit& operator=(const StdMeshMaterialTextureUnit&);
|
||||
StdMeshMaterialTextureUnit& operator=(const StdMeshMaterialTextureUnit&);
|
||||
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
const CTexRef& GetTexture() const { return Texture->Tex; }
|
||||
const CTexRef& GetTexture() const { return Texture->Tex; }
|
||||
|
||||
private:
|
||||
TexRef* Texture;
|
||||
TexRef* Texture;
|
||||
};
|
||||
|
||||
class StdMeshMaterialPass
|
||||
{
|
||||
public:
|
||||
StdMeshMaterialPass();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
StdMeshMaterialPass();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
std::vector<StdMeshMaterialTextureUnit> TextureUnits;
|
||||
std::vector<StdMeshMaterialTextureUnit> TextureUnits;
|
||||
|
||||
float Ambient[4];
|
||||
float Diffuse[4];
|
||||
float Specular[4];
|
||||
float Emissive[4];
|
||||
float Shininess;
|
||||
float Ambient[4];
|
||||
float Diffuse[4];
|
||||
float Specular[4];
|
||||
float Emissive[4];
|
||||
float Shininess;
|
||||
};
|
||||
|
||||
class StdMeshMaterialTechnique
|
||||
{
|
||||
public:
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
std::vector<StdMeshMaterialPass> Passes;
|
||||
std::vector<StdMeshMaterialPass> Passes;
|
||||
};
|
||||
|
||||
class StdMeshMaterial
|
||||
{
|
||||
public:
|
||||
StdMeshMaterial();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
StdMeshMaterial();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
// Location the Material was loaded from
|
||||
StdCopyStrBuf FileName;
|
||||
unsigned int Line;
|
||||
// Location the Material was loaded from
|
||||
StdCopyStrBuf FileName;
|
||||
unsigned int Line;
|
||||
|
||||
// Material name
|
||||
StdCopyStrBuf Name;
|
||||
// Material name
|
||||
StdCopyStrBuf Name;
|
||||
|
||||
// Not currently used in Clonk, but don't fail when we see this in a
|
||||
// Material script:
|
||||
bool ReceiveShadows;
|
||||
// Not currently used in Clonk, but don't fail when we see this in a
|
||||
// Material script:
|
||||
bool ReceiveShadows;
|
||||
|
||||
// Available techniques
|
||||
std::vector<StdMeshMaterialTechnique> Techniques;
|
||||
// Available techniques
|
||||
std::vector<StdMeshMaterialTechnique> Techniques;
|
||||
};
|
||||
|
||||
class StdMeshMatManager
|
||||
{
|
||||
public:
|
||||
// Remove all materials from manager. Make sure there is no StdMesh
|
||||
// referencing any out there before calling this.
|
||||
void Clear();
|
||||
// Remove all materials from manager. Make sure there is no StdMesh
|
||||
// referencing any out there before calling this.
|
||||
void Clear();
|
||||
|
||||
// Parse a material script file, and add the materials to the manager.
|
||||
// filename may be NULL if the source is not a file. It will only be used
|
||||
// for error messages.
|
||||
// Throws StdMeshMaterialError.
|
||||
void Parse(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader);
|
||||
// Parse a material script file, and add the materials to the manager.
|
||||
// filename may be NULL if the source is not a file. It will only be used
|
||||
// for error messages.
|
||||
// Throws StdMeshMaterialError.
|
||||
void Parse(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader);
|
||||
|
||||
// Get material by name. NULL if there is no such material with this name.
|
||||
const StdMeshMaterial* GetMaterial(const char* material_name) const;
|
||||
// Get material by name. NULL if there is no such material with this name.
|
||||
const StdMeshMaterial* GetMaterial(const char* material_name) const;
|
||||
|
||||
private:
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial> Materials;
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial> Materials;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,119 +22,119 @@
|
|||
|
||||
StdMeshMaterialError::StdMeshMaterialError(const StdStrBuf& message, const char* file, unsigned int line)
|
||||
{
|
||||
Buf.Format("%s:%u: %s", file, line, message.getData());
|
||||
Buf.Format("%s:%u: %s", file, line, message.getData());
|
||||
}
|
||||
|
||||
enum Token
|
||||
{
|
||||
TOKEN_IDTF,
|
||||
TOKEN_BRACE_OPEN,
|
||||
TOKEN_BRACE_CLOSE,
|
||||
TOKEN_COLON,
|
||||
TOKEN_EOF
|
||||
TOKEN_IDTF,
|
||||
TOKEN_BRACE_OPEN,
|
||||
TOKEN_BRACE_CLOSE,
|
||||
TOKEN_COLON,
|
||||
TOKEN_EOF
|
||||
};
|
||||
|
||||
class StdMeshMaterialParserCtx
|
||||
{
|
||||
public:
|
||||
StdMeshMaterialParserCtx(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader);
|
||||
StdMeshMaterialParserCtx(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader);
|
||||
|
||||
void SkipWhitespace();
|
||||
Token Peek(StdStrBuf& name);
|
||||
Token Advance(StdStrBuf& name);
|
||||
Token AdvanceNonEOF(StdStrBuf& name);
|
||||
Token AdvanceRequired(StdStrBuf& name, Token expect);
|
||||
Token AdvanceRequired(StdStrBuf& name, Token expect1, Token expect2);
|
||||
float AdvanceFloat();
|
||||
bool AdvanceFloatOptional(float& value);
|
||||
bool AdvanceBoolean();
|
||||
void Error(const StdStrBuf& message);
|
||||
void ErrorUnexpectedIdentifier(const StdStrBuf& identifier);
|
||||
void SkipWhitespace();
|
||||
Token Peek(StdStrBuf& name);
|
||||
Token Advance(StdStrBuf& name);
|
||||
Token AdvanceNonEOF(StdStrBuf& name);
|
||||
Token AdvanceRequired(StdStrBuf& name, Token expect);
|
||||
Token AdvanceRequired(StdStrBuf& name, Token expect1, Token expect2);
|
||||
float AdvanceFloat();
|
||||
bool AdvanceFloatOptional(float& value);
|
||||
bool AdvanceBoolean();
|
||||
void Error(const StdStrBuf& message);
|
||||
void ErrorUnexpectedIdentifier(const StdStrBuf& identifier);
|
||||
|
||||
// Current parsing data
|
||||
unsigned int Line;
|
||||
const char* Script;
|
||||
// Current parsing data
|
||||
unsigned int Line;
|
||||
const char* Script;
|
||||
|
||||
StdCopyStrBuf FileName;
|
||||
StdMeshMaterialTextureLoader& TextureLoader;
|
||||
StdCopyStrBuf FileName;
|
||||
StdMeshMaterialTextureLoader& TextureLoader;
|
||||
};
|
||||
|
||||
StdMeshMaterialParserCtx::StdMeshMaterialParserCtx(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader):
|
||||
Line(0), Script(mat_script), FileName(filename), TextureLoader(tex_loader)
|
||||
Line(0), Script(mat_script), FileName(filename), TextureLoader(tex_loader)
|
||||
{
|
||||
}
|
||||
|
||||
void StdMeshMaterialParserCtx::SkipWhitespace()
|
||||
{
|
||||
while(isspace(*Script))
|
||||
{
|
||||
if(*Script == '\n') ++Line;
|
||||
++Script;
|
||||
}
|
||||
while(isspace(*Script))
|
||||
{
|
||||
if(*Script == '\n') ++Line;
|
||||
++Script;
|
||||
}
|
||||
}
|
||||
|
||||
Token StdMeshMaterialParserCtx::Peek(StdStrBuf& name)
|
||||
{
|
||||
SkipWhitespace();
|
||||
SkipWhitespace();
|
||||
|
||||
const char* before = Script;
|
||||
Token tok = Advance(name);
|
||||
Script = before;
|
||||
return tok;
|
||||
const char* before = Script;
|
||||
Token tok = Advance(name);
|
||||
Script = before;
|
||||
return tok;
|
||||
}
|
||||
|
||||
Token StdMeshMaterialParserCtx::Advance(StdStrBuf& name)
|
||||
{
|
||||
SkipWhitespace();
|
||||
SkipWhitespace();
|
||||
|
||||
switch(*Script)
|
||||
{
|
||||
case '\0':
|
||||
name.Clear();
|
||||
return TOKEN_EOF;
|
||||
case '{':
|
||||
++Script;
|
||||
name = "{";
|
||||
return TOKEN_BRACE_OPEN;
|
||||
case '}':
|
||||
++Script;
|
||||
name = "}";
|
||||
return TOKEN_BRACE_CLOSE;
|
||||
case ':':
|
||||
++Script;
|
||||
name = ":";
|
||||
return TOKEN_COLON;
|
||||
default:
|
||||
const char* begin = Script;
|
||||
// Advance to next whitespace
|
||||
do { ++Script; } while(!isspace(*Script) && *Script != '{' && *Script != '}' && *Script != ':');
|
||||
name.Copy(begin, Script - begin);
|
||||
return TOKEN_IDTF;
|
||||
}
|
||||
switch(*Script)
|
||||
{
|
||||
case '\0':
|
||||
name.Clear();
|
||||
return TOKEN_EOF;
|
||||
case '{':
|
||||
++Script;
|
||||
name = "{";
|
||||
return TOKEN_BRACE_OPEN;
|
||||
case '}':
|
||||
++Script;
|
||||
name = "}";
|
||||
return TOKEN_BRACE_CLOSE;
|
||||
case ':':
|
||||
++Script;
|
||||
name = ":";
|
||||
return TOKEN_COLON;
|
||||
default:
|
||||
const char* begin = Script;
|
||||
// Advance to next whitespace
|
||||
do { ++Script; } while(!isspace(*Script) && *Script != '{' && *Script != '}' && *Script != ':');
|
||||
name.Copy(begin, Script - begin);
|
||||
return TOKEN_IDTF;
|
||||
}
|
||||
}
|
||||
|
||||
Token StdMeshMaterialParserCtx::AdvanceNonEOF(StdStrBuf& name)
|
||||
{
|
||||
Token token = Advance(name);
|
||||
if(token == TOKEN_EOF) Error(StdCopyStrBuf("Unexpected end of file"));
|
||||
return token;
|
||||
Token token = Advance(name);
|
||||
if(token == TOKEN_EOF) Error(StdCopyStrBuf("Unexpected end of file"));
|
||||
return token;
|
||||
}
|
||||
|
||||
Token StdMeshMaterialParserCtx::AdvanceRequired(StdStrBuf& name, Token expect)
|
||||
{
|
||||
Token token = AdvanceNonEOF(name);
|
||||
// TODO: Explain what was actually expected
|
||||
if(token != expect) Error(StdCopyStrBuf("'") + name + "' unexpected");
|
||||
return token;
|
||||
Token token = AdvanceNonEOF(name);
|
||||
// TODO: Explain what was actually expected
|
||||
if(token != expect) Error(StdCopyStrBuf("'") + name + "' unexpected");
|
||||
return token;
|
||||
}
|
||||
|
||||
Token StdMeshMaterialParserCtx::AdvanceRequired(StdStrBuf& name, Token expect1, Token expect2)
|
||||
{
|
||||
Token token = AdvanceNonEOF(name);
|
||||
// TODO: Explain what was actually expected
|
||||
if(token != expect1 && token != expect2)
|
||||
Error(StdStrBuf("'") + name + "' unexpected");
|
||||
return token;
|
||||
Token token = AdvanceNonEOF(name);
|
||||
// TODO: Explain what was actually expected
|
||||
if(token != expect1 && token != expect2)
|
||||
Error(StdStrBuf("'") + name + "' unexpected");
|
||||
return token;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -146,310 +146,310 @@ static inline float strtof(const char *_Str, char **_EndPtr)
|
|||
|
||||
float StdMeshMaterialParserCtx::AdvanceFloat()
|
||||
{
|
||||
StdStrBuf buf;
|
||||
AdvanceRequired(buf, TOKEN_IDTF);
|
||||
char* end;
|
||||
float f = strtof(buf.getData(), &end);
|
||||
if(*end != '\0') Error(StdStrBuf("Floating point value expected"));
|
||||
return f;
|
||||
StdStrBuf buf;
|
||||
AdvanceRequired(buf, TOKEN_IDTF);
|
||||
char* end;
|
||||
float f = strtof(buf.getData(), &end);
|
||||
if(*end != '\0') Error(StdStrBuf("Floating point value expected"));
|
||||
return f;
|
||||
}
|
||||
|
||||
bool StdMeshMaterialParserCtx::AdvanceFloatOptional(float& value)
|
||||
{
|
||||
StdStrBuf buf;
|
||||
Token tok = Peek(buf);
|
||||
StdStrBuf buf;
|
||||
Token tok = Peek(buf);
|
||||
|
||||
if(tok == TOKEN_IDTF && isdigit(buf[0]))
|
||||
{
|
||||
value = AdvanceFloat();
|
||||
return true;
|
||||
}
|
||||
if(tok == TOKEN_IDTF && isdigit(buf[0]))
|
||||
{
|
||||
value = AdvanceFloat();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StdMeshMaterialParserCtx::AdvanceBoolean()
|
||||
{
|
||||
StdCopyStrBuf buf;
|
||||
AdvanceRequired(buf, TOKEN_IDTF);
|
||||
if(buf == "on") return true;
|
||||
if(buf == "off") return false;
|
||||
Error(StdCopyStrBuf("Expected either 'on' or 'off', but not '") + buf + "'");
|
||||
return false; // Never reached
|
||||
StdCopyStrBuf buf;
|
||||
AdvanceRequired(buf, TOKEN_IDTF);
|
||||
if(buf == "on") return true;
|
||||
if(buf == "off") return false;
|
||||
Error(StdCopyStrBuf("Expected either 'on' or 'off', but not '") + buf + "'");
|
||||
return false; // Never reached
|
||||
}
|
||||
|
||||
void StdMeshMaterialParserCtx::Error(const StdStrBuf& message)
|
||||
{
|
||||
throw StdMeshMaterialError(message, FileName.getData(), Line);
|
||||
throw StdMeshMaterialError(message, FileName.getData(), Line);
|
||||
}
|
||||
|
||||
void StdMeshMaterialParserCtx::ErrorUnexpectedIdentifier(const StdStrBuf& identifier)
|
||||
{
|
||||
Error(StdCopyStrBuf("Unexpected identifier: '") + identifier + "'");
|
||||
Error(StdCopyStrBuf("Unexpected identifier: '") + identifier + "'");
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::TexRef::TexRef(unsigned int size):
|
||||
RefCount(1), Tex(size, false)
|
||||
RefCount(1), Tex(size, false)
|
||||
{
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::TexRef::~TexRef()
|
||||
{
|
||||
assert(RefCount == 0);
|
||||
assert(RefCount == 0);
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::StdMeshMaterialTextureUnit():
|
||||
Texture(NULL)
|
||||
Texture(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::StdMeshMaterialTextureUnit(const StdMeshMaterialTextureUnit& other):
|
||||
Texture(other.Texture)
|
||||
Texture(other.Texture)
|
||||
{
|
||||
if(Texture)
|
||||
++Texture->RefCount;
|
||||
if(Texture)
|
||||
++Texture->RefCount;
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::~StdMeshMaterialTextureUnit()
|
||||
{
|
||||
if(Texture && !--Texture->RefCount)
|
||||
delete Texture;
|
||||
if(Texture && !--Texture->RefCount)
|
||||
delete Texture;
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit& StdMeshMaterialTextureUnit::operator=(const StdMeshMaterialTextureUnit& other)
|
||||
{
|
||||
if(this == &other) return *this;
|
||||
if(Texture) if(!--Texture->RefCount) delete Texture;
|
||||
Texture = other.Texture;
|
||||
if(Texture) ++Texture->RefCount;
|
||||
return *this;
|
||||
if(this == &other) return *this;
|
||||
if(Texture) if(!--Texture->RefCount) delete Texture;
|
||||
Texture = other.Texture;
|
||||
if(Texture) ++Texture->RefCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void StdMeshMaterialTextureUnit::Load(StdMeshMaterialParserCtx& ctx)
|
||||
{
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "texture")
|
||||
{
|
||||
ctx.AdvanceRequired(token_name, TOKEN_IDTF);
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "texture")
|
||||
{
|
||||
ctx.AdvanceRequired(token_name, TOKEN_IDTF);
|
||||
|
||||
CPNGFile png;
|
||||
if(!ctx.TextureLoader.LoadTexture(token_name.getData(), png))
|
||||
ctx.Error(StdCopyStrBuf("Could not load texture '") + token_name + "'");
|
||||
CPNGFile png;
|
||||
if(!ctx.TextureLoader.LoadTexture(token_name.getData(), png))
|
||||
ctx.Error(StdCopyStrBuf("Could not load texture '") + token_name + "'");
|
||||
|
||||
if(png.iWdt != png.iHgt)
|
||||
ctx.Error(StdCopyStrBuf("Texture '") + token_name + "' is not quadratic");
|
||||
if(png.iWdt != png.iHgt)
|
||||
ctx.Error(StdCopyStrBuf("Texture '") + token_name + "' is not quadratic");
|
||||
|
||||
Texture = new TexRef(png.iWdt);
|
||||
Texture = new TexRef(png.iWdt);
|
||||
|
||||
Texture->Tex.Lock();
|
||||
for(unsigned int y = 0; y < png.iHgt; ++y)
|
||||
for(unsigned int x = 0; x < png.iWdt; ++x)
|
||||
Texture->Tex.SetPix4(x, y, png.GetPix(x, y));
|
||||
Texture->Tex.Unlock();
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
Texture->Tex.Lock();
|
||||
for(unsigned int y = 0; y < png.iHgt; ++y)
|
||||
for(unsigned int x = 0; x < png.iWdt; ++x)
|
||||
Texture->Tex.SetPix4(x, y, png.GetPix(x, y));
|
||||
Texture->Tex.Unlock();
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
StdMeshMaterialPass::StdMeshMaterialPass()
|
||||
{
|
||||
Ambient[0] = Ambient[1] = Ambient[2] = 1.0f; Ambient[3] = 0.0f;
|
||||
Diffuse[0] = Diffuse[1] = Diffuse[2] = 1.0f; Diffuse[3] = 0.0f;
|
||||
Specular[0] = Specular[1] = Specular[2] = 0.0f; Specular[3] = 1.0f;
|
||||
Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 1.0f;
|
||||
Shininess = 0.0f;
|
||||
Ambient[0] = Ambient[1] = Ambient[2] = 1.0f; Ambient[3] = 0.0f;
|
||||
Diffuse[0] = Diffuse[1] = Diffuse[2] = 1.0f; Diffuse[3] = 0.0f;
|
||||
Specular[0] = Specular[1] = Specular[2] = 0.0f; Specular[3] = 1.0f;
|
||||
Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 1.0f;
|
||||
Shininess = 0.0f;
|
||||
}
|
||||
|
||||
void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
||||
{
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "texture_unit")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
TextureUnits.push_back(StdMeshMaterialTextureUnit());
|
||||
TextureUnits.back().Load(ctx);
|
||||
}
|
||||
else if(token_name == "ambient")
|
||||
{
|
||||
Ambient[0] = ctx.AdvanceFloat();
|
||||
Ambient[1] = ctx.AdvanceFloat();
|
||||
Ambient[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Ambient[3]))
|
||||
Ambient[3] = 1 - Ambient[3];
|
||||
}
|
||||
else if(token_name == "diffuse")
|
||||
{
|
||||
Diffuse[0] = ctx.AdvanceFloat();
|
||||
Diffuse[1] = ctx.AdvanceFloat();
|
||||
Diffuse[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Diffuse[3]))
|
||||
Diffuse[3] = 1 - Diffuse[3];
|
||||
}
|
||||
else if(token_name == "specular")
|
||||
{
|
||||
Specular[0] = ctx.AdvanceFloat();
|
||||
Specular[1] = ctx.AdvanceFloat();
|
||||
Specular[2] = ctx.AdvanceFloat();
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "texture_unit")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
TextureUnits.push_back(StdMeshMaterialTextureUnit());
|
||||
TextureUnits.back().Load(ctx);
|
||||
}
|
||||
else if(token_name == "ambient")
|
||||
{
|
||||
Ambient[0] = ctx.AdvanceFloat();
|
||||
Ambient[1] = ctx.AdvanceFloat();
|
||||
Ambient[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Ambient[3]))
|
||||
Ambient[3] = 1 - Ambient[3];
|
||||
}
|
||||
else if(token_name == "diffuse")
|
||||
{
|
||||
Diffuse[0] = ctx.AdvanceFloat();
|
||||
Diffuse[1] = ctx.AdvanceFloat();
|
||||
Diffuse[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Diffuse[3]))
|
||||
Diffuse[3] = 1 - Diffuse[3];
|
||||
}
|
||||
else if(token_name == "specular")
|
||||
{
|
||||
Specular[0] = ctx.AdvanceFloat();
|
||||
Specular[1] = ctx.AdvanceFloat();
|
||||
Specular[2] = ctx.AdvanceFloat();
|
||||
|
||||
// The fourth argument is optional, not the fifth:
|
||||
float specular3 = ctx.AdvanceFloat();
|
||||
// The fourth argument is optional, not the fifth:
|
||||
float specular3 = ctx.AdvanceFloat();
|
||||
|
||||
float shininess;
|
||||
if(ctx.AdvanceFloatOptional(shininess))
|
||||
{
|
||||
Specular[3] = 1 - specular3;
|
||||
Shininess = shininess;
|
||||
}
|
||||
else
|
||||
{
|
||||
Shininess = specular3;
|
||||
}
|
||||
}
|
||||
else if(token_name == "emissive")
|
||||
{
|
||||
Emissive[0] = ctx.AdvanceFloat();
|
||||
Emissive[1] = ctx.AdvanceFloat();
|
||||
Emissive[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Emissive[3]))
|
||||
Emissive[3] = 1 - Emissive[3];
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
float shininess;
|
||||
if(ctx.AdvanceFloatOptional(shininess))
|
||||
{
|
||||
Specular[3] = 1 - specular3;
|
||||
Shininess = shininess;
|
||||
}
|
||||
else
|
||||
{
|
||||
Shininess = specular3;
|
||||
}
|
||||
}
|
||||
else if(token_name == "emissive")
|
||||
{
|
||||
Emissive[0] = ctx.AdvanceFloat();
|
||||
Emissive[1] = ctx.AdvanceFloat();
|
||||
Emissive[2] = ctx.AdvanceFloat();
|
||||
if(ctx.AdvanceFloatOptional(Emissive[3]))
|
||||
Emissive[3] = 1 - Emissive[3];
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
void StdMeshMaterialTechnique::Load(StdMeshMaterialParserCtx& ctx)
|
||||
{
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "pass")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
Passes.push_back(StdMeshMaterialPass());
|
||||
Passes.back().Load(ctx);
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "pass")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
Passes.push_back(StdMeshMaterialPass());
|
||||
Passes.back().Load(ctx);
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
StdMeshMaterial::StdMeshMaterial():
|
||||
Line(0), ReceiveShadows(true)
|
||||
Line(0), ReceiveShadows(true)
|
||||
{
|
||||
}
|
||||
|
||||
void StdMeshMaterial::Load(StdMeshMaterialParserCtx& ctx)
|
||||
{
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "technique")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
Techniques.push_back(StdMeshMaterialTechnique());
|
||||
Techniques.back().Load(ctx);
|
||||
}
|
||||
else if(token_name == "receive_shadows")
|
||||
{
|
||||
ReceiveShadows = ctx.AdvanceBoolean();
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.AdvanceNonEOF(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "technique")
|
||||
{
|
||||
// TODO: Can there be an optional name?
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
Techniques.push_back(StdMeshMaterialTechnique());
|
||||
Techniques.back().Load(ctx);
|
||||
}
|
||||
else if(token_name == "receive_shadows")
|
||||
{
|
||||
ReceiveShadows = ctx.AdvanceBoolean();
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_BRACE_CLOSE)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
void StdMeshMatManager::Clear()
|
||||
{
|
||||
Materials.clear();
|
||||
Materials.clear();
|
||||
}
|
||||
|
||||
void StdMeshMatManager::Parse(const char* mat_script, const char* filename, StdMeshMaterialTextureLoader& tex_loader)
|
||||
{
|
||||
StdMeshMaterialParserCtx ctx(mat_script, filename, tex_loader);
|
||||
StdMeshMaterialParserCtx ctx(mat_script, filename, tex_loader);
|
||||
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.Advance(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "material")
|
||||
{
|
||||
// Read name
|
||||
StdCopyStrBuf material_name;
|
||||
ctx.AdvanceRequired(material_name, TOKEN_IDTF);
|
||||
Token token;
|
||||
StdCopyStrBuf token_name;
|
||||
while((token = ctx.Advance(token_name)) == TOKEN_IDTF)
|
||||
{
|
||||
if(token_name == "material")
|
||||
{
|
||||
// Read name
|
||||
StdCopyStrBuf material_name;
|
||||
ctx.AdvanceRequired(material_name, TOKEN_IDTF);
|
||||
|
||||
// Check for uniqueness
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial>::iterator iter = Materials.find(material_name);
|
||||
if(iter != Materials.end())
|
||||
ctx.Error(FormatString("Material with name '%s' is already defined in %s:%u", material_name.getData(), iter->second.FileName.getData(), iter->second.Line));
|
||||
// Check for uniqueness
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial>::iterator iter = Materials.find(material_name);
|
||||
if(iter != Materials.end())
|
||||
ctx.Error(FormatString("Material with name '%s' is already defined in %s:%u", material_name.getData(), iter->second.FileName.getData(), iter->second.Line));
|
||||
|
||||
// Check if there is a parent given
|
||||
Token next = ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN, TOKEN_COLON);
|
||||
// Read parent name, if any
|
||||
StdMeshMaterial* parent = NULL;
|
||||
if(next == TOKEN_COLON)
|
||||
{
|
||||
// Note that if there is a parent, then it needs to be loaded
|
||||
// already. This currently makes only sense when its defined above
|
||||
// in the same material script file or in a parent definition.
|
||||
// We could later support material scripts in the System.c4g.
|
||||
StdCopyStrBuf parent_name;
|
||||
ctx.AdvanceRequired(parent_name, TOKEN_IDTF);
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
// Check if there is a parent given
|
||||
Token next = ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN, TOKEN_COLON);
|
||||
// Read parent name, if any
|
||||
StdMeshMaterial* parent = NULL;
|
||||
if(next == TOKEN_COLON)
|
||||
{
|
||||
// Note that if there is a parent, then it needs to be loaded
|
||||
// already. This currently makes only sense when its defined above
|
||||
// in the same material script file or in a parent definition.
|
||||
// We could later support material scripts in the System.c4g.
|
||||
StdCopyStrBuf parent_name;
|
||||
ctx.AdvanceRequired(parent_name, TOKEN_IDTF);
|
||||
ctx.AdvanceRequired(token_name, TOKEN_BRACE_OPEN);
|
||||
|
||||
iter = Materials.find(parent_name);
|
||||
if(iter == Materials.end())
|
||||
ctx.Error(StdCopyStrBuf("Parent material '") + parent_name + "' does not exist (or is not yet loaded)");
|
||||
parent = &iter->second;
|
||||
}
|
||||
iter = Materials.find(parent_name);
|
||||
if(iter == Materials.end())
|
||||
ctx.Error(StdCopyStrBuf("Parent material '") + parent_name + "' does not exist (or is not yet loaded)");
|
||||
parent = &iter->second;
|
||||
}
|
||||
|
||||
// Copy properties from parent if one is given, otherwise
|
||||
// default-construct the material.
|
||||
StdMeshMaterial& mat = Materials.insert(std::make_pair(material_name, parent ? StdMeshMaterial(*parent) : StdMeshMaterial())).first->second;
|
||||
// Set/Overwrite source and name
|
||||
mat.Name = material_name;
|
||||
mat.FileName = ctx.FileName;
|
||||
mat.Line = ctx.Line;
|
||||
// Copy properties from parent if one is given, otherwise
|
||||
// default-construct the material.
|
||||
StdMeshMaterial& mat = Materials.insert(std::make_pair(material_name, parent ? StdMeshMaterial(*parent) : StdMeshMaterial())).first->second;
|
||||
// Set/Overwrite source and name
|
||||
mat.Name = material_name;
|
||||
mat.FileName = ctx.FileName;
|
||||
mat.Line = ctx.Line;
|
||||
|
||||
mat.Load(ctx);
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
mat.Load(ctx);
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
||||
if(token != TOKEN_EOF)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
if(token != TOKEN_EOF)
|
||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
const StdMeshMaterial* StdMeshMatManager::GetMaterial(const char* material_name) const
|
||||
{
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial>::const_iterator iter = Materials.find(StdCopyStrBuf(material_name));
|
||||
if(iter == Materials.end()) return NULL;
|
||||
return &iter->second;
|
||||
std::map<StdCopyStrBuf, StdMeshMaterial>::const_iterator iter = Materials.find(StdCopyStrBuf(material_name));
|
||||
if(iter == Materials.end()) return NULL;
|
||||
return &iter->second;
|
||||
}
|
||||
|
||||
// vim: et ts=2 sw=2
|
||||
|
|
Loading…
Reference in New Issue