1
0
forked from 0ad/0ad

Initial revision.

This was SVN commit r96.
This commit is contained in:
notpete 2003-11-25 18:34:05 +00:00
parent 61a04870e2
commit cc2b6afdac
16 changed files with 1588 additions and 0 deletions

140
source/terrain/Bound.cpp Executable file
View File

@ -0,0 +1,140 @@
//-----------------------------------------------------------
//
// Name: Bound.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: Basic axis aligned bounding box class
//
//-----------------------------------------------------------
// necessary includes
#include <float.h>
#include "Bound.h"
//-----------------------------------------------------------
// operator+=: extend this bound to include given bound
//-----------------------------------------------------------
CBound& CBound::operator+=(const CBound& b)
{
for (int i=0;i<3;++i) {
if (b[0][i]<m_Data[0][i])
m_Data[0][i]=b[0][i];
if (b[1][i]>m_Data[1][i])
m_Data[1][i]=b[1][i];
}
return *this;
}
//-----------------------------------------------------------
// operator+=: extend this bound to include given point
//-----------------------------------------------------------
CBound& CBound::operator+=(const CVector3D& pt)
{
for (int i=0;i<3;++i) {
if (pt[i]<m_Data[0][i])
m_Data[0][i]=pt[i];
else if (pt[i]>m_Data[1][i])
m_Data[1][i]=pt[i];
}
return *this;
}
//-----------------------------------------------------------
// RayIntersect: intersect ray with this bound; return true
// if ray hits (and store entry and exit times), or false
// otherwise
// note: incoming ray direction must be normalised
//-----------------------------------------------------------
bool CBound::RayIntersect(const CVector3D& origin,const CVector3D& dir,
float& tmin,float& tmax) const
{
float t1,t2;
float tnear,tfar;
if (dir[0]==0) {
if (origin[0]<m_Data[0][0] || origin[0]>m_Data[1][0])
return false;
else {
tnear=(float) FLT_MIN;
tfar=(float) FLT_MAX;
}
} else {
t1=(m_Data[0][0]-origin[0])/dir[0];
t2=(m_Data[1][0]-origin[0])/dir[0];
if (dir[0]<0) {
tnear = t2;
tfar = t1;
} else {
tnear = t1;
tfar = t2;
}
if (tfar<0)
return false;
}
if (dir[1]==0 && (origin[1]<m_Data[0][1] || origin[1]>m_Data[1][1]))
return false;
else {
t1=(m_Data[0][1]-origin[1])/dir[1];
t2=(m_Data[1][1]-origin[1])/dir[1];
if (dir[1]<0) {
if (t2>tnear)
tnear = t2;
if (t1<tfar)
tfar = t1;
} else {
if (t1>tnear)
tnear = t1;
if (t2<tfar)
tfar = t2;
}
if (tnear>tfar || tfar<0)
return false;
}
if (dir[2]==0 && (origin[2]<m_Data[0][2] || origin[2]>m_Data[1][2]))
return false;
else {
t1=(m_Data[0][2]-origin[2])/dir[2];
t2=(m_Data[1][2]-origin[2])/dir[2];
if (dir[2]<0) {
if (t2>tnear)
tnear = t2;
if (t1<tfar)
tfar = t1;
} else {
if (t1>tnear)
tnear = t1;
if (t2<tfar)
tfar = t2;
}
if (tnear>tfar || tfar<0)
return false;
}
tmin=tnear;
tmax=tfar;
return true;
}
//-----------------------------------------------------------
// SetEmpty: initialise this bound as empty
//-----------------------------------------------------------
void CBound::SetEmpty()
{
m_Data[0]=CVector3D(FLT_MAX,FLT_MAX,FLT_MAX);
m_Data[1]=CVector3D(FLT_MIN,FLT_MIN,FLT_MIN);
}

48
source/terrain/Bound.h Executable file
View File

