Changed terrain stuff from ScEd 0.0.5.2
This was SVN commit r203.
This commit is contained in:
parent
0cd2d55569
commit
d4ca9695d7
@ -10,6 +10,7 @@
|
|||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
// necessary includes
|
// necessary includes
|
||||||
|
#include <assert.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include "Bound.h"
|
#include "Bound.h"
|
||||||
|
|
||||||
@ -138,3 +139,27 @@ void CBound::SetEmpty()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CBound::Transform(const CMatrix3D& m,CBound& result) const
|
||||||
|
{
|
||||||
|
assert(this!=&result);
|
||||||
|
|
||||||
|
for (int i=0;i<3;++i) {
|
||||||
|
// handle translation
|
||||||
|
result[0][i]=result[1][i]=m(3,i);
|
||||||
|
|
||||||
|
// Now find the extreme points by considering the product of the
|
||||||
|
// min and max with each component of matrix
|
||||||
|
for(int j=0;j<3;j++) {
|
||||||
|
float a=m(i,j)*m_Data[0][j];
|
||||||
|
float b=m(i,j)*m_Data[1][j];
|
||||||
|
|
||||||
|
if (a<b) {
|
||||||
|
result[0][i]+=a;
|
||||||
|
result[1][i]+=b;
|
||||||
|
} else {
|
||||||
|
result[0][i]+=b;
|
||||||
|
result[1][i]+=a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
// necessary includes
|
// necessary includes
|
||||||
#include "Vector3D.h"
|
#include "Vector3D.h"
|
||||||
|
#include "Matrix3D.h"
|
||||||
|
|
||||||
class CBound
|
class CBound
|
||||||
{
|
{
|
||||||
@ -22,6 +23,8 @@ public:
|
|||||||
CBound(const CVector3D& min,const CVector3D& max) {
|
CBound(const CVector3D& min,const CVector3D& max) {
|
||||||
m_Data[0]=min; m_Data[1]=max;
|
m_Data[0]=min; m_Data[1]=max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Transform(const CMatrix3D& m,CBound& result) const;
|
||||||
|
|
||||||
CVector3D& operator[](int index) { return m_Data[index]; }
|
CVector3D& operator[](int index) { return m_Data[index]; }
|
||||||
const CVector3D& operator[](int index) const { return m_Data[index]; }
|
const CVector3D& operator[](int index) const { return m_Data[index]; }
|
||||||
|
@ -26,21 +26,21 @@ CCamera::CCamera ()
|
|||||||
CCamera::~CCamera ()
|
CCamera::~CCamera ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCamera::SetProjection (float nearp, float farp, float fov)
|
void CCamera::SetProjection (float nearp, float farp, float fov)
|
||||||
{
|
{
|
||||||
float h, w, Q;
|
float h, w, Q;
|
||||||
|
|
||||||
m_NearPlane = nearp;
|
m_NearPlane = nearp;
|
||||||
m_FarPlane = farp;
|
m_FarPlane = farp;
|
||||||
m_FOV = fov;
|
m_FOV = fov;
|
||||||
|
|
||||||
float Aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
|
float Aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
|
||||||
|
|
||||||
w = 1/tanf (fov*0.5f*Aspect);
|
w = 1/tanf (fov*0.5f*Aspect);
|
||||||
h = 1/tanf (fov*0.5f);
|
h = 1/tanf (fov*0.5f);
|
||||||
Q = m_FarPlane / (m_FarPlane - m_NearPlane);
|
Q = m_FarPlane / (m_FarPlane - m_NearPlane);
|
||||||
|
|
||||||
m_ProjMat.SetZero ();
|
m_ProjMat.SetZero ();
|
||||||
m_ProjMat._11 = w;
|
m_ProjMat._11 = w;
|
||||||
m_ProjMat._22 = h;
|
m_ProjMat._22 = h;
|
||||||
@ -57,8 +57,8 @@ void CCamera::UpdateFrustum ()
|
|||||||
CMatrix3D MatFinal;
|
CMatrix3D MatFinal;
|
||||||
CMatrix3D MatView;
|
CMatrix3D MatView;
|
||||||
|
|
||||||
MatView = m_Orientation.GetTranspose ();
|
m_Orientation.Invert(MatView);
|
||||||
|
|
||||||
MatFinal = m_ProjMat * MatView;
|
MatFinal = m_ProjMat * MatView;
|
||||||
|
|
||||||
//get the RIGHT plane
|
//get the RIGHT plane
|
||||||
|
@ -69,4 +69,4 @@ class CCamera
|
|||||||
CFrustum m_ViewFrustum;
|
CFrustum m_ViewFrustum;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,12 +12,13 @@
|
|||||||
#ifndef MATHUTIL_H
|
#ifndef MATHUTIL_H
|
||||||
#define MATHUTIL_H
|
#define MATHUTIL_H
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
#define PI 3.14159265358979323846f
|
#define PI 3.14159265358979323846f
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEGTORAD(a) ((a) * (PI/180.0f))
|
#define DEGTORAD(a) ((a) * (PI/180.0f))
|
||||||
#define RADTODEG(a) ((a) * (180.0f/PI))
|
#define RADTODEG(a) ((a) * (180.0f/PI))
|
||||||
#define SQR(x) ((x) * (x))
|
#define SQR(x) ((x) * (x))
|
||||||
|
|
||||||
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
|
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
|
||||||
#define ABS(a) ((a > 0) ? (a) : (-a))
|
#define ABS(a) ((a > 0) ? (a) : (-a))
|
||||||
|
|
||||||
|
@ -277,36 +277,27 @@ void CMatrix3D::Scale (float x_scale, float y_scale, float z_scale)
|
|||||||
|
|
||||||
//Returns the transpose of the matrix. For orthonormal
|
//Returns the transpose of the matrix. For orthonormal
|
||||||
//matrices, this is the same is the inverse matrix
|
//matrices, this is the same is the inverse matrix
|
||||||
CMatrix3D CMatrix3D::GetTranspose() const
|
void CMatrix3D::GetTranspose(CMatrix3D& result) const
|
||||||
{
|
{
|
||||||
CMatrix3D Temp;
|
result._11 = _11;
|
||||||
|
result._21 = _12;
|
||||||
|
result._31 = _13;
|
||||||
|
result._41 = _14;
|
||||||
|
|
||||||
Temp._11 = _11;
|
result._12 = _21;
|
||||||
Temp._21 = _12;
|
result._22 = _22;
|
||||||
Temp._31 = _13;
|
result._32 = _23;
|
||||||
Temp._41 = 0.0f;
|
result._42 = _24;
|
||||||
|
|
||||||
Temp._12 = _21;
|
result._13 = _31;
|
||||||
Temp._22 = _22;
|
result._23 = _32;
|
||||||
Temp._32 = _23;
|
result._33 = _33;
|
||||||
Temp._42 = 0.0f;
|
result._43 = _34;
|
||||||
|
|
||||||
Temp._13 = _31;
|
result._14 = _41;
|
||||||
Temp._23 = _32;
|
result._24 = _42;
|
||||||
Temp._33 = _33;
|
result._34 = _43;
|
||||||
Temp._43 = 0.0f;
|
result._44 = _44;
|
||||||
|
|
||||||
Temp._14 = 0.0f;
|
|
||||||
Temp._24 = 0.0f;
|
|
||||||
Temp._34 = 0.0f;
|
|
||||||
Temp._44 = 1.0f;
|
|
||||||
|
|
||||||
CMatrix3D Trans;
|
|
||||||
Trans.SetTranslation (-_14, -_24, -_34);
|
|
||||||
|
|
||||||
Temp = Temp * Trans;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get a vector which points to the left of the matrix
|
//Get a vector which points to the left of the matrix
|
||||||
|
@ -84,7 +84,7 @@ class CMatrix3D
|
|||||||
|
|
||||||
//Returns the transpose of the matrix. For orthonormal
|
//Returns the transpose of the matrix. For orthonormal
|
||||||
//matrices, this is the same is the inverse matrix
|
//matrices, this is the same is the inverse matrix
|
||||||
CMatrix3D GetTranspose() const;
|
void GetTranspose(CMatrix3D& result) const;
|
||||||
|
|
||||||
//Get a vector which points to the left of the matrix
|
//Get a vector which points to the left of the matrix
|
||||||
CVector3D GetLeft () const;
|
CVector3D GetLeft () const;
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
#include "MiniPatch.h"
|
#include "MiniPatch.h"
|
||||||
|
#include "Patch.h"
|
||||||
|
|
||||||
CMiniPatch::CMiniPatch()
|
CMiniPatch::CMiniPatch()
|
||||||
{
|
{
|
||||||
Tex1 = Tex2 = 0;
|
Tex1 = 0;
|
||||||
m_AlphaMap = 0;
|
Tex1Priority = 0;
|
||||||
m_pRightNeighbor = NULL;
|
m_Parent = NULL;
|
||||||
m_pParrent = NULL;
|
|
||||||
m_Rotation = 0;
|
|
||||||
m_RenderStage = 0;
|
|
||||||
m_LastRenderedFrame = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMiniPatch::~CMiniPatch()
|
CMiniPatch::~CMiniPatch()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniPatch::Initialize (STerrainVertex *first_vertex)
|
void CMiniPatch::GetTileIndex(u32& x,u32& z)
|
||||||
{
|
{
|
||||||
m_pVertices = first_vertex;
|
u32 tindex=this-&m_Parent->m_MiniPatches[0][0];
|
||||||
|
x=(m_Parent->m_X*16)+tindex%16;
|
||||||
|
z=(m_Parent->m_Z*16)+tindex/16;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -2,36 +2,28 @@
|
|||||||
#define MINIPATCH_H
|
#define MINIPATCH_H
|
||||||
|
|
||||||
#include "res/res.h"
|
#include "res/res.h"
|
||||||
#include "Color.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
|
|
||||||
struct STerrainVertex
|
|
||||||
{
|
|
||||||
CVector3D m_Position;
|
|
||||||
CVector3D m_Normal;
|
|
||||||
RGBColor m_Color;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
class CPatch;
|
||||||
|
|
||||||
class CMiniPatch
|
class CMiniPatch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMiniPatch();
|
CMiniPatch();
|
||||||
~CMiniPatch();
|
~CMiniPatch();
|
||||||
|
|
||||||
void Initialize (STerrainVertex *first_vertex);
|
// get the index of this tile in the root terrain object; x,y in [0,MapSize)
|
||||||
|
void GetTileIndex(u32& x,u32& z);
|
||||||
|
|
||||||
|
Handle Tex1;
|
||||||
|
int Tex1Priority;
|
||||||
|
|
||||||
|
// Handle Tex2;
|
||||||
|
// Handle m_AlphaMap;
|
||||||
|
// unsigned int m_AlphaMapFlags;
|
||||||
|
|
||||||
Handle Tex1, Tex2;
|
CPatch *m_Parent;
|
||||||
Handle m_AlphaMap;
|
// STerrainVertex *m_pVertices;
|
||||||
CMiniPatch *m_pRightNeighbor;
|
|
||||||
CPatch *m_pParrent;
|
|
||||||
unsigned char m_RenderStage;
|
|
||||||
unsigned int m_LastRenderedFrame;
|
|
||||||
|
|
||||||
unsigned char m_Rotation;
|
|
||||||
|
|
||||||
STerrainVertex *m_pVertices;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,11 +11,13 @@
|
|||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "Quaternion.h"
|
#include "Quaternion.h"
|
||||||
|
#include "Bound.h"
|
||||||
|
|
||||||
CModel::CModel()
|
CModel::CModel()
|
||||||
{
|
{
|
||||||
m_pModelDef = NULL;
|
m_pModelDef = NULL;
|
||||||
m_pBonePoses = NULL;
|
m_pBonePoses = NULL;
|
||||||
|
m_RenderData = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CModel::~CModel()
|
CModel::~CModel()
|
||||||
@ -126,3 +128,19 @@ void RotateX (CMatrix3D *mat, float angle1, float angle2, float factor)
|
|||||||
|
|
||||||
*mat = RotX * (*mat);
|
*mat = RotX * (*mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CModel::CalcBounds(CBound& bound)
|
||||||
|
{
|
||||||
|
bound.SetEmpty();
|
||||||
|
|
||||||
|
for (int i=0; i<m_pModelDef->GetNumVertices(); i++)
|
||||||
|
{
|
||||||
|
SModelVertex *pVertex = &m_pModelDef->GetVertices()[i];
|
||||||
|
CVector3D coord;
|
||||||
|
if (pVertex->m_Bone!=-1) {
|
||||||
|
bound+=GetBonePoses()[pVertex->m_Bone].Transform(pVertex->m_Coords);
|
||||||
|
} else {
|
||||||
|
bound+=pVertex->m_Coords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,8 +14,12 @@
|
|||||||
|
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "ModelDef.h"
|
#include "ModelDef.h"
|
||||||
|
#include "RenderableObject.h"
|
||||||
|
|
||||||
class CModel
|
|
||||||
|
class CBound;
|
||||||
|
|
||||||
|
class CModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CModel();
|
CModel();
|
||||||
@ -27,6 +31,10 @@ class CModel
|
|||||||
void SetPose (const char *anim_name, float time);
|
void SetPose (const char *anim_name, float time);
|
||||||
void ClearPose ();
|
void ClearPose ();
|
||||||
|
|
||||||
|
void CalcBounds(CBound& bound);
|
||||||
|
|
||||||
|
CRenderData* m_RenderData;
|
||||||
|
|
||||||
//access functions
|
//access functions
|
||||||
public:
|
public:
|
||||||
CModelDef *GetModelDef() { return m_pModelDef; }
|
CModelDef *GetModelDef() { return m_pModelDef; }
|
||||||
|
@ -94,16 +94,19 @@ void CModelDef::SetupBones()
|
|||||||
for (i=0; i<m_NumVertices; i++)
|
for (i=0; i<m_NumVertices; i++)
|
||||||
{
|
{
|
||||||
SModelVertex *pVertex = &m_pVertices[i];
|
SModelVertex *pVertex = &m_pVertices[i];
|
||||||
SModelBone *pBone = &m_pBones[pVertex->m_Bone];
|
if (pVertex->m_Bone>=0) {
|
||||||
|
SModelBone *pBone = &m_pBones[pVertex->m_Bone];
|
||||||
|
|
||||||
CVector3D BonePos = pBone->m_Absolute.GetTranslation();
|
CVector3D BonePos = pBone->m_Absolute.GetTranslation();
|
||||||
|
|
||||||
pVertex->m_Coords.X -= BonePos.X;
|
pVertex->m_Coords.X -= BonePos.X;
|
||||||
pVertex->m_Coords.Y -= BonePos.Y;
|
pVertex->m_Coords.Y -= BonePos.Y;
|
||||||
pVertex->m_Coords.Z -= BonePos.Z;
|
pVertex->m_Coords.Z -= BonePos.Z;
|
||||||
|
|
||||||
CMatrix3D BoneInvMat = pBone->m_Absolute.GetTranspose();
|
CMatrix3D BoneInvMat;
|
||||||
|
pBone->m_Absolute.Invert(BoneInvMat);
|
||||||
|
|
||||||
pVertex->m_Coords = BoneInvMat.Rotate (pVertex->m_Coords);
|
pVertex->m_Coords = BoneInvMat.Rotate (pVertex->m_Coords);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class CModelDef
|
|||||||
int GetNumAnimationFrames() { return m_NumAnimationFrames; }
|
int GetNumAnimationFrames() { return m_NumAnimationFrames; }
|
||||||
int GetNumAnimations() { return m_NumAnimations; }
|
int GetNumAnimations() { return m_NumAnimations; }
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
SModelVertex *m_pVertices;
|
SModelVertex *m_pVertices;
|
||||||
SModelFace *m_pFaces;
|
SModelFace *m_pFaces;
|
||||||
SModelBone *m_pBones;
|
SModelBone *m_pBones;
|
||||||
|
@ -11,40 +11,51 @@
|
|||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
#include "Patch.h"
|
#include "Patch.h"
|
||||||
|
#include "Terrain.h"
|
||||||
|
|
||||||
|
|
||||||
CPatch::CPatch ()
|
CPatch::CPatch()
|
||||||
{
|
{
|
||||||
m_pVertices = NULL;
|
m_Parent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPatch::~CPatch ()
|
CPatch::~CPatch()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialize the patch
|
void CPatch::Initialize(CTerrain* parent,u32 x,u32 z)
|
||||||
void CPatch::Initialize (STerrainVertex *first_vertex)
|
|
||||||
{
|
{
|
||||||
int j;
|
delete m_RenderData;
|
||||||
|
m_RenderData;
|
||||||
|
|
||||||
m_pVertices = first_vertex;
|
m_Parent=parent;
|
||||||
|
m_X=x;
|
||||||
|
m_Z=z;
|
||||||
|
|
||||||
|
u32 mapSize=m_Parent->GetVerticesPerSide();
|
||||||
|
|
||||||
|
for (int j=0; j<16; j++) {
|
||||||
|
for (int i=0; i<16; i++) {
|
||||||
|
m_MiniPatches[j][i].m_Parent=this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CalcBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPatch::CalcBounds()
|
||||||
|
{
|
||||||
|
u32 mapSize=m_Parent->GetVerticesPerSide();
|
||||||
|
|
||||||
m_Bounds.SetEmpty();
|
m_Bounds.SetEmpty();
|
||||||
|
|
||||||
for (j=0; j<PATCH_SIZE+1; j++)
|
for (int j=0; j<PATCH_SIZE+1; j++)
|
||||||
{
|
{
|
||||||
for (int i=0; i<PATCH_SIZE+1; i++)
|
for (int i=0; i<PATCH_SIZE+1; i++)
|
||||||
{
|
{
|
||||||
m_Bounds+=m_pVertices[j*MAP_SIZE + i].m_Position;
|
CVector3D pos;
|
||||||
}
|
m_Parent->CalcPosition(m_X*PATCH_SIZE+i,m_Z*PATCH_SIZE+j,pos);
|
||||||
}
|
m_Bounds+=pos;
|
||||||
|
|
||||||
for (j=0; j<16; j++)
|
|
||||||
{
|
|
||||||
for (int i=0; i<16; i++)
|
|
||||||
{
|
|
||||||
int pos = (j*MAP_SIZE) + (i);
|
|
||||||
m_MiniPatches[j][i].Initialize ( &m_pVertices[pos] );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,27 +12,32 @@
|
|||||||
#ifndef PATCH_H
|
#ifndef PATCH_H
|
||||||
#define PATCH_H
|
#define PATCH_H
|
||||||
|
|
||||||
#include "Bound.h"
|
#include "Matrix3D.h"
|
||||||
|
#include "Camera.h"
|
||||||
#include "TerrGlobals.h"
|
#include "TerrGlobals.h"
|
||||||
#include "MiniPatch.h"
|
#include "MiniPatch.h"
|
||||||
|
#include "RenderableObject.h"
|
||||||
|
|
||||||
class CPatch
|
|
||||||
|
class CPatch : public CRenderableObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPatch ();
|
CPatch();
|
||||||
~CPatch ();
|
~CPatch();
|
||||||
|
|
||||||
//initialize the patch
|
//initialize the patch
|
||||||
void Initialize (STerrainVertex *first_vertex);
|
void Initialize(CTerrain* parent,u32 x,u32 z);
|
||||||
|
|
||||||
// protected:
|
// calculate and store bounds of this patch
|
||||||
CMiniPatch m_MiniPatches[16][16];
|
void CalcBounds();
|
||||||
|
|
||||||
CBound m_Bounds;
|
// minipatches (tiles) making up the patch
|
||||||
unsigned int m_LastVisFrame;
|
CMiniPatch m_MiniPatches[16][16];
|
||||||
|
// position of patch in parent terrain grid
|
||||||
STerrainVertex *m_pVertices;
|
u32 m_X,m_Z;
|
||||||
|
// parent terrain
|
||||||
|
CTerrain* m_Parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -106,7 +106,7 @@ void CPatchRData::BuildBlends()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (neighbourTextures.size()>0) {
|
if (neighbourTextures.size()>0) {
|
||||||
u32 count=neighbourTextures.size();
|
size_t count=neighbourTextures.size();
|
||||||
// sort textures from lowest to highest priority
|
// sort textures from lowest to highest priority
|
||||||
std::sort(neighbourTextures.begin(),neighbourTextures.end());
|
std::sort(neighbourTextures.begin(),neighbourTextures.end());
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ void CPatchRData::BuildBlends()
|
|||||||
int vsize=PATCH_SIZE+1;
|
int vsize=PATCH_SIZE+1;
|
||||||
|
|
||||||
SBlendVertex dst;
|
SBlendVertex dst;
|
||||||
int vindex=m_BlendVertices.size();
|
size_t vindex=m_BlendVertices.size();
|
||||||
|
|
||||||
const SBaseVertex& vtx0=m_Vertices[(j*vsize)+i];
|
const SBaseVertex& vtx0=m_Vertices[(j*vsize)+i];
|
||||||
dst.m_UVs[0]=i*0.125f;
|
dst.m_UVs[0]=i*0.125f;
|
||||||
|
@ -10,21 +10,90 @@
|
|||||||
// types - terrain, models, sprites, particles etc
|
// types - terrain, models, sprites, particles etc
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
#include "TransparencyRenderer.h"
|
||||||
#include "Terrain.h"
|
#include "Terrain.h"
|
||||||
#include "Matrix3D.h"
|
#include "Matrix3D.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
#include "PatchRData.h"
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
#include "LightEnv.h"
|
||||||
|
#include "Visual.h"
|
||||||
|
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "ModelDef.h"
|
#include "ModelDef.h"
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "ogl.h"
|
#include "ogl.h"
|
||||||
#include "res/res.h"
|
#include "res/mem.h"
|
||||||
|
#include "res/tex.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct TGAHeader {
|
||||||
|
// header stuff
|
||||||
|
unsigned char iif_size;
|
||||||
|
unsigned char cmap_type;
|
||||||
|
unsigned char image_type;
|
||||||
|
unsigned char pad[5];
|
||||||
|
|
||||||
|
// origin : unused
|
||||||
|
unsigned short d_x_origin;
|
||||||
|
unsigned short d_y_origin;
|
||||||
|
|
||||||
|
// dimensions
|
||||||
|
unsigned short width;
|
||||||
|
unsigned short height;
|
||||||
|
|
||||||
|
// bits per pixel : 16, 24 or 32
|
||||||
|
unsigned char bpp;
|
||||||
|
|
||||||
|
// image descriptor : Bits 3-0: size of alpha channel
|
||||||
|
// Bit 4: must be 0 (reserved)
|
||||||
|
// Bit 5: should be 0 (origin)
|
||||||
|
// Bits 6-7: should be 0 (interleaving)
|
||||||
|
unsigned char image_descriptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool saveTGA(const char* filename,int width,int height,unsigned char* data)
|
||||||
|
{
|
||||||
|
FILE* fp=fopen(filename,"wb");
|
||||||
|
if (!fp) return false;
|
||||||
|
|
||||||
|
// fill file header
|
||||||
|
TGAHeader header;
|
||||||
|
header.iif_size=0;
|
||||||
|
header.cmap_type=0;
|
||||||
|
header.image_type=2;
|
||||||
|
memset(header.pad,0,sizeof(header.pad));
|
||||||
|
header.d_x_origin=0;
|
||||||
|
header.d_y_origin=0;
|
||||||
|
header.width=width;
|
||||||
|
header.height=height;
|
||||||
|
header.bpp=24;
|
||||||
|
header.image_descriptor=0;
|
||||||
|
|
||||||
|
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data
|
||||||
|
if (fwrite(data,width*height*3,1,fp)!=1) {
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return success ..
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern CTerrain g_Terrain;
|
||||||
|
|
||||||
#define RENDER_STAGE_BASE (1)
|
|
||||||
#define RENDER_STAGE_TRANS (2)
|
|
||||||
|
|
||||||
CRenderer::CRenderer ()
|
CRenderer::CRenderer ()
|
||||||
{
|
{
|
||||||
@ -32,7 +101,8 @@ CRenderer::CRenderer ()
|
|||||||
m_Height=0;
|
m_Height=0;
|
||||||
m_Depth=0;
|
m_Depth=0;
|
||||||
m_FrameCounter=0;
|
m_FrameCounter=0;
|
||||||
m_TerrainMode=FILL;
|
m_TerrainRenderMode=SOLID;
|
||||||
|
m_ModelRenderMode=SOLID;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRenderer::~CRenderer ()
|
CRenderer::~CRenderer ()
|
||||||
@ -40,18 +110,38 @@ CRenderer::~CRenderer ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// EnumCaps: build card cap bits
|
||||||
|
void CRenderer::EnumCaps()
|
||||||
|
{
|
||||||
|
// assume support for nothing
|
||||||
|
m_Caps.m_VBO=false;
|
||||||
|
#if 1
|
||||||
|
// now start querying extensions
|
||||||
|
if (oglExtAvail("GL_ARB_vertex_buffer_object")) {
|
||||||
|
m_Caps.m_VBO=true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool CRenderer::Open(int width, int height, int depth)
|
bool CRenderer::Open(int width, int height, int depth)
|
||||||
{
|
{
|
||||||
m_Width = width;
|
m_Width = width;
|
||||||
m_Height = height;
|
m_Height = height;
|
||||||
m_Depth = depth;
|
m_Depth = depth;
|
||||||
|
|
||||||
|
// set packing parameters
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT,1);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||||
|
|
||||||
// setup default state
|
// setup default state
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glClearColor(0.0f,0.0f,0.0f,0.0f);
|
glClearColor(0.0f,0.0f,0.0f,0.0f);
|
||||||
|
|
||||||
|
// query card capabilities
|
||||||
|
EnumCaps();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,35 +162,199 @@ void CRenderer::BeginFrame()
|
|||||||
// bump frame counter
|
// bump frame counter
|
||||||
m_FrameCounter++;
|
m_FrameCounter++;
|
||||||
|
|
||||||
|
// zero out all the per-frame stats
|
||||||
|
m_Stats.Reset();
|
||||||
|
|
||||||
|
// calculate coefficients for terrain and unit lighting
|
||||||
|
m_SHCoeffsUnits.Clear();
|
||||||
|
m_SHCoeffsTerrain.Clear();
|
||||||
|
|
||||||
|
if (m_LightEnv) {
|
||||||
|
CVector3D dirlight;
|
||||||
|
m_LightEnv->GetSunDirection(dirlight);
|
||||||
|
m_SHCoeffsUnits.AddDirectionalLight(dirlight,m_LightEnv->m_SunColor);
|
||||||
|
m_SHCoeffsTerrain.AddDirectionalLight(dirlight,m_LightEnv->m_SunColor);
|
||||||
|
|
||||||
|
m_SHCoeffsUnits.AddAmbientLight(m_LightEnv->m_UnitsAmbientColor);
|
||||||
|
m_SHCoeffsTerrain.AddAmbientLight(m_LightEnv->m_TerrainAmbientColor);
|
||||||
|
}
|
||||||
|
|
||||||
// clear buffers
|
// clear buffers
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRenderer::RenderPatches()
|
||||||
|
{
|
||||||
|
// switch on wireframe if we need it
|
||||||
|
if (m_TerrainRenderMode==WIREFRAME) {
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render all the patches, including blend pass
|
||||||
|
RenderPatchSubmissions();
|
||||||
|
|
||||||
|
if (m_TerrainRenderMode==WIREFRAME) {
|
||||||
|
// switch wireframe off again
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||||
|
} else if (m_TerrainRenderMode==EDGED_FACES) {
|
||||||
|
// edged faces: need to make a second pass over the data:
|
||||||
|
// first switch on wireframe
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||||
|
|
||||||
|
// setup some renderstate ..
|
||||||
|
glDepthMask(0);
|
||||||
|
SetTexture(0,0);
|
||||||
|
glColor4f(1,1,1,0.35f);
|
||||||
|
glLineWidth(2.0f);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// .. and some client states
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
// render each patch in wireframe
|
||||||
|
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||||
|
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||||
|
CPatchRData* patchdata=(CPatchRData*) patch->m_RenderData;
|
||||||
|
patchdata->RenderWireframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set color for outline
|
||||||
|
glColor3f(0,0,1);
|
||||||
|
glLineWidth(4.0f);
|
||||||
|
|
||||||
|
// render outline of each patch
|
||||||
|
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||||
|
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||||
|
CPatchRData* patchdata=(CPatchRData*) patch->m_RenderData;
|
||||||
|
patchdata->RenderOutline();
|
||||||
|
}
|
||||||
|
|
||||||
|
// .. and switch off the client states
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
// .. and restore the renderstates
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDepthMask(1);
|
||||||
|
|
||||||
|
// restore fill mode, and we're done
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderer::RenderModelSubmissions()
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
// first ensure all patches have up to date renderdata built for them; build up transparent passes
|
||||||
|
// along the way
|
||||||
|
for (i=0;i<m_Models.size();++i) {
|
||||||
|
CVisual* visual=m_Models[i].m_Object;
|
||||||
|
CModelRData* data=(CModelRData*) visual->m_Model->m_RenderData;
|
||||||
|
if (data==0) {
|
||||||
|
// no renderdata for model, create it now
|
||||||
|
data=new CModelRData(visual->m_Model);
|
||||||
|
} else {
|
||||||
|
data->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildTransparentPasses(visual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup texture environment to modulate diffuse color with texture color
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||||
|
|
||||||
|
// just pass through texture's alpha
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||||
|
|
||||||
|
// setup client states
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
// render models
|
||||||
|
for (i=0;i<m_Models.size();++i) {
|
||||||
|
CVisual* visual=m_Models[i].m_Object;
|
||||||
|
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
|
||||||
|
modeldata->Render(visual->GetTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch off client states
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderer::RenderModels()
|
||||||
|
{
|
||||||
|
// switch on wireframe if we need it
|
||||||
|
if (m_ModelRenderMode==WIREFRAME) {
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render all the models
|
||||||
|
RenderModelSubmissions();
|
||||||
|
|
||||||
|
if (m_ModelRenderMode==WIREFRAME) {
|
||||||
|
// switch wireframe off again
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||||
|
} else if (m_ModelRenderMode==EDGED_FACES) {
|
||||||
|
// edged faces: need to make a second pass over the data:
|
||||||
|
// first switch on wireframe
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||||
|
|
||||||
|
// setup some renderstate ..
|
||||||
|
glDepthMask(0);
|
||||||
|
SetTexture(0,0);
|
||||||
|
glColor4f(1,1,1,0.75f);
|
||||||
|
glLineWidth(1.0f);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// .. and some client states
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
// render each model
|
||||||
|
for (uint i=0;i<m_Models.size();++i) {
|
||||||
|
CVisual* visual=m_Models[i].m_Object;
|
||||||
|
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
|
||||||
|
modeldata->RenderWireframe(visual->GetTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
// .. and switch off the client states
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
// .. and restore the renderstates
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDepthMask(1);
|
||||||
|
|
||||||
|
// restore fill mode, and we're done
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// force rendering of any batched objects
|
// force rendering of any batched objects
|
||||||
void CRenderer::FlushFrame()
|
void CRenderer::FlushFrame()
|
||||||
{
|
{
|
||||||
unsigned i;
|
// render submitted patches and models
|
||||||
|
RenderPatches();
|
||||||
|
|
||||||
// render base terrain
|
RenderModels();
|
||||||
if (m_TerrainMode==WIREFRAME) {
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
// call on the transparency renderer to render all the transparent stuff
|
||||||
RenderPatchBase(m_TerrainPatches[i].m_Object);
|
g_TransparencyRenderer.Render();
|
||||||
}
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
RenderPatchTrans(m_TerrainPatches[i].m_Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_TerrainMode==WIREFRAME) {
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// render models
|
|
||||||
for (i=0;i<m_Models.size();++i) {
|
|
||||||
RenderModel(m_Models[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty lists
|
// empty lists
|
||||||
m_TerrainPatches.clear();
|
m_TerrainPatches.clear();
|
||||||
@ -115,7 +369,8 @@ void CRenderer::EndFrame()
|
|||||||
|
|
||||||
void CRenderer::SetCamera(CCamera& camera)
|
void CRenderer::SetCamera(CCamera& camera)
|
||||||
{
|
{
|
||||||
CMatrix3D view = camera.m_Orientation.GetTranspose();
|
CMatrix3D view;
|
||||||
|
camera.m_Orientation.Invert(view);
|
||||||
CMatrix3D proj = camera.GetProjection();
|
CMatrix3D proj = camera.GetProjection();
|
||||||
|
|
||||||
float gl_view[16] = {view._11, view._21, view._31, view._41,
|
float gl_view[16] = {view._11, view._21, view._31, view._41,
|
||||||
@ -137,21 +392,21 @@ void CRenderer::SetCamera(CCamera& camera)
|
|||||||
|
|
||||||
const SViewPort& vp = camera.GetViewPort();
|
const SViewPort& vp = camera.GetViewPort();
|
||||||
glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height);
|
glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height);
|
||||||
|
|
||||||
|
m_Camera=camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::Submit(CPatch* patch)
|
void CRenderer::Submit(CPatch* patch)
|
||||||
{
|
{
|
||||||
SSubmission<CPatch*> sub;
|
SSubmission<CPatch*> sub;
|
||||||
patch->m_LastVisFrame=m_FrameCounter;
|
|
||||||
sub.m_Object=patch;
|
sub.m_Object=patch;
|
||||||
m_TerrainPatches.push_back(sub);
|
m_TerrainPatches.push_back(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::Submit(CModel* model,CMatrix3D* transform)
|
void CRenderer::Submit(CVisual* visual)
|
||||||
{
|
{
|
||||||
SSubmission<CModel*> sub;
|
SSubmission<CVisual*> sub;
|
||||||
sub.m_Object=model;
|
sub.m_Object=visual;
|
||||||
sub.m_Transform=transform;
|
|
||||||
m_Models.push_back(sub);
|
m_Models.push_back(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,74 +422,109 @@ void CRenderer::Submit(COverlay* overlay)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRenderer::RenderPatchSubmissions()
|
||||||
|
|
||||||
/*
|
|
||||||
void CRenderer::RenderTileOutline (CMiniPatch *mpatch)
|
|
||||||
{
|
{
|
||||||
glActiveTexture (GL_TEXTURE0);
|
uint i;
|
||||||
glDisable (GL_DEPTH_TEST);
|
// first ensure all patches have up to date renderdata built for them
|
||||||
glDisable (GL_TEXTURE_2D);
|
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||||
glLineWidth (4);
|
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||||
|
CPatchRData* data=(CPatchRData*) patch->m_RenderData;
|
||||||
STerrainVertex V[4];
|
if (data==0) {
|
||||||
V[0] = mpatch->m_pVertices[0];
|
// no renderdata for patch, create it now
|
||||||
V[1] = mpatch->m_pVertices[1];
|
data=new CPatchRData(patch);
|
||||||
V[2] = mpatch->m_pVertices[MAP_SIZE*1 + 1];
|
} else {
|
||||||
V[3] = mpatch->m_pVertices[MAP_SIZE*1];
|
data->Update();
|
||||||
|
|
||||||
glColor3f (0,1.0f,0);
|
|
||||||
|
|
||||||
glBegin (GL_LINE_LOOP);
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
|
||||||
glVertex3fv(&V[i].m_Position.X);
|
|
||||||
|
|
||||||
glEnd ();
|
|
||||||
|
|
||||||
glEnable (GL_DEPTH_TEST);
|
|
||||||
glEnable (GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void CRenderer::RenderModel(SSubmission<CModel*>& modelsub)
|
|
||||||
{
|
|
||||||
glPushMatrix();
|
|
||||||
glMultMatrixf(modelsub.m_Transform->_data);
|
|
||||||
|
|
||||||
SetTexture(0,modelsub.m_Object->GetTexture());
|
|
||||||
glColor3f(1.0f,1.0f,1.0f);
|
|
||||||
|
|
||||||
CModel* mdl=(CModel*) modelsub.m_Object;
|
|
||||||
CModelDef* mdldef=(CModelDef*) mdl->GetModelDef();
|
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
for (int fi=0; fi<mdldef->GetNumFaces(); fi++)
|
|
||||||
{
|
|
||||||
SModelFace *pFace = &mdldef->GetFaces()[fi];
|
|
||||||
|
|
||||||
for (int vi=0; vi<3; vi++)
|
|
||||||
{
|
|
||||||
SModelVertex *pVertex = &mdldef->GetVertices()[pFace->m_Verts[vi]];
|
|
||||||
CVector3D Coord = mdl->GetBonePoses()[pVertex->m_Bone].Transform(pVertex->m_Coords);
|
|
||||||
|
|
||||||
glTexCoord2f (pVertex->m_U, pVertex->m_V);
|
|
||||||
|
|
||||||
glVertex3f (Coord.X, Coord.Y, Coord.Z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glPopMatrix();
|
// set up client states for base pass
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
// set up texture environment for base pass
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||||
|
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// render base passes for each patch
|
||||||
|
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||||
|
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||||
|
CPatchRData* patchdata=(CPatchRData*) patch->m_RenderData;
|
||||||
|
patchdata->RenderBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch on the composite alpha map texture
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_CompositeAlphaMap);
|
||||||
|
|
||||||
|
// setup additional texenv required by blend pass
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||||
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// switch on blending
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// no need to write to the depth buffer a second time
|
||||||
|
glDepthMask(0);
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE1);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
// render blend passes for each patch
|
||||||
|
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||||
|
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||||
|
CPatchRData* patchdata=(CPatchRData*) patch->m_RenderData;
|
||||||
|
patchdata->RenderBlends();
|
||||||
|
}
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE1);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
// restore depth writes
|
||||||
|
glDepthMask(1);
|
||||||
|
|
||||||
|
// restore default state: switch off blending
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
// switch off texture unit 1, make unit 0 active texture
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
// switch off all client states
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// try and load the given texture
|
// try and load the given texture
|
||||||
bool CRenderer::LoadTexture(CTexture* texture)
|
bool CRenderer::LoadTexture(CTexture* texture)
|
||||||
{
|
{
|
||||||
Handle h=texture->GetHandle();
|
Handle h=texture->GetHandle();
|
||||||
if (h) {
|
if (h) {
|
||||||
// already tried to load this texture, nothing to do here - just return accord to whether this
|
// already tried to load this texture, nothing to do here - just return success according
|
||||||
// is a valid handle
|
// to whether this is a valid handle or not
|
||||||
return h==0xfffffff ? true : false;
|
return h==0xfffffff ? true : false;
|
||||||
} else {
|
} else {
|
||||||
h=tex_load(texture->GetName());
|
h=tex_load(texture->GetName());
|
||||||
@ -250,7 +540,7 @@ bool CRenderer::LoadTexture(CTexture* texture)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
||||||
void CRenderer::SetTexture(int unit,CTexture* texture)
|
void CRenderer::SetTexture(int unit,CTexture* texture,u32 wrapflags)
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0+unit);
|
glActiveTexture(GL_TEXTURE0+unit);
|
||||||
if (texture) {
|
if (texture) {
|
||||||
@ -258,6 +548,11 @@ void CRenderer::SetTexture(int unit,CTexture* texture)
|
|||||||
if (!h) {
|
if (!h) {
|
||||||
LoadTexture(texture);
|
LoadTexture(texture);
|
||||||
h=texture->GetHandle();
|
h=texture->GetHandle();
|
||||||
|
|
||||||
|
if (wrapflags) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable texturing if invalid handle
|
// disable texturing if invalid handle
|
||||||
@ -273,247 +568,147 @@ void CRenderer::SetTexture(int unit,CTexture* texture)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::RenderPatchBase (CPatch *patch)
|
bool CRenderer::IsTextureTransparent(CTexture* texture)
|
||||||
{
|
{
|
||||||
CMiniPatch *MPatch, *MPCurrent;
|
if (texture) {
|
||||||
|
Handle h=texture->GetHandle();
|
||||||
float StartU, StartV;
|
if (!h) {
|
||||||
|
LoadTexture(texture);
|
||||||
|
h=texture->GetHandle();
|
||||||
for (int j=0; j<16; j++)
|
if (h!=0xffffffff) {
|
||||||
{
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
for (int i=0; i<16; i++)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
{
|
|
||||||
MPatch = &(patch->m_MiniPatches[j][i]);
|
|
||||||
|
|
||||||
if (MPatch->m_LastRenderedFrame == m_FrameCounter)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
glActiveTexture (GL_TEXTURE0);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
tex_bind(MPatch->Tex1);
|
|
||||||
|
|
||||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
||||||
/////////////////////////////////////
|
|
||||||
|
|
||||||
StartU = 0.125f * (float)(i%8);
|
|
||||||
StartV = 0.125f * (float)(j%8);
|
|
||||||
|
|
||||||
float tu[2], tv[2];
|
|
||||||
tu[0] = tu[1] = StartU;
|
|
||||||
tv[0] = StartV+0.125f;
|
|
||||||
tv[1] = StartV;
|
|
||||||
|
|
||||||
MPCurrent = MPatch;
|
|
||||||
glBegin (GL_TRIANGLE_STRIP);
|
|
||||||
|
|
||||||
int start = 0;
|
|
||||||
|
|
||||||
while (MPCurrent)
|
|
||||||
{
|
|
||||||
for (int x=start; x<2; x++)
|
|
||||||
{
|
|
||||||
int v1 = MAP_SIZE + x;
|
|
||||||
int v2 = x;
|
|
||||||
|
|
||||||
glTexCoord2f (tu[0], tv[0]);
|
|
||||||
|
|
||||||
if (g_HillShading)
|
|
||||||
glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X);
|
|
||||||
else
|
|
||||||
glColor3f (1,1,1);
|
|
||||||
|
|
||||||
glVertex3f (MPCurrent->m_pVertices[v1].m_Position.X,
|
|
||||||
MPCurrent->m_pVertices[v1].m_Position.Y,
|
|
||||||
MPCurrent->m_pVertices[v1].m_Position.Z);
|
|
||||||
|
|
||||||
glTexCoord2f (tu[1], tv[1]);
|
|
||||||
|
|
||||||
if (g_HillShading)
|
|
||||||
glColor3fv(&MPCurrent->m_pVertices[v2].m_Color.X);
|
|
||||||
else
|
|
||||||
glColor3f (1,1,1);
|
|
||||||
|
|
||||||
glVertex3f (MPCurrent->m_pVertices[v2].m_Position.X,
|
|
||||||
MPCurrent->m_pVertices[v2].m_Position.Y,
|
|
||||||
MPCurrent->m_pVertices[v2].m_Position.Z);
|
|
||||||
|
|
||||||
tu[0]+=0.125f;
|
|
||||||
tu[1]+=0.125f;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPCurrent->m_LastRenderedFrame = m_FrameCounter;
|
|
||||||
MPCurrent->m_RenderStage = RENDER_STAGE_BASE;
|
|
||||||
|
|
||||||
if (!MPCurrent->m_pRightNeighbor)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MPCurrent->m_pRightNeighbor->Tex1 != MPCurrent->Tex1 ||
|
|
||||||
MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != m_FrameCounter)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPCurrent = MPCurrent->m_pRightNeighbor;
|
|
||||||
start = 1;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
glEnd ();
|
if (h!=0xffffffff && h) {
|
||||||
|
int fmt;
|
||||||
|
int bpp;
|
||||||
|
|
||||||
|
tex_info(h, NULL, NULL, &fmt, &bpp, NULL);
|
||||||
|
if (bpp==24 || fmt == GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::RenderPatchTrans (CPatch *patch)
|
static int RoundUpToPowerOf2(int x)
|
||||||
{
|
{
|
||||||
CMiniPatch *MPatch, *MPCurrent;
|
if ((x & (x-1))==0) return x;
|
||||||
|
int d=x;
|
||||||
|
while (d & (d-1)) {
|
||||||
|
d&=(d-1);
|
||||||
|
}
|
||||||
|
return d<<1;
|
||||||
|
}
|
||||||
|
|
||||||
float StartU, StartV;
|
|
||||||
|
inline void CopyTriple(unsigned char* dst,const unsigned char* src)
|
||||||
|
{
|
||||||
|
dst[0]=src[0];
|
||||||
|
dst[1]=src[1];
|
||||||
|
dst[2]=src[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAlphaMaps: load the 14 default alpha maps, pack them into one composite texture and
|
||||||
|
// calculate the coordinate of each alphamap within this packed texture .. need to add
|
||||||
|
// validation that all maps are the same size
|
||||||
|
bool CRenderer::LoadAlphaMaps(const char* fnames[])
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0_ARB);
|
||||||
|
|
||||||
glEnable (GL_BLEND);
|
Handle textures[NumAlphaMaps];
|
||||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
int i;
|
||||||
|
|
||||||
for (int j=0; j<16; j++)
|
for (i=0;i<NumAlphaMaps;i++) {
|
||||||
{
|
textures[i]=tex_load(fnames[i]);
|
||||||
for (int i=0; i<16; i++)
|
if (textures[i] <= 0) {
|
||||||
{
|
return false;
|
||||||
MPatch = &(patch->m_MiniPatches[j][i]);
|
|
||||||
|
|
||||||
if (MPatch->m_LastRenderedFrame == m_FrameCounter &&
|
|
||||||
MPatch->m_RenderStage == RENDER_STAGE_TRANS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//now for transition
|
|
||||||
if (MPatch->Tex2 && MPatch->m_AlphaMap)
|
|
||||||
{
|
|
||||||
|
|
||||||
glActiveTexture (GL_TEXTURE0);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
tex_bind(MPatch->Tex2);
|
|
||||||
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
||||||
/////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
glActiveTexture (GL_TEXTURE1);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
tex_bind(MPatch->m_AlphaMap);
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
/////////////////////////////////////
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
||||||
/////////////////////////////////////
|
|
||||||
|
|
||||||
StartU = 0.125f * (float)(i%8);
|
|
||||||
StartV = 0.125f * (float)(j%8);
|
|
||||||
|
|
||||||
float tu[2], tv[2];
|
|
||||||
tu[0] = tu[1] = StartU;
|
|
||||||
tv[0] = StartV+0.125f;
|
|
||||||
tv[1] = StartV;
|
|
||||||
|
|
||||||
glBegin (GL_TRIANGLE_STRIP);
|
|
||||||
MPCurrent = MPatch;
|
|
||||||
|
|
||||||
int start = 0;
|
|
||||||
|
|
||||||
while (MPCurrent)
|
|
||||||
{
|
|
||||||
for (int x=start; x<2; x++)
|
|
||||||
{
|
|
||||||
int v1 = MAP_SIZE + x;
|
|
||||||
int v2 = x;
|
|
||||||
|
|
||||||
glMultiTexCoord2f (GL_TEXTURE0_ARB, tu[0], tv[0]);
|
|
||||||
glMultiTexCoord2f (GL_TEXTURE1_ARB, tu[0]*2, tv[0]*2);
|
|
||||||
|
|
||||||
if (g_HillShading)
|
|
||||||
glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X);
|
|
||||||
else
|
|
||||||
glColor3f (1,1,1);
|
|
||||||
|
|
||||||
glVertex3f (MPCurrent->m_pVertices[v1].m_Position.X,
|
|
||||||
MPCurrent->m_pVertices[v1].m_Position.Y,
|
|
||||||
MPCurrent->m_pVertices[v1].m_Position.Z);
|
|
||||||
|
|
||||||
glMultiTexCoord2f (GL_TEXTURE0_ARB, tu[1], tv[1]);
|
|
||||||
glMultiTexCoord2f (GL_TEXTURE1_ARB, tu[1]*2, tv[1]*2);
|
|
||||||
|
|
||||||
if (g_HillShading)
|
|
||||||
glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X);
|
|
||||||
else
|
|
||||||
glColor3f (1,1,1);
|
|
||||||
|
|
||||||
glVertex3f (MPCurrent->m_pVertices[v2].m_Position.X,
|
|
||||||
MPCurrent->m_pVertices[v2].m_Position.Y,
|
|
||||||
MPCurrent->m_pVertices[v2].m_Position.Z);
|
|
||||||
|
|
||||||
tu[0]+=0.125f;
|
|
||||||
tu[1]+=0.125f;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPCurrent->m_LastRenderedFrame = m_FrameCounter;
|
|
||||||
MPCurrent->m_RenderStage = RENDER_STAGE_TRANS;
|
|
||||||
|
|
||||||
if (!MPCurrent->m_pRightNeighbor)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (MPCurrent->m_pRightNeighbor->Tex2 != MPCurrent->Tex2 ||
|
|
||||||
MPCurrent->m_pRightNeighbor->m_AlphaMap != MPCurrent->m_AlphaMap ||
|
|
||||||
MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != m_FrameCounter)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPCurrent = MPCurrent->m_pRightNeighbor;
|
|
||||||
start=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnd ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glDisable (GL_BLEND);
|
|
||||||
glActiveTexture (GL_TEXTURE1);
|
int base;//=textures[0].width;
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glActiveTexture (GL_TEXTURE0);
|
i=tex_info(textures[0], &base, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
int size=(base+4)*NumAlphaMaps;
|
||||||
|
int texsize=RoundUpToPowerOf2(size);
|
||||||
|
|
||||||
|
unsigned char* data=new unsigned char[texsize*base*3];
|
||||||
|
|
||||||
|
// for each tile on row
|
||||||
|
for (i=0;i<NumAlphaMaps;i++) {
|
||||||
|
//TEX& tex=textures[i];
|
||||||
|
int bpp;
|
||||||
|
// get src of copy
|
||||||
|
const unsigned char* src;
|
||||||
|
|
||||||
|
tex_info(textures[i], NULL, NULL, NULL, &bpp, (void **)&src);
|
||||||
|
|
||||||
|
int srcstep=bpp/8;
|
||||||
|
|
||||||
|
// get destination of copy
|
||||||
|
unsigned char* dst=data+3*(i*(base+4));
|
||||||
|
|
||||||
|
// for each row of image
|
||||||
|
for (int j=0;j<base;j++) {
|
||||||
|
// duplicate first pixel
|
||||||
|
CopyTriple(dst,src);
|
||||||
|
dst+=3;
|
||||||
|
CopyTriple(dst,src);
|
||||||
|
dst+=3;
|
||||||
|
|
||||||
|
// copy a row
|
||||||
|
for (int k=0;k<base;k++) {
|
||||||
|
CopyTriple(dst,src);
|
||||||
|
dst+=3;
|
||||||
|
src+=srcstep;
|
||||||
|
}
|
||||||
|
// duplicate last pixel
|
||||||
|
CopyTriple(dst,(src-bpp/8));
|
||||||
|
dst+=3;
|
||||||
|
CopyTriple(dst,(src-bpp/8));
|
||||||
|
dst+=3;
|
||||||
|
|
||||||
|
// advance write pointer for next row
|
||||||
|
dst+=3*(texsize-(base+4));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_AlphaMapCoords[i].u0=float(i*(base+4)+2)/float(texsize);
|
||||||
|
m_AlphaMapCoords[i].u1=float((i+1)*(base+4)-2)/float(texsize);
|
||||||
|
m_AlphaMapCoords[i].v0=0.0f;
|
||||||
|
m_AlphaMapCoords[i].v1=1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenTextures(1,&m_CompositeAlphaMap);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,m_CompositeAlphaMap);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,texsize,base,0,GL_RGB,GL_UNSIGNED_BYTE,data);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRenderer::BuildTransparentPasses(CVisual* visual)
|
||||||
|
{
|
||||||
|
if (!IsTextureTransparent(visual->m_Model->GetTexture())) {
|
||||||
|
// ok, no transparency on this model .. ignore it here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add this visual to the transparency renderer for later processing
|
||||||
|
g_TransparencyRenderer.Add(visual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,20 +15,31 @@
|
|||||||
#define RENDERER_H
|
#define RENDERER_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "res/res.h"
|
||||||
#include "ogl.h"
|
#include "ogl.h"
|
||||||
|
#include "Camera.h"
|
||||||
#include "Frustum.h"
|
#include "Frustum.h"
|
||||||
|
#include "PatchRData.h"
|
||||||
|
#include "ModelRData.h"
|
||||||
|
#include "SHCoeffs.h"
|
||||||
|
#include "Terrain.h"
|
||||||
|
|
||||||
// necessary declarations
|
// necessary declarations
|
||||||
class CCamera;
|
class CCamera;
|
||||||
class CPatch;
|
class CPatch;
|
||||||
class CModel;
|
class CVisual;
|
||||||
class CSprite;
|
class CSprite;
|
||||||
class CParticleSys;
|
class CParticleSys;
|
||||||
class COverlay;
|
class COverlay;
|
||||||
class CMaterial;
|
class CMaterial;
|
||||||
class CLightEnv;
|
class CLightEnv;
|
||||||
class SPatchRData;
|
|
||||||
class CTexture;
|
class CTexture;
|
||||||
|
class CTerrain;
|
||||||
|
|
||||||
|
|
||||||
|
// rendering modes
|
||||||
|
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// SSubmission: generalised class representating a submission of objects to renderer
|
// SSubmission: generalised class representating a submission of objects to renderer
|
||||||
@ -63,8 +74,36 @@ struct SVertex2D
|
|||||||
class CRenderer
|
class CRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// various enumerations
|
// various enumerations and renderer related constants
|
||||||
enum ETerrainMode { WIREFRAME, FILL };
|
enum { NumAlphaMaps=14 };
|
||||||
|
|
||||||
|
// stats class - per frame counts of number of draw calls, poly counts etc
|
||||||
|
struct Stats {
|
||||||
|
// set all stats to zero
|
||||||
|
void Reset() { memset(this,0,sizeof(*this)); }
|
||||||
|
// add given stats to this stats
|
||||||
|
Stats& operator+=(const Stats& rhs) {
|
||||||
|
m_Counter++;
|
||||||
|
m_DrawCalls+=rhs.m_DrawCalls;
|
||||||
|
m_TerrainTris+=rhs.m_TerrainTris;
|
||||||
|
m_ModelTris+=rhs.m_ModelTris;
|
||||||
|
m_TransparentTris+=rhs.m_TransparentTris;
|
||||||
|
m_BlendSplats+=rhs.m_BlendSplats;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// count of the number of stats added together
|
||||||
|
u32 m_Counter;
|
||||||
|
// number of draw calls per frame - total DrawElements + Begin/End immediate mode loops
|
||||||
|
u32 m_DrawCalls;
|
||||||
|
// number of terrain triangles drawn
|
||||||
|
u32 m_TerrainTris;
|
||||||
|
// number of (non-transparent) model triangles drawn
|
||||||
|
u32 m_ModelTris;
|
||||||
|
// number of transparent model triangles drawn
|
||||||
|
u32 m_TransparentTris;
|
||||||
|
// number of splat passes for alphamapping
|
||||||
|
u32 m_BlendSplats;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor, destructor
|
// constructor, destructor
|
||||||
@ -95,12 +134,11 @@ public:
|
|||||||
// submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond
|
// submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond
|
||||||
// the call to frame end, as must the object itself
|
// the call to frame end, as must the object itself
|
||||||
void Submit(CPatch* patch);
|
void Submit(CPatch* patch);
|
||||||
void Submit(CModel* model,CMatrix3D* transform);
|
void Submit(CVisual* visual);
|
||||||
void Submit(CSprite* sprite,CMatrix3D* transform);
|
void Submit(CSprite* sprite,CMatrix3D* transform);
|
||||||
void Submit(CParticleSys* psys,CMatrix3D* transform);
|
void Submit(CParticleSys* psys,CMatrix3D* transform);
|
||||||
void Submit(COverlay* overlay);
|
void Submit(COverlay* overlay);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in
|
// basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in
|
||||||
// editor tools (eg for highlighting specific terrain patches)
|
// editor tools (eg for highlighting specific terrain patches)
|
||||||
// note:
|
// note:
|
||||||
@ -115,30 +153,53 @@ public:
|
|||||||
void RenderLineLoop(int len,const SVertex3D* vertices);
|
void RenderLineLoop(int len,const SVertex3D* vertices);
|
||||||
void RenderTri(const SVertex3D* vertices);
|
void RenderTri(const SVertex3D* vertices);
|
||||||
void RenderQuad(const SVertex3D* vertices);
|
void RenderQuad(const SVertex3D* vertices);
|
||||||
#endif
|
|
||||||
|
|
||||||
// set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer,
|
// set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer,
|
||||||
// so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering)
|
// so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering)
|
||||||
void SetLightEnv(CLightEnv* lightenv);
|
void SetLightEnv(CLightEnv* lightenv) {
|
||||||
|
m_LightEnv=lightenv;
|
||||||
|
}
|
||||||
|
|
||||||
// set the mode to render subsequent terrain patches
|
// set the mode to render subsequent terrain patches
|
||||||
void SetTerrainMode(ETerrainMode mode) { m_TerrainMode=mode; }
|
void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; }
|
||||||
// get the mode to render subsequent terrain patches
|
// get the mode to render subsequent terrain patches
|
||||||
ETerrainMode GetTerrainMode() const { return m_TerrainMode; }
|
ERenderMode GetTerrainRenderMode() const { return m_TerrainRenderMode; }
|
||||||
|
|
||||||
|
// set the mode to render subsequent models
|
||||||
|
void SetModelRenderMode(ERenderMode mode) { m_ModelRenderMode=mode; }
|
||||||
|
// get the mode to render subsequent models
|
||||||
|
ERenderMode GetModelRenderMode() const { return m_ModelRenderMode; }
|
||||||
|
|
||||||
// try and load the given texture
|
// try and load the given texture
|
||||||
bool LoadTexture(CTexture* texture);
|
bool LoadTexture(CTexture* texture);
|
||||||
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
||||||
// note - active texture always set to given unit on exit
|
// note - active texture always set to given unit on exit
|
||||||
void SetTexture(int unit,CTexture* texture);
|
void SetTexture(int unit,CTexture* texture,u32 wrapflags=0);
|
||||||
|
// query transparency of given texture
|
||||||
|
bool IsTextureTransparent(CTexture* texture);
|
||||||
|
|
||||||
|
// load the default set of alphamaps; return false if any alphamap fails to load, true otherwise
|
||||||
|
bool LoadAlphaMaps(const char* fnames[]);
|
||||||
|
|
||||||
|
// return stats accumulated for current frame
|
||||||
|
const Stats& GetStats() { return m_Stats; }
|
||||||
|
|
||||||
|
inline int GetWidth() const { return m_Width; }
|
||||||
|
inline int GetHeight() const { return m_Height; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class CPatchRData;
|
||||||
|
friend class CModelRData;
|
||||||
|
friend class CTransparencyRenderer;
|
||||||
|
|
||||||
// patch rendering stuff
|
// patch rendering stuff
|
||||||
void RenderPatchBase(CPatch* patch);
|
void RenderPatchSubmissions();
|
||||||
void RenderPatchTrans(CPatch* patch);
|
void RenderPatches();
|
||||||
|
|
||||||
// model rendering stuff
|
// model rendering stuff
|
||||||
void RenderModel(SSubmission<CModel*>& modelsub);
|
void BuildTransparentPasses(CVisual* visual);
|
||||||
|
void RenderModelSubmissions();
|
||||||
|
void RenderModels();
|
||||||
|
|
||||||
// RENDERER DATA:
|
// RENDERER DATA:
|
||||||
// view width
|
// view width
|
||||||
@ -150,15 +211,40 @@ protected:
|
|||||||
// frame counter
|
// frame counter
|
||||||
int m_FrameCounter;
|
int m_FrameCounter;
|
||||||
// current terrain rendering mode
|
// current terrain rendering mode
|
||||||
ETerrainMode m_TerrainMode;
|
ERenderMode m_TerrainRenderMode;
|
||||||
|
// current model rendering mode
|
||||||
|
ERenderMode m_ModelRenderMode;
|
||||||
|
// current view camera
|
||||||
|
CCamera m_Camera;
|
||||||
// submitted object lists for batching
|
// submitted object lists for batching
|
||||||
std::vector<SSubmission<CPatch*> > m_TerrainPatches;
|
std::vector<SSubmission<CPatch*> > m_TerrainPatches;
|
||||||
std::vector<SSubmission<CModel*> > m_Models;
|
std::vector<SSubmission<CVisual*> > m_Models;
|
||||||
std::vector<SSubmission<CSprite*> > m_Sprites;
|
std::vector<SSubmission<CSprite*> > m_Sprites;
|
||||||
std::vector<SSubmission<CParticleSys*> > m_ParticleSyses;
|
std::vector<SSubmission<CParticleSys*> > m_ParticleSyses;
|
||||||
std::vector<SSubmission<COverlay*> > m_Overlays;
|
std::vector<SSubmission<COverlay*> > m_Overlays;
|
||||||
// current lighting setup
|
// current lighting setup
|
||||||
CLightEnv* m_LightEnv;
|
CLightEnv* m_LightEnv;
|
||||||
|
// current spherical harmonic coefficients (for unit lighting), derived from lightenv
|
||||||
|
CSHCoeffs m_SHCoeffsUnits;
|
||||||
|
// current spherical harmonic coefficients (for terrain lighting), derived from lightenv
|
||||||
|
CSHCoeffs m_SHCoeffsTerrain;
|
||||||
|
// default alpha maps
|
||||||
|
//Handle m_AlphaMaps[NumAlphaMaps];
|
||||||
|
// all the alpha maps packed into one texture
|
||||||
|
unsigned int m_CompositeAlphaMap;
|
||||||
|
// coordinates of each (untransformed) alpha map within the packed texture
|
||||||
|
struct {
|
||||||
|
float u0,u1,v0,v1;
|
||||||
|
} m_AlphaMapCoords[NumAlphaMaps];
|
||||||
|
|
||||||
|
// card capabilities
|
||||||
|
struct Caps {
|
||||||
|
bool m_VBO;
|
||||||
|
} m_Caps;
|
||||||
|
// build card cap bits
|
||||||
|
void EnumCaps();
|
||||||
|
// per-frame renderer stats
|
||||||
|
Stats m_Stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
#include "SHCoeffs.h"
|
#include "SHCoeffs.h"
|
||||||
|
|
||||||
CSHCoeffs::CSHCoeffs()
|
CSHCoeffs::CSHCoeffs()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSHCoeffs::Clear()
|
||||||
{
|
{
|
||||||
for (int i=0;i<9;i++) {
|
for (int i=0;i<9;i++) {
|
||||||
_data[i].Clear();
|
_data[i].Clear();
|
||||||
@ -45,7 +50,7 @@ void CSHCoeffs::AddDirectionalLight(const CVector3D& lightDir,const RGBColor& li
|
|||||||
_data[8]+=lightColor*c5*(SQR(dirToLight.X)-SQR(dirToLight.Y));
|
_data[8]+=lightColor*c5*(SQR(dirToLight.X)-SQR(dirToLight.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color)
|
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color) const
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
color=_data[0];
|
color=_data[0];
|
||||||
|
@ -19,10 +19,12 @@ class CSHCoeffs
|
|||||||
public:
|
public:
|
||||||
CSHCoeffs();
|
CSHCoeffs();
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
void AddAmbientLight(const RGBColor& color);
|
void AddAmbientLight(const RGBColor& color);
|
||||||
void AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor);
|
void AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor);
|
||||||
|
|
||||||
void Evaluate(const CVector3D& normal,RGBColor& color);
|
void Evaluate(const CVector3D& normal,RGBColor& color) const;
|
||||||
|
|
||||||
const RGBColor* GetCoefficients() const { return _data; }
|
const RGBColor* GetCoefficients() const { return _data; }
|
||||||
|
|
||||||
|
@ -12,18 +12,9 @@
|
|||||||
#ifndef TERRGLOBALS_H
|
#ifndef TERRGLOBALS_H
|
||||||
#define TERRGLOBALS_H
|
#define TERRGLOBALS_H
|
||||||
|
|
||||||
const int PATCH_SIZE = 16;
|
const int PATCH_SIZE = 16;
|
||||||
const int CELL_SIZE = 4; //horizontal scale of the patches
|
const int CELL_SIZE = 4; //horizontal scale of the patches
|
||||||
const float HEIGHT_SCALE = 0.35f;
|
const float HEIGHT_SCALE = 0.35f/256.0f;
|
||||||
|
|
||||||
//only 3x3 patches loaded at a time
|
|
||||||
const int NUM_PATCHES_PER_SIDE = 20;
|
|
||||||
|
|
||||||
//must be odd number of patches
|
|
||||||
//#define TERRAIN_CHUNK_SIZE (PATCH_SIZE*NUM_PATCHES_PER_SIDE)
|
|
||||||
const int MAP_SIZE = ( (NUM_PATCHES_PER_SIDE*PATCH_SIZE)+1 );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,182 +14,267 @@
|
|||||||
//
|
//
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
|
|
||||||
|
#include "res/tex.h"
|
||||||
|
#include "res/mem.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "Terrain.h"
|
#include "Terrain.h"
|
||||||
#include "LightEnv.h"
|
|
||||||
#include "SHCoeffs.h"
|
|
||||||
|
|
||||||
bool g_HillShading = true;
|
|
||||||
|
|
||||||
CVector3D SeasonLight[2];
|
CTerrain::CTerrain()
|
||||||
float SeasonColor[2][3];
|
|
||||||
|
|
||||||
CTerrain::CTerrain ()
|
|
||||||
{
|
{
|
||||||
m_pVertices = NULL;
|
m_Heightmap = NULL;
|
||||||
|
m_Patches = NULL;
|
||||||
|
m_MapSize = 0;
|
||||||
|
m_MapSizePatches = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTerrain::~CTerrain ()
|
CTerrain::~CTerrain()
|
||||||
{
|
{
|
||||||
delete [] m_pVertices;
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTerrain::Load(char *filename)
|
|
||||||
{
|
|
||||||
Handle ht = tex_load(filename);
|
|
||||||
if(!ht)
|
|
||||||
return false;
|
|
||||||
void* p;
|
|
||||||
tex_info(ht, 0, 0, &p);
|
|
||||||
|
|
||||||
return InitFromHeightmap((const u8*)p);
|
void CTerrain::Reset()
|
||||||
|
{
|
||||||
|
delete[] m_Heightmap;
|
||||||
|
delete[] m_Patches;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTerrain::InitFromHeightmap(const u8* data)
|
|
||||||
|
bool CTerrain::Initialize(u32 size,const u16* data)
|
||||||
{
|
{
|
||||||
int j;
|
// clean up any previous terrain
|
||||||
|
Reset();
|
||||||
|
|
||||||
delete[] m_pVertices;
|
// store terrain size
|
||||||
|
m_MapSize=(size*PATCH_SIZE)+1;
|
||||||
|
m_MapSizePatches=size;
|
||||||
|
|
||||||
m_pVertices = new STerrainVertex[MAP_SIZE*MAP_SIZE];
|
// allocate data for new terrain
|
||||||
if (m_pVertices == NULL)
|
m_Heightmap=new u16[m_MapSize*m_MapSize];
|
||||||
return false;
|
m_Patches=new CPatch[m_MapSizePatches*m_MapSizePatches];
|
||||||
|
|
||||||
for (j=0; j<MAP_SIZE; j++)
|
// given a heightmap?
|
||||||
{
|
if (data) {
|
||||||
for (int i=0; i<MAP_SIZE; i++)
|
// yes; keep a copy of it
|
||||||
{
|
memcpy(m_Heightmap,data,m_MapSize*m_MapSize*sizeof(u16));
|
||||||
int pos = j*MAP_SIZE + i;
|
} else {
|
||||||
|
// build a flat terrain
|
||||||
m_pVertices[pos].m_Position.X = ((float)i)*CELL_SIZE;
|
memset(m_Heightmap,0,m_MapSize*m_MapSize*sizeof(u16));
|
||||||
m_pVertices[pos].m_Position.Y = (*data++)*HEIGHT_SCALE;
|
|
||||||
m_pVertices[pos].m_Position.Z = ((float)j)*CELL_SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j=0; j<NUM_PATCHES_PER_SIDE; j++)
|
// setup patch parents, indices etc
|
||||||
{
|
InitialisePatches();
|
||||||
for (int i=0; i<NUM_PATCHES_PER_SIDE; i++)
|
|
||||||
{
|
|
||||||
int pos = j*MAP_SIZE*PATCH_SIZE;
|
|
||||||
pos += i*PATCH_SIZE;
|
|
||||||
|
|
||||||
m_Patches[j][i].Initialize ( &(m_pVertices[pos]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CalcNormals();
|
|
||||||
SetNeighbors();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTerrain::CalcLighting(const CLightEnv& lightEnv)
|
void CTerrain::CalcPosition(u32 i,u32 j,CVector3D& pos)
|
||||||
{
|
{
|
||||||
CSHCoeffs coeffs;
|
u16 height=m_Heightmap[j*m_MapSize + i];
|
||||||
coeffs.AddAmbientLight(lightEnv.m_TerrainAmbientColor);
|
pos.X = float(i)*CELL_SIZE;
|
||||||
|
pos.Y = float(height)*HEIGHT_SCALE;
|
||||||
CVector3D dirlight;
|
pos.Z = float(j)*CELL_SIZE;
|
||||||
lightEnv.GetSunDirection(dirlight);
|
|
||||||
coeffs.AddDirectionalLight(dirlight,lightEnv.m_SunColor);
|
|
||||||
|
|
||||||
for (int k=0;k<MAP_SIZE*MAP_SIZE;++k) {
|
|
||||||
coeffs.Evaluate(m_pVertices[k].m_Normal,m_pVertices[k].m_Color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTerrain::CalcNormals()
|
|
||||||
{
|
void CTerrain::CalcNormal(u32 i,u32 j,CVector3D& normal)
|
||||||
CVector3D left, right, up, down, n[4];
|
{
|
||||||
|
CVector3D left, right, up, down;
|
||||||
|
|
||||||
for (int j=0; j<MAP_SIZE; j++)
|
left.Clear();
|
||||||
{
|
right.Clear();
|
||||||
for (int i=0; i<MAP_SIZE; i++)
|
up.Clear();
|
||||||
{
|
down.Clear();
|
||||||
left.Clear();
|
|
||||||
right.Clear();
|
// get position of vertex where normal is being evaluated
|
||||||
up.Clear();
|
CVector3D basepos;
|
||||||
down.Clear();
|
CalcPosition(i,j,basepos);
|
||||||
|
|
||||||
if (i>0)
|
|
||||||
left = m_pVertices[j*MAP_SIZE + i - 1].m_Position -
|
|
||||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
|
||||||
|
|
||||||
if (i<MAP_SIZE-1)
|
CVector3D tmp;
|
||||||
right = m_pVertices[j*MAP_SIZE + i + 1].m_Position -
|
if (i>0) {
|
||||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
CalcPosition(i-1,j,tmp);
|
||||||
|
left=tmp-basepos;
|
||||||
|
}
|
||||||
|
|
||||||
if (j>0)
|
if (i<m_MapSize-1) {
|
||||||
up = m_pVertices[(j-1)*MAP_SIZE + i].m_Position -
|
CalcPosition(i+1,j,tmp);
|
||||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
right=tmp-basepos;
|
||||||
|
}
|
||||||
|
|
||||||
if (j<MAP_SIZE-1)
|
if (j>0) {
|
||||||
down = m_pVertices[(j+1)*MAP_SIZE + i].m_Position -
|
CalcPosition(i,j-1,tmp);
|
||||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
up=tmp-basepos;
|
||||||
|
}
|
||||||
|
|
||||||
n[0] = up.Cross(left);
|
if (j<m_MapSize-1) {
|
||||||
n[1] = left.Cross(down);
|
CalcPosition(i,j+1,tmp);
|
||||||
n[2] = down.Cross(right);
|
down=tmp-basepos;
|
||||||
n[3] = right.Cross(up);
|
}
|
||||||
|
|
||||||
float n0len=n[0].GetLength();
|
CVector3D n0 = up.Cross(left);
|
||||||
if (n0len>0.0001f) n[0]*=1.0f/n0len;
|
CVector3D n1 = left.Cross(down);
|
||||||
|
CVector3D n2 = down.Cross(right);
|
||||||
|
CVector3D n3 = right.Cross(up);
|
||||||
|
|
||||||
float n1len=n[1].GetLength();
|
normal = n0 + n1 + n2 + n3;
|
||||||
if (n1len>0.0001f) n[1]*=1.0f/n1len;
|
float nlen=normal.GetLength();
|
||||||
|
if (nlen>0.00001f) normal*=1.0f/nlen;
|
||||||
|
}
|
||||||
|
|
||||||
float n2len=n[2].GetLength();
|
|
||||||
if (n2len>0.0001f) n[2]*=1.0f/n2len;
|
|
||||||
|
|
||||||
float n3len=n[3].GetLength();
|
CPatch* CTerrain::GetPatch(int32 x,int32 z)
|
||||||
if (n3len>0.0001f) n[3]*=1.0f/n3len;
|
{
|
||||||
|
if (x<0 || x>=int32(m_MapSizePatches)) return 0;
|
||||||
|
if (z<0 || z>=int32(m_MapSizePatches)) return 0;
|
||||||
|
return &m_Patches[(z*m_MapSizePatches)+x];
|
||||||
|
}
|
||||||
|
|
||||||
CVector3D Normal = n[0] + n[1] + n[2] + n[3];
|
CMiniPatch* CTerrain::GetTile(int32 x,int32 z)
|
||||||
float nlen=Normal.GetLength();
|
{
|
||||||
if (nlen>0.00001f) Normal*=1.0f/nlen;
|
if (x<0 || x>=int32(m_MapSize)-1) return 0;
|
||||||
|
if (z<0 || z>=int32(m_MapSize)-1) return 0;
|
||||||
m_pVertices[j*MAP_SIZE + i].m_Normal=Normal;
|
|
||||||
|
CPatch* patch=GetPatch(x/16,z/16);
|
||||||
|
return &patch->m_MiniPatches[z%16][x%16];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CTerrain::Resize(u32 size)
|
||||||
|
{
|
||||||
|
if (size==m_MapSizePatches) {
|
||||||
|
// inexplicable request to resize terrain to the same size .. ignore it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_Heightmap) {
|
||||||
|
// not yet created a terrain; build a default terrain of the given size now
|
||||||
|
Initialize(size,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate data for new terrain
|
||||||
|
u32 newMapSize=(size*PATCH_SIZE)+1;
|
||||||
|
u16* newHeightmap=new u16[newMapSize*newMapSize];
|
||||||
|
CPatch* newPatches=new CPatch[size*size];
|
||||||
|
|
||||||
|
if (size>m_MapSizePatches) {
|
||||||
|
// new map is bigger than old one - zero the heightmap so we don't get uninitialised
|
||||||
|
// height data along the expanded edges
|
||||||
|
memset(newHeightmap,0,newMapSize*newMapSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now copy over rows of data
|
||||||
|
u32 j;
|
||||||
|
u16* src=m_Heightmap;
|
||||||
|
u16* dst=newHeightmap;
|
||||||
|
u32 copysize=newMapSize>m_MapSize ? m_MapSize : newMapSize;
|
||||||
|
for (j=0;j<copysize;j++) {
|
||||||
|
memcpy(dst,src,copysize*sizeof(u16));
|
||||||
|
dst+=copysize;
|
||||||
|
src+=m_MapSize;
|
||||||
|
if (newMapSize>m_MapSize) {
|
||||||
|
// entend the last height to the end of the row
|
||||||
|
for (u32 i=0;i<newMapSize-m_MapSize;i++) {
|
||||||
|
*dst++=*(src-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (newMapSize>m_MapSize) {
|
||||||
|
// copy over heights of the last row to any remaining rows
|
||||||
|
src=newHeightmap+((m_MapSize-1)*newMapSize);
|
||||||
|
dst=src+newMapSize;
|
||||||
|
for (u32 i=0;i<newMapSize-m_MapSize;i++) {
|
||||||
|
memcpy(dst,src,newMapSize*sizeof(u16));
|
||||||
|
dst+=newMapSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CTerrain::SetNeighbors ()
|
// now build new patches
|
||||||
{
|
for (j=0;j<size;j++) {
|
||||||
CPatch *ThisPatch, *RightPatch;
|
for (u32 i=0;i<size;i++) {
|
||||||
|
// copy over texture data from existing tiles, if possible
|
||||||
|
if (i<m_MapSizePatches && j<m_MapSizePatches) {
|
||||||
|
memcpy(newPatches[j*size+i].m_MiniPatches,m_Patches[j*m_MapSizePatches+i].m_MiniPatches,sizeof(CMiniPatch)*16*16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int pj=0; pj<NUM_PATCHES_PER_SIDE; pj++)
|
if (j<m_MapSizePatches && size>m_MapSizePatches) {
|
||||||
{
|
// copy over the last tile from each column
|
||||||
for (int pi=0; pi<NUM_PATCHES_PER_SIDE; pi++)
|
for (u32 n=0;n<size-m_MapSizePatches;n++) {
|
||||||
{
|
for (int m=0;m<16;m++) {
|
||||||
ThisPatch = &m_Patches[pj][pi];
|
CMiniPatch& src=m_Patches[j*m_MapSizePatches+m_MapSizePatches-1].m_MiniPatches[m][15];
|
||||||
|
for (int k=0;k<16;k++) {
|
||||||
if (pi < NUM_PATCHES_PER_SIDE-1)
|
CMiniPatch& dst=newPatches[j*size+m_MapSizePatches+n].m_MiniPatches[m][k];
|
||||||
RightPatch = &m_Patches[pj][pi+1];
|
dst.Tex1=src.Tex1;
|
||||||
else
|
dst.Tex1Priority=src.Tex1Priority;
|
||||||
RightPatch = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
for (int tj=0; tj<16; tj++)
|
|
||||||
{
|
|
||||||
for (int ti=0; ti<16; ti++)
|
|
||||||
{
|
|
||||||
CMiniPatch *MPatch = &ThisPatch->m_MiniPatches[tj][ti];
|
|
||||||
|
|
||||||
MPatch->m_pParrent = ThisPatch;
|
|
||||||
|
|
||||||
if (ti < 15)
|
|
||||||
MPatch->m_pRightNeighbor = &ThisPatch->m_MiniPatches[tj][ti+1];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (RightPatch)
|
|
||||||
MPatch->m_pRightNeighbor = &RightPatch->m_MiniPatches[tj][0];
|
|
||||||
else
|
|
||||||
MPatch->m_pRightNeighbor = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size>m_MapSizePatches) {
|
||||||
|
// copy over the last tile from each column
|
||||||
|
CPatch* srcpatch=&newPatches[(m_MapSizePatches-1)*size];
|
||||||
|
CPatch* dstpatch=srcpatch+size;
|
||||||
|
for (u32 p=0;p<size-m_MapSizePatches;p++) {
|
||||||
|
for (u32 n=0;n<size;n++) {
|
||||||
|
for (int m=0;m<16;m++) {
|
||||||
|
for (int k=0;k<16;k++) {
|
||||||
|
CMiniPatch& src=srcpatch->m_MiniPatches[15][k];
|
||||||
|
CMiniPatch& dst=dstpatch->m_MiniPatches[m][k];
|
||||||
|
dst.Tex1=src.Tex1;
|
||||||
|
dst.Tex1Priority=src.Tex1Priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srcpatch++;
|
||||||
|
dstpatch++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// release all the original data
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
// store new data
|
||||||
|
m_Heightmap=newHeightmap;
|
||||||
|
m_Patches=newPatches;
|
||||||
|
m_MapSize=newMapSize;
|
||||||
|
m_MapSizePatches=size;
|
||||||
|
|
||||||
|
// initialise all the new patches
|
||||||
|
InitialisePatches();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTerrain::InitialisePatches()
|
||||||
|
{
|
||||||
|
for (u32 j=0;j<m_MapSizePatches;j++) {
|
||||||
|
for (u32 i=0;i<m_MapSizePatches;i++) {
|
||||||
|
CPatch* patch=GetPatch(i,j);
|
||||||
|
patch->Initialize(this,i,j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeightMap: set up a new heightmap from 16-bit source data;
|
||||||
|
// assumes heightmap matches current terrain size
|
||||||
|
void CTerrain::SetHeightMap(u16* heightmap)
|
||||||
|
{
|
||||||
|
// keep a copy of the given heightmap
|
||||||
|
memcpy(m_Heightmap,heightmap,m_MapSize*m_MapSize*sizeof(u16));
|
||||||
|
|
||||||
|
// recalculate patch bounds, invalidate vertices
|
||||||
|
for (u32 j=0;j<m_MapSizePatches;j++) {
|
||||||
|
for (u32 i=0;i<m_MapSizePatches;i++) {
|
||||||
|
CPatch* patch=GetPatch(i,j);
|
||||||
|
patch->CalcBounds();
|
||||||
|
if (patch->m_RenderData) patch->m_RenderData->m_UpdateFlags|=RENDERDATA_UPDATE_VERTICES;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,34 +17,62 @@
|
|||||||
#ifndef TERRAIN_H
|
#ifndef TERRAIN_H
|
||||||
#define TERRAIN_H
|
#define TERRAIN_H
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "Patch.h"
|
#include "Patch.h"
|
||||||
#include "Vector3D.h"
|
#include "Vector3D.h"
|
||||||
|
#include "TerrGlobals.h"
|
||||||
|
|
||||||
class CLightEnv;
|
class CLightEnv;
|
||||||
|
class CSHCoeffs;
|
||||||
|
|
||||||
extern bool g_HillShading;
|
|
||||||
|
|
||||||
class CTerrain
|
class CTerrain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CTerrain ();
|
CTerrain();
|
||||||
~CTerrain ();
|
~CTerrain();
|
||||||
|
|
||||||
bool Load(char *filename);
|
bool Initialize(u32 size,const u16* ptr);
|
||||||
bool InitFromHeightmap(const u8* data);
|
|
||||||
|
|
||||||
// protected:
|
// return number of vertices along edge of the terrain
|
||||||
//the patches currently loaded
|
u32 GetVerticesPerSide() { return m_MapSize; }
|
||||||
CPatch m_Patches[NUM_PATCHES_PER_SIDE][NUM_PATCHES_PER_SIDE];
|
// return number of patches along edge of the terrain
|
||||||
STerrainVertex *m_pVertices;
|
u32 GetPatchesPerSide() { return m_MapSizePatches; }
|
||||||
|
|
||||||
|
// resize this terrain such that each side has given number of patches
|
||||||
|
void Resize(u32 size);
|
||||||
|
|
||||||
|
// set up a new heightmap from 16 bit data; assumes heightmap matches current terrain size
|
||||||
|
void SetHeightMap(u16* heightmap);
|
||||||
|
// return a pointer to the heightmap
|
||||||
|
u16* GetHeightMap() const { return m_Heightmap; }
|
||||||
|
|
||||||
|
// get patch at given coordinates, expressed in patch-space; return 0 if
|
||||||
|
// coordinates represent patch off the edge of the map
|
||||||
|
CPatch* GetPatch(int32 x,int32 z);
|
||||||
|
// get tile at given coordinates, expressed in tile-space; return 0 if
|
||||||
|
// coordinates represent tile off the edge of the map
|
||||||
|
CMiniPatch* GetTile(int32 x,int32 z);
|
||||||
|
|
||||||
|
// calculate the position of a given vertex
|
||||||
|
void CalcPosition(u32 i,u32 j,CVector3D& pos);
|
||||||
|
// calculate the normal at a given vertex
|
||||||
|
void CalcNormal(u32 i,u32 j,CVector3D& normal);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// clean up terrain data
|
||||||
|
void Reset();
|
||||||
|
// setup patch pointers etc
|
||||||
|
void InitialisePatches();
|
||||||
|
|
||||||
|
// size of this map in each direction, in vertices; ie. total tiles = sqr(m_MapSize-1)
|
||||||
|
u32 m_MapSize;
|
||||||
|
// size of this map in each direction, in patches; total patches = sqr(m_MapSizePatches)
|
||||||
|
u32 m_MapSizePatches;
|
||||||
|
// the patches comprising this terrain
|
||||||
|
CPatch* m_Patches;
|
||||||
|
// 16-bit heightmap data
|
||||||
|
u16* m_Heightmap;
|
||||||
|
|
||||||
// protected:
|
|
||||||
void CalcNormals();
|
|
||||||
void CalcLighting(const CLightEnv& env);
|
|
||||||
void SetNeighbors();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,7 +80,7 @@ CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
|
|||||||
{
|
{
|
||||||
assert(type<m_TerrainTextures.size());
|
assert(type<m_TerrainTextures.size());
|
||||||
|
|
||||||
CStr pathname("terrains/textures/");
|
CStr pathname("art/textures/terrain/types/");
|
||||||
pathname+=m_TerrainTextures[type].m_Name;
|
pathname+=m_TerrainTextures[type].m_Name;
|
||||||
pathname+='/';
|
pathname+='/';
|
||||||
pathname+=filename;
|
pathname+=filename;
|
||||||
@ -151,7 +151,7 @@ void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext)
|
|||||||
long handle;
|
long handle;
|
||||||
|
|
||||||
// build pathname
|
// build pathname
|
||||||
CStr pathname("terrains\\textures\\");
|
CStr pathname("mods\\official\\art\\textures\\terrain\\types\\");
|
||||||
pathname+=m_TerrainTextures[terraintype].m_Name;
|
pathname+=m_TerrainTextures[terraintype].m_Name;
|
||||||
pathname+="\\";
|
pathname+="\\";
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ void CTextureManager::BuildTerrainTypes()
|
|||||||
long handle;
|
long handle;
|
||||||
|
|
||||||
// Find first matching directory in terrain\textures
|
// Find first matching directory in terrain\textures
|
||||||
if ((handle=_findfirst("terrains\\textures\\*",&file))!=-1) {
|
if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) {
|
||||||
|
|
||||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.' && file.name[0]!='_') {
|
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.' && file.name[0]!='_') {
|
||||||
AddTextureType(file.name);
|
AddTextureType(file.name);
|
||||||
|
@ -59,4 +59,4 @@ class CVector3D;
|
|||||||
class CWorld;
|
class CWorld;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
#include "Matrix3D.h"
|
#include "Matrix3D.h"
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "Terrain.h"
|
#include "Terrain.h"
|
||||||
#include "Camera.h"
|
|
||||||
#include "LightEnv.h"
|
#include "LightEnv.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
#include "Prometheus.h"
|
#include "Prometheus.h"
|
||||||
|
|
||||||
#include "detect.h"
|
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "sdl.h"
|
#include "sdl.h"
|
||||||
#include "res/res.h"
|
#include "res/tex.h"
|
||||||
|
#include "detect.h"
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
// TODO: fix scrolling hack - framerate independent, use SDL
|
// TODO: fix scrolling hack - framerate independent, use SDL
|
||||||
//#include "win.h" // REMOVEME
|
//#include "win.h" // REMOVEME
|
||||||
@ -37,15 +39,8 @@ double g_LastTime;
|
|||||||
|
|
||||||
const int NUM_ALPHA_MAPS = 13;
|
const int NUM_ALPHA_MAPS = 13;
|
||||||
|
|
||||||
//CTexture g_BaseTexture[5];
|
|
||||||
Handle BaseTexs[5];
|
|
||||||
|
|
||||||
Handle AlphaMaps[NUM_ALPHA_MAPS];
|
|
||||||
//CTexture g_TransitionTexture[NUM_ALPHA_MAPS];
|
|
||||||
|
|
||||||
int mouse_x=50, mouse_y=50;
|
int mouse_x=50, mouse_y=50;
|
||||||
|
|
||||||
|
|
||||||
void terr_init()
|
void terr_init()
|
||||||
{
|
{
|
||||||
int xres,yres;
|
int xres,yres;
|
||||||
@ -69,10 +64,10 @@ void terr_update()
|
|||||||
g_Renderer.BeginFrame();
|
g_Renderer.BeginFrame();
|
||||||
g_Renderer.SetCamera(g_Camera);
|
g_Renderer.SetCamera(g_Camera);
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
// switch on wireframe for terrain if we want it
|
||||||
/*POINT MousePos;
|
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||||
|
|
||||||
GetCursorPos (&MousePos);*/
|
/////////////////////////////////////////////
|
||||||
CVector3D right(1,0,1);
|
CVector3D right(1,0,1);
|
||||||
CVector3D up(1,0,-1);
|
CVector3D up(1,0,-1);
|
||||||
right.Normalize ();
|
right.Normalize ();
|
||||||
@ -106,22 +101,21 @@ void terr_update()
|
|||||||
CFrustum frustum=g_Camera.GetFustum();
|
CFrustum frustum=g_Camera.GetFustum();
|
||||||
|
|
||||||
// iterate through patches; cull everything not visible
|
// iterate through patches; cull everything not visible
|
||||||
for (int j=0; j<NUM_PATCHES_PER_SIDE; j++)
|
for (uint j=0; j<g_Terrain.GetPatchesPerSide(); j++)
|
||||||
{
|
{
|
||||||
for (int i=0; i<NUM_PATCHES_PER_SIDE; i++)
|
for (uint i=0; i<g_Terrain.GetPatchesPerSide(); i++)
|
||||||
{
|
{
|
||||||
if (frustum.IsBoxVisible (CVector3D(0,0,0),g_Terrain.m_Patches[j][i].m_Bounds)) {
|
if (frustum.IsBoxVisible (CVector3D(0,0,0),g_Terrain.GetPatch(j, i)->GetBounds())) {
|
||||||
g_Renderer.Submit(&g_Terrain.m_Patches[j][i]);
|
g_Renderer.Submit(g_Terrain.GetPatch(j, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush the frame to force terrain to be renderered before overlays
|
// flush the frame to force terrain to be renderered before overlays
|
||||||
g_Renderer.FlushFrame();
|
g_Renderer.FlushFrame();
|
||||||
|
|
||||||
// g_Renderer.RenderTileOutline (&(g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]));
|
// g_Renderer.RenderTileOutline (&(g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]));
|
||||||
|
|
||||||
// mark end of frame
|
|
||||||
g_Renderer.EndFrame();
|
g_Renderer.EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,11 +136,11 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
switch(ev.key.keysym.sym)
|
switch(ev.key.keysym.sym)
|
||||||
{
|
{
|
||||||
case 'W':
|
case 'W':
|
||||||
if (g_Renderer.GetTerrainMode()==CRenderer::WIREFRAME) {
|
if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) {
|
||||||
g_Renderer.SetTerrainMode(CRenderer::FILL);
|
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||||
} else {
|
} else {
|
||||||
g_Renderer.SetTerrainMode(CRenderer::WIREFRAME);
|
g_Renderer.SetTerrainRenderMode(WIREFRAME);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -158,14 +152,14 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
/* case 'L':
|
||||||
g_HillShading = !g_HillShading;
|
g_HillShading = !g_HillShading;
|
||||||
break;
|
break;*/
|
||||||
|
|
||||||
// tile selection
|
// tile selection
|
||||||
case SDLK_DOWN:
|
case SDLK_DOWN:
|
||||||
if(++SelTX > 15)
|
if(++SelTX > 15)
|
||||||
if(SelPX == NUM_PATCHES_PER_SIDE-1)
|
if(SelPX == g_Terrain.GetPatchesPerSide()-1)
|
||||||
SelTX = 15;
|
SelTX = 15;
|
||||||
else
|
else
|
||||||
SelTX = 0, SelPX++;
|
SelTX = 0, SelPX++;
|
||||||
@ -180,7 +174,7 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
break;
|
break;
|
||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
if(++SelTY > 15)
|
if(++SelTY > 15)
|
||||||
if(SelPY == NUM_PATCHES_PER_SIDE-1)
|
if(SelPY == g_Terrain.GetPatchesPerSide()-1)
|
||||||
SelTY = 15;
|
SelTY = 15;
|
||||||
else
|
else
|
||||||
SelTY = 0, SelPY++;
|
SelTY = 0, SelPY++;
|
||||||
@ -197,8 +191,8 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
|
|
||||||
case SDLK_KP0:
|
case SDLK_KP0:
|
||||||
{
|
{
|
||||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||||
if (!MPatch->Tex2)
|
/*if (!MPatch->Tex2)
|
||||||
{
|
{
|
||||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||||
@ -207,13 +201,13 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
{
|
{
|
||||||
MPatch->Tex2 = 0;
|
MPatch->Tex2 = 0;
|
||||||
MPatch->m_AlphaMap = 0;
|
MPatch->m_AlphaMap = 0;
|
||||||
}
|
}*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDLK_KP1:
|
/*case SDLK_KP1:
|
||||||
{
|
{
|
||||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||||
|
|
||||||
g_BaseTexCounter++;
|
g_BaseTexCounter++;
|
||||||
if (g_BaseTexCounter > 4)
|
if (g_BaseTexCounter > 4)
|
||||||
@ -243,7 +237,7 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
{
|
{
|
||||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||||
|
|
||||||
if (MPatch->/*m_pTransitionTexture*/m_AlphaMap)
|
if (MPatch->m_AlphaMap)
|
||||||
{
|
{
|
||||||
g_TransTexCounter++;
|
g_TransTexCounter++;
|
||||||
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
|
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
|
||||||
@ -253,7 +247,7 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,32 +261,61 @@ bool terr_handler(const SDL_Event& ev)
|
|||||||
void InitScene ()
|
void InitScene ()
|
||||||
{
|
{
|
||||||
// setup default lighting environment
|
// setup default lighting environment
|
||||||
g_LightEnv.m_SunColor=RGBColor(0.75f,0.70f,0.65f);
|
g_LightEnv.m_SunColor=RGBColor(1,1,1);
|
||||||
g_LightEnv.m_Rotation=270;
|
g_LightEnv.m_Rotation=DEGTORAD(270);
|
||||||
g_LightEnv.m_Elevation=DEGTORAD(30);
|
g_LightEnv.m_Elevation=DEGTORAD(45);
|
||||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0.0f,0.0f,0.0f);
|
g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0);
|
||||||
|
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
|
||||||
|
g_Renderer.SetLightEnv(&g_LightEnv);
|
||||||
|
|
||||||
g_Terrain.Load("terrain.raw");
|
// load terrain
|
||||||
|
Handle ht = tex_load("terrain.raw");
|
||||||
for (int pj=0; pj<NUM_PATCHES_PER_SIDE; pj++)
|
if(ht > 0)
|
||||||
{
|
{
|
||||||
for (int pi=0; pi<NUM_PATCHES_PER_SIDE; pi++)
|
const u8* p;
|
||||||
{
|
int w;
|
||||||
for (int tj=0; tj<16; tj++)
|
int h;
|
||||||
{
|
|
||||||
for (int ti=0; ti<16; ti++)
|
tex_info(ht, &w, &h, NULL, NULL, (void **)&p);
|
||||||
{
|
|
||||||
g_Terrain.m_Patches[pj][pi].m_MiniPatches[tj][ti].Tex1 = BaseTexs[0];//rand()%5];
|
printf("terrain.raw: %dx%d\n", w, h);
|
||||||
g_Terrain.m_Patches[pj][pi].m_MiniPatches[tj][ti].Tex2 = NULL;//&g_BaseTexture[rand()%5];
|
|
||||||
g_Terrain.m_Patches[pj][pi].m_MiniPatches[tj][ti].m_AlphaMap = 0;//&g_TransitionTexture[rand()%5];
|
u16 *p16=new u16[w*h];
|
||||||
|
u16 *p16p=p16;
|
||||||
|
while (p16p < p16+(w*h))
|
||||||
|
*p16p++ = (*p++) << 8;
|
||||||
|
|
||||||
|
g_Terrain.Resize(20);
|
||||||
|
g_Terrain.SetHeightMap(p16);
|
||||||
|
|
||||||
|
delete[] p16;
|
||||||
|
|
||||||
|
tex_free(ht);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get default texture to apply to terrain
|
||||||
|
CTextureEntry* texture=0;
|
||||||
|
if (g_TexMan.m_TerrainTextures.size()>0) {
|
||||||
|
if (g_TexMan.m_TerrainTextures[0].m_Textures.size()) {
|
||||||
|
texture=g_TexMan.m_TerrainTextures[0].m_Textures[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cover entire terrain with default texture
|
||||||
|
u32 patchesPerSide=g_Terrain.GetPatchesPerSide();
|
||||||
|
for (uint pj=0; pj<patchesPerSide; pj++) {
|
||||||
|
for (uint pi=0; pi<patchesPerSide; pi++) {
|
||||||
|
|
||||||
|
CPatch* patch=g_Terrain.GetPatch(pi,pj);
|
||||||
|
|
||||||
|
for (int j=0;j<16;j++) {
|
||||||
|
for (int i=0;i<16;i++) {
|
||||||
|
patch->m_MiniPatches[j][i].Tex1=texture ? texture->m_Handle :0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate terrain lighting
|
|
||||||
g_Terrain.CalcLighting(g_LightEnv);
|
|
||||||
|
|
||||||
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
||||||
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||||
@ -304,75 +327,29 @@ void InitScene ()
|
|||||||
|
|
||||||
void InitResources()
|
void InitResources()
|
||||||
{
|
{
|
||||||
int i;
|
#ifndef _WIN32
|
||||||
char* base_fns[] =
|
g_TexMan.AddTextureType("grass");
|
||||||
{
|
g_TexMan.AddTexture("Base1.tga", 0);
|
||||||
"Base1.bmp",
|
|
||||||
"Base2.bmp",
|
|
||||||
"Base3.bmp",
|
|
||||||
"Base4.bmp",
|
|
||||||
"Base5.bmp"
|
|
||||||
};
|
|
||||||
|
|
||||||
for(i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
BaseTexs[i] = tex_load(base_fns[i]);
|
|
||||||
tex_upload(BaseTexs[i], GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int cnt;
|
|
||||||
#if 1
|
|
||||||
|
|
||||||
char* fns[NUM_ALPHA_MAPS] = {
|
|
||||||
"blendcircle.raw",
|
|
||||||
"blendcorner.raw",
|
|
||||||
"blendedge.raw",
|
|
||||||
"blendedgecorner.raw",
|
|
||||||
"blendedgetwocorners.raw",
|
|
||||||
"blendfourcorners.raw",
|
|
||||||
"blendlshape.raw",
|
|
||||||
"blendlshapecorner.raw",
|
|
||||||
"blendthreecorners.raw",
|
|
||||||
"blendtwocorners.raw",
|
|
||||||
"blendtwoedges.raw",
|
|
||||||
"blendtwooppositecorners.raw",
|
|
||||||
"blendushape.raw"
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
//for(i = 0; i < NUM_ALPHA_MAPS;i++)
|
|
||||||
i=5;
|
|
||||||
{
|
|
||||||
FILE* f = fopen(fns[i],"rb");
|
|
||||||
u8 buf[5000],buf2[5000];
|
|
||||||
fread(buf,5000,1,f);
|
|
||||||
fclose(f);
|
|
||||||
for(int j = 0; j < 1024; j++)
|
|
||||||
buf2[2*j] = buf2[2*j+1] = buf[j];
|
|
||||||
f=fopen(fns[i],"wb");
|
|
||||||
fwrite(buf2,2048,1,f);
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
/**/
|
|
||||||
cnt=13;
|
|
||||||
#else
|
#else
|
||||||
|
g_TexMan.LoadTerrainTextures();
|
||||||
char* fns[NUM_ALPHA_MAPS] = {
|
|
||||||
"Transition1.bmp",
|
|
||||||
"Transition2.bmp",
|
|
||||||
"Transition3.bmp",
|
|
||||||
"Transition4.bmp",
|
|
||||||
"Transition5.bmp",
|
|
||||||
};
|
|
||||||
cnt=5;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(i = 0; i < cnt; i++)
|
const char* fns[CRenderer::NumAlphaMaps] = {
|
||||||
{
|
"art/textures/terrain/alphamaps/special/blendcircle.png",
|
||||||
AlphaMaps[i] = tex_load(fns[i]);
|
"art/textures/terrain/alphamaps/special/blendlshape.png",
|
||||||
tex_upload(AlphaMaps[i], GL_LINEAR, GL_INTENSITY4);
|
"art/textures/terrain/alphamaps/special/blendedge.png",
|
||||||
}
|
"art/textures/terrain/alphamaps/special/blendedgecorner.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendedgetwocorners.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendfourcorners.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendtwooppositecorners.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendlshapecorner.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendtwocorners.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendcorner.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendtwoedges.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendthreecorners.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendushape.png",
|
||||||
|
"art/textures/terrain/alphamaps/special/blendbad.png"
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(g_Renderer.LoadAlphaMaps(fns));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user