Initial revision.
This was SVN commit r96.
This commit is contained in:
parent
61a04870e2
commit
cc2b6afdac
140
source/terrain/Bound.cpp
Executable file
140
source/terrain/Bound.cpp
Executable 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
48
source/terrain/Bound.h
Executable 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
22
source/terrain/Color.h
Executable 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
44
source/terrain/LightEnv.h
Executable 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
128
source/terrain/Model.cpp
Executable 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
44
source/terrain/Model.h
Executable 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
109
source/terrain/ModelDef.cpp
Executable 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
120
source/terrain/ModelDef.h
Executable 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
352
source/terrain/ModelFile.cpp
Executable 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
116
source/terrain/ModelFile.h
Executable 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
179
source/terrain/Quaternion.cpp
Executable 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
42
source/terrain/Quaternion.h
Executable 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
64
source/terrain/SHCoeffs.cpp
Executable 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
34
source/terrain/SHCoeffs.h
Executable 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
35
source/terrain/Texture.h
Executable 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
111
source/terrain/Vector4D.h
Executable 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
|
Loading…
Reference in New Issue
Block a user