@ -0,0 +1,48 @@
//-----------------------------------------------------------
//
// Name: Bound.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: Basic axis aligned bounding box class
//
//-----------------------------------------------------------
#ifndef _BOUND_H
#define _BOUND_H
// necessary includes
#include "Vector3D.h"
class CBound
{
public:
CBound() {}
CBound(const CVector3D& min,const CVector3D& max) {
m_Data[0]=min; m_Data[1]=max;
}
CVector3D& operator[](int index) { return m_Data[index]; }
const CVector3D& operator[](int index) const { return m_Data[index]; }
void SetEmpty();
CBound& operator+=(const CBound& b);
CBound& operator+=(const CVector3D& pt);
bool RayIntersect(const CVector3D& origin,const CVector3D& dir,float& tmin,float& tmax) const;
float GetVolume() const {
CVector3D v=m_Data[1]-m_Data[0];
return v.X*v.Y*v.Z;
}
private:
CVector3D m_Data[2];
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

22
source/terrain/Color.h Executable file
View File

@ -0,0 +1,22 @@
//-----------------------------------------------------------
//
// Name: Color.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: Definitions for 3 and 4 component floating
// point colors
//
//-----------------------------------------------------------
#ifndef _COLOR_H
#define _COLOR_H
#include "Vector3D.h"
#include "Vector4D.h"
typedef CVector3D RGBColor;
typedef CVector4D RGBAColor;
#endif

44
source/terrain/LightEnv.h Executable file
View File

@ -0,0 +1,44 @@
//----------------------------------------------------------------
//
// Name: LightEnv.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: class describing current lighting environment -
// at the minute, this is only sunlight and ambient light
// parameters; will be extended to handle dynamic lights at some
// later date
//----------------------------------------------------------------
#ifndef __LIGHTENV_H
#define __LIGHTENV_H
#include "Color.h"
#include "Vector3D.h"
class CLightEnv
{
public:
RGBColor m_SunColor;
float m_Elevation;
float m_Rotation;
RGBColor m_TerrainAmbientColor;
RGBColor m_UnitsAmbientColor;
// get sun direction from a rotation and elevation; defined such that:
// 0 rotation = (0,0,1)
// PI/2 rotation = (-1,0,0)
// 0 elevation = (0,0,0)
// PI/2 elevation = (0,-1,0)
void GetSunDirection(CVector3D& lightdir) const {
lightdir.Y=-float(sin(m_Elevation));
float scale=1+lightdir.Y;
lightdir.X=scale*float(sin(m_Rotation));
lightdir.Z=scale*float(cos(m_Rotation));
lightdir.Normalize();
}
};
#endif

128
source/terrain/Model.cpp Executable file
View File

@ -0,0 +1,128 @@
/************************************************************
*
* File Name: Model.Cpp
*
* Description: CModel is a specific instance of a model.
* It contains a pointer to CModelDef, and
* includes all instance information, such as
* current animation pose.
*
************************************************************/
#include "Model.h"
#include "Quaternion.h"
CModel::CModel()
{
m_pModelDef = NULL;
m_pBonePoses = NULL;
}
CModel::~CModel()
{
Destroy();
}
bool CModel::InitModel(CModelDef *modeldef)
{
m_pModelDef = modeldef;
m_pBonePoses = new CMatrix3D[m_pModelDef->GetNumBones()];
ClearPose();
return true;
}
void CModel::Destroy()
{
m_pModelDef = NULL;
if (m_pBonePoses)
delete [] m_pBonePoses;
m_pBonePoses = NULL;
}
void CModel::SetPose (const char *anim_name, float time)
{
int AnimI = -1;
for (int i=0; i<m_pModelDef->GetNumAnimations(); i++)
{
if ( strcmp(anim_name, m_pModelDef->GetAnimations()[i].m_Name) == 0 )
{
AnimI = i;
break;
}
}
if (AnimI == -1)
return;
SModelAnimation *pAnim = &m_pModelDef->GetAnimations()[AnimI];
int StartI = (int)time;
int EndI;// = (int)(time + 0.999999f);
if ((float)StartI == time)
EndI = StartI;
else
EndI = StartI+1;
float factor = time - (float)StartI;
if (EndI > pAnim->m_NumFrames-1)
EndI = 0;
SModelAnimationFrame *pStartFrame = &m_pModelDef->GetAnimationFrames()[pAnim->m_FirstFrame + StartI];
SModelAnimationFrame *pEndFrame = &m_pModelDef->GetAnimationFrames()[pAnim->m_FirstFrame + EndI];
for (i=0; i<m_pModelDef->GetNumBones(); i++)
{
SModelAnimationKey *pKey1 = &m_pModelDef->GetAnimationKeys()[pStartFrame->m_FirstKey+i];
SModelAnimationKey *pKey2 = &m_pModelDef->GetAnimationKeys()[pEndFrame->m_FirstKey+i];
CVector3D Translation = pKey1->m_Translation + (pKey2->m_Translation - pKey1->m_Translation)*factor;
m_pBonePoses[i].SetIdentity();
CQuaternion from, to, rotation;
from.FromEularAngles (pKey1->m_Rotation.X, pKey1->m_Rotation.Y, pKey1->m_Rotation.Z);
to.FromEularAngles (pKey2->m_Rotation.X, pKey2->m_Rotation.Y, pKey2->m_Rotation.Z);
rotation.Slerp (from, to, factor);
m_pBonePoses[i] = rotation.ToMatrix();
m_pBonePoses[i].Translate(Translation);
int Parent = m_pModelDef->GetBones()[i].m_Parent;
if (Parent > -1)
m_pBonePoses[i] = m_pBonePoses[Parent] * m_pBonePoses[i];
}
}
void CModel::ClearPose()
{
//for each bone, set the bone's pose to the intial pose
for (int i=0; i<m_pModelDef->GetNumBones(); i++)
m_pBonePoses[i] = m_pModelDef->GetBones()[i].m_Absolute;
}
void RotateX (CMatrix3D *mat, float angle1, float angle2, float factor)
{
float Cos = cosf(angle1) + (cosf(angle2)-cosf(angle1))*factor;
float Sin = sinf(angle1) + (sinf(angle2)-cosf(angle1))*factor;
CMatrix3D RotX;
RotX._11=1.0f; RotX._12=0.0f; RotX._13=0.0f; RotX._14=0.0f;
RotX._21=0.0f; RotX._22=Cos; RotX._23=-Sin; RotX._24=0.0f;
RotX._31=0.0f; RotX._32=Sin; RotX._33=Cos; RotX._34=0.0f;
RotX._41=0.0f; RotX._42=0.0f; RotX._43=0.0f; RotX._44=1.0f;
*mat = RotX * (*mat);
}

44
source/terrain/Model.h Executable file
View File

@ -0,0 +1,44 @@
/************************************************************
*
* File Name: Model.H
*
* Description: CModel is a specific instance of a model.
* It contains a pointer to CModelDef, and
* includes all instance information, such as
* current animation pose.
*
************************************************************/
#ifndef MODEL_H
#define MODEL_H
#include "Texture.h"
#include "ModelDef.h"
class CModel
{
public:
CModel();
~CModel();
bool InitModel(CModelDef *modeldef);
void Destroy();
void SetPose (const char *anim_name, float time);
void ClearPose ();
//access functions
public:
CModelDef *GetModelDef() { return m_pModelDef; }
CMatrix3D *GetBonePoses() { return m_pBonePoses; }
void SetTexture(const CTexture& tex) { m_Texture=tex; }
CTexture* GetTexture() { return &m_Texture; }
protected:
CTexture m_Texture;
CModelDef *m_pModelDef;
CMatrix3D *m_pBonePoses; //describes the current pose for each bone
};
#endif

109
source/terrain/ModelDef.cpp Executable file
View File

@ -0,0 +1,109 @@
/************************************************************
*
* File Name: ModelDef.Cpp
*
* Description: CModelDef is essentially a CModelFile, except
* that the data is stored in a more convenient
* way. To create a CModelDef, call
* CModelFile::ReadModelDef();
*
************************************************************/
#include "ModelDef.h"
CModelDef::CModelDef()
{
m_pVertices = NULL;
m_pFaces = NULL;
m_pBones = NULL;
m_pAnimationKeys = NULL;
m_pAnimationFrames = NULL;
m_pAnimations = NULL;
m_NumVertices = 0;
m_NumFaces = 0;
m_NumBones = 0;
m_NumAnimationKeys = 0;
m_NumAnimationFrames = 0;
m_NumAnimations = 0;
}
CModelDef::~CModelDef()
{
Destroy();
}
void CModelDef::Destroy()
{
if (m_pVertices)
delete [] m_pVertices;
if (m_pFaces)
delete [] m_pFaces;
if (m_pBones)
delete [] m_pBones;
if (m_pAnimationKeys)
delete [] m_pAnimationKeys;
if (m_pAnimationFrames)
delete [] m_pAnimationFrames;
if (m_pAnimations)
delete [] m_pAnimations;
m_pVertices = NULL;
m_pFaces = NULL;
m_pBones = NULL;
m_pAnimationKeys = NULL;
m_pAnimationFrames = NULL;
m_pAnimations = NULL;
m_NumVertices = 0;
m_NumFaces = 0;
m_NumBones = 0;
m_NumAnimationKeys = 0;
m_NumAnimationFrames = 0;
m_NumAnimations = 0;
}
void CModelDef::SetupBones()
{
for (int i=0; i<m_NumBones; i++)
{
SModelBone *pBone = &m_pBones[i];
pBone->m_Relative.SetIdentity();
pBone->m_Absolute.SetIdentity();
pBone->m_Relative.RotateX (pBone->m_Rotation.X);
pBone->m_Relative.RotateY (pBone->m_Rotation.Y);
pBone->m_Relative.RotateZ (pBone->m_Rotation.Z);
// pBone->m_Relative.RotateX (DEGTORAD(90));
pBone->m_Relative.Translate (pBone->m_Position);
if (pBone->m_Parent >= 0)
{
SModelBone *pParent = &m_pBones[pBone->m_Parent];
pBone->m_Absolute = pParent->m_Absolute * pBone->m_Relative;
}
else
pBone->m_Absolute = pBone->m_Relative;
}
//we need to "un-transform" all the vertices by the initial
//pose of the bones they are attached to.
for (i=0; i<m_NumVertices; i++)
{
SModelVertex *pVertex = &m_pVertices[i];
SModelBone *pBone = &m_pBones[pVertex->m_Bone];
CVector3D BonePos = pBone->m_Absolute.GetTranslation();
pVertex->m_Coords.X -= BonePos.X;
pVertex->m_Coords.Y -= BonePos.Y;
pVertex->m_Coords.Z -= BonePos.Z;
CMatrix3D BoneInvMat = pBone->m_Absolute.GetTranspose();
pVertex->m_Coords = BoneInvMat.Rotate (pVertex->m_Coords);
}
}

120
source/terrain/ModelDef.h Executable file
View File

@ -0,0 +1,120 @@
/************************************************************
*
* File Name: ModelDef.H
*
* Description: CModelDef is essentially a CModelFile, except
* that the data is stored in a more convenient
* way. To create a CModelDef, call
* CModelFile::ReadModelDef();
*
************************************************************/
#ifndef MODELDEF_H
#define MODELDEF_H
#include "Vector3D.h"
#include "Matrix3D.h"
#define MAX_NAME_LENGTH (128)
struct SModelVertex
{
CVector3D m_Coords;
CVector3D m_Norm;
float m_U, m_V;
int m_Bone;
};
struct SModelFace
{
int m_Verts[3];
};
struct SModelBone
{
char m_Name[MAX_NAME_LENGTH];
int m_Parent;
CVector3D m_Position;
CVector3D m_Rotation;
//absolute and relative orientation of this bone
CMatrix3D m_Relative;
CMatrix3D m_Absolute;
};
struct SModelAnimationKey
{
CVector3D m_Translation;
CVector3D m_Rotation;
};
//An animation frame contains one animation key for each of
//the bones in the model
struct SModelAnimationFrame
{
int m_FirstKey;
int m_NumKeys; //this should be that same as number of bones in the model
};
//a complete animation for all the bones
struct SModelAnimation
{
char m_Name[MAX_NAME_LENGTH];
int m_FirstFrame;
int m_NumFrames;
};
class CModelDef
{
friend class CModelFile;
public:
CModelDef ();
virtual ~CModelDef ();
void SetupBones();
void Destroy();
//access functions
public:
SModelVertex *GetVertices() { return m_pVertices; }
SModelFace *GetFaces() { return m_pFaces; }
SModelBone *GetBones() { return m_pBones; }
SModelAnimationKey *GetAnimationKeys() { return m_pAnimationKeys; }
SModelAnimationFrame *GetAnimationFrames() { return m_pAnimationFrames; }
SModelAnimation *GetAnimations() { return m_pAnimations; }
int GetNumVertices() { return m_NumVertices; }
int GetNumFaces() { return m_NumFaces; }
int GetNumBones() { return m_NumBones; }
int GetNumAnimationKeys() { return m_NumAnimationKeys; }
int GetNumAnimationFrames() { return m_NumAnimationFrames; }
int GetNumAnimations() { return m_NumAnimations; }
protected:
SModelVertex *m_pVertices;
SModelFace *m_pFaces;
SModelBone *m_pBones;
SModelAnimationKey *m_pAnimationKeys;
SModelAnimationFrame *m_pAnimationFrames;
SModelAnimation *m_pAnimations;
int m_NumVertices;
int m_NumFaces;
int m_NumBones;
int m_NumAnimationKeys;
int m_NumAnimationFrames;
int m_NumAnimations;
char m_TextureName[MAX_NAME_LENGTH];
};
#endif

352
source/terrain/ModelFile.cpp Executable file
View File

@ -0,0 +1,352 @@
/************************************************************
*
* File Name: ModelFile.Cpp
*
* Description: A CModelFile holds the structure of a model
* file. A model is easily read/written to disk
* using this interface.
*
************************************************************/
#include <stdio.h>
#include "ModelFile.h"
CModelFile::CModelFile ()
{
m_pVertices = NULL;
m_pFaces = NULL;
m_pBones = NULL;
m_pAnimationKeys = NULL;
m_pAnimationFrames = NULL;
m_pAnimations = NULL;
m_NumVertices = 0;
m_NumFaces = 0;
m_NumBones = 0;
m_NumAnimationKeys = 0;
m_NumAnimationFrames = 0;
m_NumAnimations = 0;
}
CModelFile::~CModelFile()
{
Destroy();
}
void CModelFile::Destroy()
{
if (m_pVertices)
delete [] m_pVertices;
if (m_pFaces)
delete [] m_pFaces;
if (m_pBones)
delete [] m_pBones;
if (m_pAnimationKeys)
delete [] m_pAnimationKeys;
if (m_pAnimationFrames)
delete [] m_pAnimationFrames;
if (m_pAnimations)
delete [] m_pAnimations;
m_pVertices = NULL;
m_pFaces = NULL;
m_pBones = NULL;
m_pAnimationKeys = NULL;
m_pAnimationFrames = NULL;
m_pAnimations = NULL;
m_NumVertices = 0;
m_NumFaces = 0;
m_NumBones = 0;
m_NumAnimationKeys = 0;
m_NumAnimationFrames = 0;
m_NumAnimations = 0;
}
bool CModelFile::WriteModelDef (const char *filename, CModelDef *modeldef)
{
FILE *out_f = NULL;
out_f = fopen (filename, "wb");
m_NumVertices = modeldef->m_NumVertices;
m_NumFaces = modeldef->m_NumFaces;
m_NumBones = modeldef->m_NumBones;
m_NumAnimationKeys = modeldef->m_NumAnimationKeys;
m_NumAnimationFrames = modeldef->m_NumAnimationFrames;
m_NumAnimations = modeldef->m_NumAnimations;
m_pVertices = new SModelFile_Vertex[m_NumVertices];
m_pFaces = new SModelFile_Face[m_NumFaces];
m_pBones = new SModelFile_Bone[m_NumBones];
m_pAnimationKeys = new SModelFile_AnimationKey[m_NumAnimationKeys];
m_pAnimationFrames = new SModelFile_AnimationFrame[m_NumAnimationFrames];
m_pAnimations = new SModelFile_Animation[m_NumAnimations];
for (int i=0; i<m_NumVertices; i++)
{
m_pVertices[i].m_Coords = modeldef->m_pVertices[i].m_Coords;
m_pVertices[i].m_Norm = modeldef->m_pVertices[i].m_Norm;
m_pVertices[i].m_U = modeldef->m_pVertices[i].m_U;
m_pVertices[i].m_V = modeldef->m_pVertices[i].m_V;
m_pVertices[i].m_Bone = modeldef->m_pVertices[i].m_Bone;
if (m_pVertices[i].m_Bone >= 0)
{
SModelBone *pBone = &modeldef->m_pBones[m_pVertices[i].m_Bone];
m_pVertices[i].m_Coords = pBone->m_Absolute.Transform (m_pVertices[i].m_Coords);
}
}
for (i=0; i<m_NumFaces; i++)
{
m_pFaces[i].m_Verts[0] = modeldef->m_pFaces[i].m_Verts[0];
m_pFaces[i].m_Verts[1] = modeldef->m_pFaces[i].m_Verts[1];
m_pFaces[i].m_Verts[2] = modeldef->m_pFaces[i].m_Verts[2];
}
for (i=0; i<m_NumBones; i++)
{
strcpy (m_pBones[i].m_Name, modeldef->m_pBones[i].m_Name);
m_pBones[i].m_Position = modeldef->m_pBones[i].m_Position;
m_pBones[i].m_Rotation = modeldef->m_pBones[i].m_Rotation;
m_pBones[i].m_Parent = modeldef->m_pBones[i].m_Parent;
}
for (i=0; i<m_NumAnimationKeys; i++)
{
m_pAnimationKeys[i].m_Translation = modeldef->m_pAnimationKeys[i].m_Translation;
m_pAnimationKeys[i].m_Rotation = modeldef->m_pAnimationKeys[i].m_Rotation;
}
for (i=0; i<m_NumAnimationFrames; i++)
{
m_pAnimationFrames[i].m_FirstKey = modeldef->m_pAnimationFrames[i].m_FirstKey;
m_pAnimationFrames[i].m_NumKeys = modeldef->m_pAnimationFrames[i].m_NumKeys;
}
for (i=0; i<m_NumAnimations; i++)
{
strcpy (m_pAnimations[i].m_Name, modeldef->m_pAnimations[i].m_Name);
m_pAnimations[i].m_FirstFrame = modeldef->m_pAnimations[i].m_FirstFrame;
m_pAnimations[i].m_NumFrames = modeldef->m_pAnimations[i].m_NumFrames;
}
m_Lumps[MF_VERTICES].m_Offset = MF_NUM_LUMPS*sizeof(SLump);
m_Lumps[MF_VERTICES].m_Length = m_NumVertices*sizeof(SModelFile_Vertex);
m_Lumps[MF_FACES].m_Offset = m_Lumps[MF_VERTICES].m_Offset + m_Lumps[MF_VERTICES].m_Length;
m_Lumps[MF_FACES].m_Length = m_NumFaces*sizeof(SModelFile_Face);
m_Lumps[MF_BONES].m_Offset = m_Lumps[MF_FACES].m_Offset + m_Lumps[MF_FACES].m_Length;
m_Lumps[MF_BONES].m_Length = m_NumBones*sizeof(SModelFile_Bone);
m_Lumps[MF_ANIMKEYS].m_Offset = m_Lumps[MF_BONES].m_Offset + m_Lumps[MF_BONES].m_Length;
m_Lumps[MF_ANIMKEYS].m_Length = m_NumAnimationKeys*sizeof(SModelFile_AnimationKey);
m_Lumps[MF_ANIMFRAMES].m_Offset = m_Lumps[MF_ANIMKEYS].m_Offset + m_Lumps[MF_ANIMKEYS].m_Length;
m_Lumps[MF_ANIMFRAMES].m_Length = m_NumAnimationFrames*sizeof(SModelFile_AnimationFrame);
m_Lumps[MF_ANIMS].m_Offset = m_Lumps[MF_ANIMFRAMES].m_Offset + m_Lumps[MF_ANIMFRAMES].m_Length;
m_Lumps[MF_ANIMS].m_Length = m_NumAnimations*sizeof(SModelFile_Animation);
//write the lumps
if (fwrite (m_Lumps, sizeof(SLump), MF_NUM_LUMPS, out_f) != MF_NUM_LUMPS)
{
fclose (out_f);
return false;
}
//write all the data
if (fwrite (m_pVertices, sizeof (SModelFile_Vertex), m_NumVertices, out_f) != (unsigned)m_NumVertices)
{
fclose (out_f);
return false;
}
if (fwrite (m_pFaces, sizeof (SModelFile_Face), m_NumFaces, out_f) != (unsigned)m_NumFaces)
{
fclose (out_f);
return false;
}
if (fwrite (m_pBones, sizeof (SModelFile_Bone), m_NumBones, out_f) != (unsigned)m_NumBones)
{
fclose (out_f);
return false;
}
if (fwrite (m_pAnimationKeys, sizeof (SModelFile_AnimationKey), m_NumAnimationKeys, out_f) != (unsigned)m_NumAnimationKeys)
{
fclose (out_f);
return false;
}
if (fwrite (m_pAnimationFrames, sizeof (SModelFile_AnimationFrame), m_NumAnimationFrames, out_f) != (unsigned)m_NumAnimationFrames)
{
fclose (out_f);
return false;
}
if (fwrite (m_pAnimations, sizeof (SModelFile_Animation), m_NumAnimations, out_f) != (unsigned)m_NumAnimations)
{
fclose (out_f);
return false;
}
fclose (out_f);
Destroy();
return true;
}
bool CModelFile::ReadModelDef (const char *filename, CModelDef *modeldef)
{
FILE *in_f = NULL;
in_f = fopen (filename, "rb");
if (!in_f) {
return false;
}
//read the lumps first
if (fread (m_Lumps, sizeof(SLump), MF_NUM_LUMPS, in_f) != MF_NUM_LUMPS)
{
fclose (in_f);
return false;
}
//calculate the number of each element
m_NumVertices = m_Lumps[MF_VERTICES].m_Length / sizeof(SModelFile_Vertex);
m_NumFaces = m_Lumps[MF_FACES].m_Length / sizeof(SModelFile_Face);
m_NumBones = m_Lumps[MF_BONES].m_Length / sizeof(SModelFile_Bone);
m_NumAnimationKeys = m_Lumps[MF_ANIMKEYS].m_Length / sizeof(SModelFile_AnimationKey);
m_NumAnimationFrames = m_Lumps[MF_ANIMFRAMES].m_Length / sizeof(SModelFile_AnimationFrame);
m_NumAnimations = m_Lumps[MF_ANIMS].m_Length / sizeof(SModelFile_Animation);
//allocate memory
m_pVertices = new SModelFile_Vertex[m_NumVertices];
m_pFaces = new SModelFile_Face[m_NumFaces];
m_pBones = new SModelFile_Bone[m_NumBones];
m_pAnimationKeys = new SModelFile_AnimationKey[m_NumAnimationKeys];
m_pAnimationFrames = new SModelFile_AnimationFrame[m_NumAnimationFrames];
m_pAnimations = new SModelFile_Animation[m_NumAnimations];
//read all the data
fseek (in_f, m_Lumps[MF_VERTICES].m_Offset, SEEK_SET);
if (fread (m_pVertices, sizeof(SModelFile_Vertex), m_NumVertices, in_f) != (unsigned)m_NumVertices)
{
fclose (in_f);
return false;
}
fseek (in_f, m_Lumps[MF_FACES].m_Offset, SEEK_SET);
if (fread (m_pFaces, sizeof (SModelFile_Face), m_NumFaces, in_f) != (unsigned)m_NumFaces)
{
fclose (in_f);
return false;
}
fseek (in_f, m_Lumps[MF_BONES].m_Offset, SEEK_SET);
if (fread (m_pBones, sizeof (SModelFile_Bone), m_NumBones, in_f) != (unsigned)m_NumBones)
{
fclose (in_f);
return false;
}
fseek (in_f, m_Lumps[MF_ANIMKEYS].m_Offset, SEEK_SET);
if (fread (m_pAnimationKeys, sizeof (SModelFile_AnimationKey), m_NumAnimationKeys, in_f) != (unsigned)m_NumAnimationKeys)
{
fclose (in_f);
return false;
}
fseek (in_f, m_Lumps[MF_ANIMFRAMES].m_Offset, SEEK_SET);
if (fread (m_pAnimationFrames, sizeof (SModelFile_AnimationFrame), m_NumAnimationFrames, in_f) != (unsigned)m_NumAnimationFrames)
{
fclose (in_f);
return false;
}
fseek (in_f, m_Lumps[MF_ANIMS].m_Offset, SEEK_SET);
if (fread (m_pAnimations, sizeof (SModelFile_Animation), m_NumAnimations, in_f) != (unsigned)m_NumAnimations)
{
fclose (in_f);
return false;
}
fclose (in_f);
modeldef->Destroy();
modeldef->m_NumVertices = m_NumVertices;
modeldef->m_NumFaces = m_NumFaces;
modeldef->m_NumBones = m_NumBones;
modeldef->m_NumAnimationKeys = m_NumAnimationKeys;
modeldef->m_NumAnimationFrames = m_NumAnimationFrames;
modeldef->m_NumAnimations = m_NumAnimations;
modeldef->m_pVertices = new SModelVertex[m_NumVertices];
modeldef->m_pFaces = new SModelFace[m_NumFaces];
modeldef->m_pBones = new SModelBone[m_NumBones];
modeldef->m_pAnimationKeys = new SModelAnimationKey[m_NumAnimationKeys];
modeldef->m_pAnimationFrames = new SModelAnimationFrame[m_NumAnimationFrames];
modeldef->m_pAnimations = new SModelAnimation[m_NumAnimations];
for (int i=0; i<m_NumVertices; i++)
{
modeldef->m_pVertices[i].m_Coords = m_pVertices[i].m_Coords;
modeldef->m_pVertices[i].m_Norm = m_pVertices[i].m_Norm;
modeldef->m_pVertices[i].m_U = m_pVertices[i].m_U;
modeldef->m_pVertices[i].m_V = m_pVertices[i].m_V;
modeldef->m_pVertices[i].m_Bone = m_pVertices[i].m_Bone;
}
for (i=0; i<m_NumFaces; i++)
{
modeldef->m_pFaces[i].m_Verts[0] = m_pFaces[i].m_Verts[0];
modeldef->m_pFaces[i].m_Verts[1] = m_pFaces[i].m_Verts[1];
modeldef->m_pFaces[i].m_Verts[2] = m_pFaces[i].m_Verts[2];
}
for (i=0; i<m_NumBones; i++)
{
strcpy (modeldef->m_pBones[i].m_Name, m_pBones[i].m_Name);
modeldef->m_pBones[i].m_Position = m_pBones[i].m_Position;
modeldef->m_pBones[i].m_Rotation = m_pBones[i].m_Rotation;
modeldef->m_pBones[i].m_Parent = m_pBones[i].m_Parent;
}
for (i=0; i<m_NumAnimationKeys; i++)
{
modeldef->m_pAnimationKeys[i].m_Translation = m_pAnimationKeys[i].m_Translation;
modeldef->m_pAnimationKeys[i].m_Rotation = m_pAnimationKeys[i].m_Rotation;
}
for (i=0; i<m_NumAnimationFrames; i++)
{
modeldef->m_pAnimationFrames[i].m_FirstKey = m_pAnimationFrames[i].m_FirstKey;
modeldef->m_pAnimationFrames[i].m_NumKeys = m_pAnimationFrames[i].m_NumKeys;
}
for (i=0; i<m_NumAnimations; i++)
{
strcpy (modeldef->m_pAnimations[i].m_Name, m_pAnimations[i].m_Name);
modeldef->m_pAnimations[i].m_FirstFrame = m_pAnimations[i].m_FirstFrame;
modeldef->m_pAnimations[i].m_NumFrames = m_pAnimations[i].m_NumFrames;
}
modeldef->SetupBones();
Destroy();
return true;
}

116
source/terrain/ModelFile.h Executable file
View File

@ -0,0 +1,116 @@
/************************************************************
*
* File Name: ModelFile.H
*
* Description: A CModelFile holds the structure of a model
* file, and is responsible for reading/writing
* a CModelDef from/to a file
*
************************************************************/
#ifndef MODELFILE_H
#define MODELFILE_H
#include <windows.h>
#include "Vector3D.h"
#include "ModelDef.h"
enum EModelFileLumps
{
MF_VERTICES = 0,
MF_FACES,
MF_BONES,
MF_ANIMKEYS,
MF_ANIMFRAMES,
MF_ANIMS,
MF_NUM_LUMPS
};
struct SLump
{
int m_Offset;
int m_Length;
};
struct SModelFile_Vertex
{
CVector3D m_Coords;
CVector3D m_Norm;
float m_U, m_V;
int m_Bone;
};
struct SModelFile_Face
{
int m_Verts[3];
};
struct SModelFile_Bone
{
char m_Name[MAX_NAME_LENGTH];
int m_Parent;
CVector3D m_Position;
CVector3D m_Rotation;
};
struct SModelFile_AnimationKey
{
CVector3D m_Translation;
CVector3D m_Rotation;
};
//animation keys of one animation for one bone
struct SModelFile_AnimationFrame
{
int m_FirstKey;
int m_NumKeys; //this should always be the same as the number of bones in the model.
};
//a complete animation for all the bones
struct SModelFile_Animation
{
char m_Name[MAX_NAME_LENGTH];
int m_FirstFrame;
int m_NumFrames;
};
class CModelFile
{
public:
CModelFile ();
~CModelFile ();
bool ReadModelDef (const char *filename, CModelDef *modeldef);
bool WriteModelDef (const char *filename, CModelDef *modeldef);
private:
void Destroy();
private:
SLump m_Lumps[MF_NUM_LUMPS];
SModelFile_Vertex *m_pVertices;
SModelFile_Face *m_pFaces;
SModelFile_Bone *m_pBones;
SModelFile_AnimationKey *m_pAnimationKeys;
SModelFile_AnimationFrame *m_pAnimationFrames;
SModelFile_Animation *m_pAnimations;
int m_NumVertices;
int m_NumFaces;
int m_NumBones;
int m_NumAnimationKeys;
int m_NumAnimationFrames;
int m_NumAnimations;
};
#endif

179
source/terrain/Quaternion.cpp Executable file
View File

@ -0,0 +1,179 @@
/************************************************************
*
* File Name: Quaternion.Cpp
*
* Description:
*
************************************************************/
#include "Quaternion.h"
const float EPSILON=0.0001f;
CQuaternion::CQuaternion()
{
m_V.Clear ();
m_W = 0;
}
//quaternion addition
CQuaternion CQuaternion::operator + (CQuaternion &quat)
{
CQuaternion Temp;
Temp.m_W = m_W + quat.m_W;
Temp.m_V = m_V + quat.m_V;
return Temp;
}
//quaternion addition/assignment
CQuaternion &CQuaternion::operator += (CQuaternion &quat)
{
m_W += quat.m_W;
m_V += quat.m_V;
return (*this);
}
//quaternion multiplication
CQuaternion CQuaternion::operator * (CQuaternion &quat)
{
CQuaternion Temp;
Temp.m_W = (m_W * quat.m_W) - (m_V.Dot(quat.m_V));
Temp.m_V = (m_V.Cross(quat.m_V)) + (quat.m_V * m_W) + (m_V * quat.m_W);
return Temp;
}
//quaternion multiplication/assignment
CQuaternion &CQuaternion::operator *= (CQuaternion &quat)
{
(*this) = (*this) * quat;
return (*this);
}
void CQuaternion::FromEularAngles (float x, float y, float z)
{
float cr, cp, cy;
float sr, sp, sy;
CQuaternion QRoll, QPitch, QYaw;
cr = cosf(x * 0.5f);
cp = cosf(y * 0.5f);
cy = cosf(z * 0.5f);
sr = sinf(x * 0.5f);
sp = sinf(y * 0.5f);
sy = sinf(z * 0.5f);
QRoll.m_V.Set (sr,0,0);
QRoll.m_W = cr;
QPitch.m_V.Set (0,sp,0);
QPitch.m_W = cp;
QYaw.m_V.Set (0,0,sy);
QYaw.m_W = cy;
(*this) = QYaw * QPitch * QRoll;
}
CMatrix3D CQuaternion::ToMatrix ()
{
CMatrix3D R;
float x2, y2, z2;
float wx, wy, wz, xx, xy, xz, yy, yz, zz;
// calculate coefficients
x2 = m_V.X + m_V.X;
y2 = m_V.Y + m_V.Y;
z2 = m_V.Z + m_V.Z;
xx = m_V.X * x2;
xy = m_V.X * y2;
xz = m_V.X * z2;
yy = m_V.Y * y2;
yz = m_V.Y * z2;
zz = m_V.Z * z2;
wx = m_W * x2;
wy = m_W * y2;
wz = m_W * z2;
R.SetIdentity();
R._11 = 1.0f - (yy + zz);
R._12 = xy - wz;
R._13 = xz + wy;
R._21 = xy + wz;
R._22 = 1.0f - (xx + zz);
R._23 = yz - wx;
R._31 = xz - wy;
R._32 = yz + wx;
R._33 = 1.0f - (xx + yy);
return R;
}
void CQuaternion::Slerp(CQuaternion &from, CQuaternion &to, float ratio)
{
float to1[4];
float omega, cosom, sinom, scale0, scale1;
// calc cosine
cosom = from.m_V.X * to.m_V.X +
from.m_V.Y * to.m_V.Y +
from.m_V.Z * to.m_V.Z +
from.m_W * to.m_W;
// adjust signs (if necessary)
if (cosom < 0.0)
{
cosom = -cosom;
to1[0] = -to.m_V.X;
to1[1] = -to.m_V.Y;
to1[2] = -to.m_V.Z;
to1[3] = -to.m_W;
}
else
{
to1[0] = to.m_V.X;
to1[1] = to.m_V.Y;
to1[2] = to.m_V.Z;
to1[3] = to.m_W;
}
// calculate coefficients
if ((1.0f - cosom) > EPSILON)
{
// standard case (slerp)
omega = acosf(cosom);
sinom = sinf(omega);
scale0 = sinf((1.0f - ratio) * omega) / sinom;
scale1 = sinf(ratio * omega) / sinom;
}
else
{
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0f - ratio;
scale1 = ratio;
}
// calculate final values
m_V.X = scale0 * from.m_V.X + scale1 * to1[0];
m_V.Y = scale0 * from.m_V.Y + scale1 * to1[1];
m_V.Z = scale0 * from.m_V.Z + scale1 * to1[2];
m_W = scale0 * from.m_W + scale1 * to1[3];
}

42
source/terrain/Quaternion.h Executable file
View File

@ -0,0 +1,42 @@
/************************************************************
*
* File Name: Quaternion.H
*
* Description:
*
************************************************************/
#ifndef QUATERNION_H
#define QUATERNION_H
#include "Matrix3D.h"
class CQuaternion
{
public:
CVector3D m_V;
float m_W;
public:
CQuaternion();
//quaternion addition
CQuaternion operator + (CQuaternion &quat);
//quaternion addition/assignment
CQuaternion &operator += (CQuaternion &quat);
//quaternion multiplication
CQuaternion operator * (CQuaternion &quat);
//quaternion multiplication/assignment
CQuaternion &operator *= (CQuaternion &quat);
void FromEularAngles (float x, float y, float z);
//convert the quaternion to matrix
CMatrix3D ToMatrix ();
//sphere interpolation
void Slerp(CQuaternion &from, CQuaternion &to, float ratio);
};
#endif

64
source/terrain/SHCoeffs.cpp Executable file
View File

@ -0,0 +1,64 @@
//----------------------------------------------------------------
//
// Name: SHCoeffs.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: implementation of 9 component spherical harmonic
// lighting
//----------------------------------------------------------------
#include "SHCoeffs.h"
CSHCoeffs::CSHCoeffs()
{
for (int i=0;i<9;i++) {
_data[i].Clear();
}
}
void CSHCoeffs::AddAmbientLight(const RGBColor& color)
{
_data[0]+=color;
}
void CSHCoeffs::AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor)
{
CVector3D dirToLight(-lightDir.X,-lightDir.Y,-lightDir.Z);
const float normalisation = PI*16/17;
const float c1 = SQR(0.282095f) * normalisation * 1.0f;
const float c2 = SQR(0.488603f) * normalisation * (2.0f/3.0f);
const float c3 = SQR(1.092548f) * normalisation * (1.0f/4.0f);
const float c4 = SQR(0.315392f) * normalisation * (1.0f/4.0f);
const float c5 = SQR(0.546274f) * normalisation * (1.0f/4.0f);
_data[0]+=lightColor*c1;
_data[1]+=lightColor*c2*dirToLight.X;
_data[2]+=lightColor*c2*dirToLight.Y;
_data[3]+=lightColor*c2*dirToLight.Z;
_data[4]+=lightColor*c3*dirToLight.X*dirToLight.Z;
_data[5]+=lightColor*c3*dirToLight.Z*dirToLight.Y;
_data[6]+=lightColor*c3*dirToLight.Y*dirToLight.X;
_data[7]+=lightColor*c4*(3.0f*SQR(dirToLight.Z)-1.0f);
_data[8]+=lightColor*c5*(SQR(dirToLight.X)-SQR(dirToLight.Y));
}
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color)
{
#if 1
color=_data[0];
color+=_data[1]*normal.X;
color+=_data[2]*normal.Y;
color+=_data[3]*normal.Z;
color+=_data[4]*(normal.X*normal.Z);
color+=_data[5]*(normal.Z*normal.Y);
color+=_data[6]*(normal.Y*normal.X);
color+=_data[7]*(3*SQR(normal.Z)-1.0f);
color+=_data[8]*(SQR(normal.X)-SQR(normal.Y));
#else
// debug aid: output quantised normal
color=RGBColor((normal.X+1)*0.5,(normal.Y+1)*0.5,(normal.Z+1)*0.5);
#endif
}

34
source/terrain/SHCoeffs.h Executable file
View File

@ -0,0 +1,34 @@
//----------------------------------------------------------------
//
// Name: SHCoeffs.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: implementation of 9 component spherical harmonic
// lighting
//----------------------------------------------------------------
#ifndef __SHCOEFFS_H
#define __SHCOEFFS_H
#include "Color.h"
class CSHCoeffs
{
public:
CSHCoeffs();
void AddAmbientLight(const RGBColor& color);
void AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor);
void Evaluate(const CVector3D& normal,RGBColor& color);
const RGBColor* GetCoefficients() const { return _data; }
private:
RGBColor _data[9];
};
#endif

35
source/terrain/Texture.h Executable file
View File

@ -0,0 +1,35 @@
//-----------------------------------------------------------
//
// Name: Texture.h
// Last Update: 25/11/03
// Author: Rich Cross
// Contact: rich@0ad.wildfiregames.com
//
// Description: Basic texture class
//
//-----------------------------------------------------------
#ifndef _TEXTURE_H
#define _TEXTURE_H
#include "res.h"
#include "..\ps\CStr.h"
class CTexture
{
public:
CTexture() : m_Handle(0) {}
CTexture(const char* name) : m_Name(name), m_Handle(0) {}
void SetName(const char* name) { m_Name=name; }
const char* GetName() const { return (const char*) m_Name; }
Handle GetHandle() const { return m_Handle; }
void SetHandle(Handle handle) { m_Handle=handle; }
private:
CStr m_Name;
Handle m_Handle;
};
#endif

111
source/terrain/Vector4D.h Executable file
View File

@ -0,0 +1,111 @@
//***********************************************************
//
// Name: CVector4D.h
// Last Update: 02/11/03
// Author: Rich Cross
//
// Description: Provides an interface for a vector in R4 and
// allows vector and scalar operations on it
//
//***********************************************************
#ifndef _VECTOR4D_H
#define _VECTOR4D_H
#include <math.h>
#include "MathUtil.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CVector4D:
class CVector4D
{
public:
CVector4D() {}
CVector4D(const float f[4]) { m_X=f[0]; m_Y=f[1]; m_Z=f[2]; m_W=f[3]; }
CVector4D(float x,float y,float z,float w) { m_X=x; m_Y=y; m_Z=z; m_W=w; }
CVector4D(const CVector4D& p) { m_X=p.m_X; m_Y=p.m_Y; m_Z=p.m_Z; m_W=p.m_W; }
operator float*() {
return &m_X;
}
operator const float*() const {
return &m_X;
}
CVector4D operator-() const {
return CVector4D(-m_X,-m_Y,-m_Z,-m_W);
}
CVector4D operator+(const CVector4D& t) const {
return CVector4D(m_X+t.m_X,m_Y+t.m_Y,m_Z+t.m_Z,m_W+t.m_W);
}
CVector4D operator-(const CVector4D& t) const {
return CVector4D(m_X-t.m_X,m_Y-t.m_Y,m_Z-t.m_Z,m_W-t.m_W);
}
CVector4D operator*(const CVector4D& t) const {
return CVector4D(m_X*t.m_X,m_Y*t.m_Y,m_Z*t.m_Z,m_W*t.m_W);
}
CVector4D operator*(float f) const {
return CVector4D(m_X*f,m_Y*f,m_Z*f,m_W*f);
}
CVector4D operator/(float f) const {
float inv=1.0f/f;
return CVector4D(m_X*inv,m_Y*inv,m_Z*inv,m_W*inv);
}
CVector4D& operator+=(const CVector4D& t) {
m_X+=t.m_X; m_Y+=t.m_Y; m_Z+=t.m_Z; m_W+=t.m_W;
return *this;
}
CVector4D& operator-=(const CVector4D& t) {
m_X-=t.m_X; m_Y-=t.m_Y; m_Z-=t.m_Z; m_W-=t.m_W;
return *this;
}
CVector4D& operator*=(const CVector4D& t) {
m_X*=t.m_X; m_Y*=t.m_Y; m_Z*=t.m_Z; m_W*=t.m_W;
return *this;
}
CVector4D& operator*=(float f) {
m_X*=f; m_Y*=f; m_Z*=f; m_W*=f;
return *this;
}
CVector4D& operator/=(float f) {
float invf=1.0f/f;
m_X*=invf; m_Y*=invf; m_Z*=invf; m_W*=invf;
return *this;
}
float dot(const CVector4D& a) const {
return m_X*a.m_X+m_Y*a.m_Y+m_Z*a.m_Z+m_W*a.m_W;
}
float lengthSquared() const {
return SQR(m_X)+SQR(m_Y)+SQR(m_Z)+SQR(m_W);
}
float length() const {
return (float) sqrt(lengthSquared());
}
void normalize() {
float mag=length();
m_X/=mag; m_Y/=mag; m_Z/=mag; m_W/=mag;
}
public:
float m_X,m_Y,m_Z,m_W;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif