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
|
||||
#include <assert.h>
|
||||
#include <float.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
|
||||
#include "Vector3D.h"
|
||||
#include "Matrix3D.h"
|
||||
|
||||
class CBound
|
||||
{
|
||||
@ -23,6 +24,8 @@ public:
|
||||
m_Data[0]=min; m_Data[1]=max;
|
||||
}
|
||||
|
||||
void Transform(const CMatrix3D& m,CBound& result) const;
|
||||
|
||||
CVector3D& operator[](int index) { return m_Data[index]; }
|
||||
const CVector3D& operator[](int index) const { return m_Data[index]; }
|
||||
|
||||
|
@ -57,7 +57,7 @@ void CCamera::UpdateFrustum ()
|
||||
CMatrix3D MatFinal;
|
||||
CMatrix3D MatView;
|
||||
|
||||
MatView = m_Orientation.GetTranspose ();
|
||||
m_Orientation.Invert(MatView);
|
||||
|
||||
MatFinal = m_ProjMat * MatView;
|
||||
|
||||
|
@ -12,12 +12,13 @@
|
||||
#ifndef MATHUTIL_H
|
||||
#define MATHUTIL_H
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#define DEGTORAD(a) ((a) * (PI/180.0f))
|
||||
#define RADTODEG(a) ((a) * (180.0f/PI))
|
||||
#define SQR(x) ((x) * (x))
|
||||
|
||||
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
|
||||
#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
|
||||
//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;
|
||||
Temp._21 = _12;
|
||||
Temp._31 = _13;
|
||||
Temp._41 = 0.0f;
|
||||
result._12 = _21;
|
||||
result._22 = _22;
|
||||
result._32 = _23;
|
||||
result._42 = _24;
|
||||
|
||||
Temp._12 = _21;
|
||||
Temp._22 = _22;
|
||||
Temp._32 = _23;
|
||||
Temp._42 = 0.0f;
|
||||
result._13 = _31;
|
||||
result._23 = _32;
|
||||
result._33 = _33;
|
||||
result._43 = _34;
|
||||
|
||||
Temp._13 = _31;
|
||||
Temp._23 = _32;
|
||||
Temp._33 = _33;
|
||||
Temp._43 = 0.0f;
|
||||
|
||||
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;
|
||||
result._14 = _41;
|
||||
result._24 = _42;
|
||||
result._34 = _43;
|
||||
result._44 = _44;
|
||||
}
|
||||
|
||||
//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
|
||||
//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
|
||||
CVector3D GetLeft () const;
|
||||
|
@ -1,22 +1,21 @@
|
||||
#include "MiniPatch.h"
|
||||
#include "Patch.h"
|
||||
|
||||
CMiniPatch::CMiniPatch()
|
||||
{
|
||||
Tex1 = Tex2 = 0;
|
||||
m_AlphaMap = 0;
|
||||
m_pRightNeighbor = NULL;
|
||||
m_pParrent = NULL;
|
||||
m_Rotation = 0;
|
||||
m_RenderStage = 0;
|
||||
m_LastRenderedFrame = 0;
|
||||
Tex1 = 0;
|
||||
Tex1Priority = 0;
|
||||
m_Parent = NULL;
|
||||
}
|
||||
|
||||
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,35 +2,27 @@
|
||||
#define MINIPATCH_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
|
||||
{
|
||||
public:
|
||||
CMiniPatch();
|
||||
~CMiniPatch();
|
||||
public:
|
||||
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, Tex2;
|
||||
Handle m_AlphaMap;
|
||||
CMiniPatch *m_pRightNeighbor;
|
||||
CPatch *m_pParrent;
|
||||
unsigned char m_RenderStage;
|
||||
unsigned int m_LastRenderedFrame;
|
||||
Handle Tex1;
|
||||
int Tex1Priority;
|
||||
|
||||
unsigned char m_Rotation;
|
||||
// Handle Tex2;
|
||||
// Handle m_AlphaMap;
|
||||
// unsigned int m_AlphaMapFlags;
|
||||
|
||||
STerrainVertex *m_pVertices;
|
||||
CPatch *m_Parent;
|
||||
// STerrainVertex *m_pVertices;
|
||||
};
|
||||
|
||||
|
||||
|
@ -11,11 +11,13 @@
|
||||
|
||||
#include "Model.h"
|
||||
#include "Quaternion.h"
|
||||
#include "Bound.h"
|
||||
|
||||
CModel::CModel()
|
||||
{
|
||||
m_pModelDef = NULL;
|
||||
m_pBonePoses = NULL;
|
||||
m_RenderData = 0;
|
||||
}
|
||||
|
||||
CModel::~CModel()
|
||||
@ -126,3 +128,19 @@ void RotateX (CMatrix3D *mat, float angle1, float angle2, float factor)
|
||||
|
||||
*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,6 +14,10 @@
|
||||
|
||||
#include "Texture.h"
|
||||
#include "ModelDef.h"
|
||||
#include "RenderableObject.h"
|
||||
|
||||
|
||||
class CBound;
|
||||
|
||||
class CModel
|
||||
{
|
||||
@ -27,6 +31,10 @@ class CModel
|
||||
void SetPose (const char *anim_name, float time);
|
||||
void ClearPose ();
|
||||
|
||||
void CalcBounds(CBound& bound);
|
||||
|
||||
CRenderData* m_RenderData;
|
||||
|
||||
//access functions
|
||||
public:
|
||||
CModelDef *GetModelDef() { return m_pModelDef; }
|
||||
|
@ -94,16 +94,19 @@ void CModelDef::SetupBones()
|
||||
for (i=0; i<m_NumVertices; 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.Y -= BonePos.Y;
|
||||
pVertex->m_Coords.Z -= BonePos.Z;
|
||||
pVertex->m_Coords.X -= BonePos.X;
|
||||
pVertex->m_Coords.Y -= BonePos.Y;
|
||||
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 GetNumAnimations() { return m_NumAnimations; }
|
||||
|
||||
protected:
|
||||
public:
|
||||
SModelVertex *m_pVertices;
|
||||
SModelFace *m_pFaces;
|
||||
SModelBone *m_pBones;
|
||||
|
@ -11,40 +11,51 @@
|
||||
//***********************************************************
|
||||
|
||||
#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 (STerrainVertex *first_vertex)
|
||||
void CPatch::Initialize(CTerrain* parent,u32 x,u32 z)
|
||||
{
|
||||
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();
|
||||
|
||||
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++)
|
||||
{
|
||||
m_Bounds+=m_pVertices[j*MAP_SIZE + i].m_Position;
|
||||
}
|
||||
}
|
||||
|
||||
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] );
|
||||
CVector3D pos;
|
||||
m_Parent->CalcPosition(m_X*PATCH_SIZE+i,m_Z*PATCH_SIZE+j,pos);
|
||||
m_Bounds+=pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,26 +12,31 @@
|
||||
#ifndef PATCH_H
|
||||
#define PATCH_H
|
||||
|
||||
#include "Bound.h"
|
||||
#include "Matrix3D.h"
|
||||
#include "Camera.h"
|
||||
#include "TerrGlobals.h"
|
||||
#include "MiniPatch.h"
|
||||
#include "RenderableObject.h"
|
||||
|
||||
class CPatch
|
||||
|
||||
class CPatch : public CRenderableObject
|
||||
{
|
||||
public:
|
||||
CPatch ();
|
||||
~CPatch ();
|
||||
public:
|
||||
CPatch();
|
||||
~CPatch();
|
||||
|
||||
//initialize the patch
|
||||
void Initialize (STerrainVertex *first_vertex);
|
||||
//initialize the patch
|
||||
void Initialize(CTerrain* parent,u32 x,u32 z);
|
||||
|
||||
// protected:
|
||||
CMiniPatch m_MiniPatches[16][16];
|
||||
// calculate and store bounds of this patch
|
||||
void CalcBounds();
|
||||
|
||||
CBound m_Bounds;
|
||||
unsigned int m_LastVisFrame;
|
||||
|
||||
STerrainVertex *m_pVertices;
|
||||
// minipatches (tiles) making up the patch
|
||||
CMiniPatch m_MiniPatches[16][16];
|
||||
// position of patch in parent terrain grid
|
||||
u32 m_X,m_Z;
|
||||
// parent terrain
|
||||
CTerrain* m_Parent;
|
||||
};
|
||||
|
||||
|
||||
|
@ -106,7 +106,7 @@ void CPatchRData::BuildBlends()
|
||||
}
|
||||
}
|
||||
if (neighbourTextures.size()>0) {
|
||||
u32 count=neighbourTextures.size();
|
||||
size_t count=neighbourTextures.size();
|
||||
// sort textures from lowest to highest priority
|
||||
std::sort(neighbourTextures.begin(),neighbourTextures.end());
|
||||
|
||||
@ -175,7 +175,7 @@ void CPatchRData::BuildBlends()
|
||||
int vsize=PATCH_SIZE+1;
|
||||
|
||||
SBlendVertex dst;
|
||||
int vindex=m_BlendVertices.size();
|
||||
size_t vindex=m_BlendVertices.size();
|
||||
|
||||
const SBaseVertex& vtx0=m_Vertices[(j*vsize)+i];
|
||||
dst.m_UVs[0]=i*0.125f;
|
||||
|
@ -10,21 +10,90 @@
|
||||
// types - terrain, models, sprites, particles etc
|
||||
//----------------------------------------------------------------
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include "Renderer.h"
|
||||
#include "TransparencyRenderer.h"
|
||||
#include "Terrain.h"
|
||||
#include "Matrix3D.h"
|
||||
#include "Camera.h"
|
||||
#include "PatchRData.h"
|
||||
#include "Texture.h"
|
||||
#include "LightEnv.h"
|
||||
#include "Visual.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelDef.h"
|
||||
|
||||
#include "types.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 ()
|
||||
{
|
||||
@ -32,7 +101,8 @@ CRenderer::CRenderer ()
|
||||
m_Height=0;
|
||||
m_Depth=0;
|
||||
m_FrameCounter=0;
|
||||
m_TerrainMode=FILL;
|
||||
m_TerrainRenderMode=SOLID;
|
||||
m_ModelRenderMode=SOLID;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
m_Depth = depth;
|
||||
|
||||
// set packing parameters
|
||||
glPixelStorei(GL_PACK_ALIGNMENT,1);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
||||
|
||||
// setup default state
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glClearColor(0.0f,0.0f,0.0f,0.0f);
|
||||
|
||||
// query card capabilities
|
||||
EnumCaps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -72,35 +162,199 @@ void CRenderer::BeginFrame()
|
||||
// bump frame counter
|
||||
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
|
||||
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
|
||||
void CRenderer::FlushFrame()
|
||||
{
|
||||
unsigned i;
|
||||
// render submitted patches and models
|
||||
RenderPatches();
|
||||
|
||||
// render base terrain
|
||||
if (m_TerrainMode==WIREFRAME) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
}
|
||||
RenderModels();
|
||||
|
||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||
RenderPatchBase(m_TerrainPatches[i].m_Object);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
// call on the transparency renderer to render all the transparent stuff
|
||||
g_TransparencyRenderer.Render();
|
||||
|
||||
// empty lists
|
||||
m_TerrainPatches.clear();
|
||||
@ -115,7 +369,8 @@ void CRenderer::EndFrame()
|
||||
|
||||
void CRenderer::SetCamera(CCamera& camera)
|
||||
{
|
||||
CMatrix3D view = camera.m_Orientation.GetTranspose();
|
||||
CMatrix3D view;
|
||||
camera.m_Orientation.Invert(view);
|
||||
CMatrix3D proj = camera.GetProjection();
|
||||
|
||||
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();
|
||||
glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height);
|
||||
|
||||
m_Camera=camera;
|
||||
}
|
||||
|
||||
void CRenderer::Submit(CPatch* patch)
|
||||
{
|
||||
SSubmission<CPatch*> sub;
|
||||
patch->m_LastVisFrame=m_FrameCounter;
|
||||
sub.m_Object=patch;
|
||||
m_TerrainPatches.push_back(sub);
|
||||
}
|
||||
|
||||
void CRenderer::Submit(CModel* model,CMatrix3D* transform)
|
||||
void CRenderer::Submit(CVisual* visual)
|
||||
{
|
||||
SSubmission<CModel*> sub;
|
||||
sub.m_Object=model;
|
||||
sub.m_Transform=transform;
|
||||
SSubmission<CVisual*> sub;
|
||||
sub.m_Object=visual;
|
||||
m_Models.push_back(sub);
|
||||
}
|
||||
|
||||
@ -167,74 +422,109 @@ void CRenderer::Submit(COverlay* overlay)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void CRenderer::RenderTileOutline (CMiniPatch *mpatch)
|
||||
void CRenderer::RenderPatchSubmissions()
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glLineWidth (4);
|
||||
|
||||
STerrainVertex V[4];
|
||||
V[0] = mpatch->m_pVertices[0];
|
||||
V[1] = mpatch->m_pVertices[1];
|
||||
V[2] = mpatch->m_pVertices[MAP_SIZE*1 + 1];
|
||||
V[3] = mpatch->m_pVertices[MAP_SIZE*1];
|
||||
|
||||
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);
|
||||
uint i;
|
||||
// first ensure all patches have up to date renderdata built for them
|
||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||
CPatch* patch=m_TerrainPatches[i].m_Object;
|
||||
CPatchRData* data=(CPatchRData*) patch->m_RenderData;
|
||||
if (data==0) {
|
||||
// no renderdata for patch, create it now
|
||||
data=new CPatchRData(patch);
|
||||
} else {
|
||||
data->Update();
|
||||
}
|
||||
}
|
||||
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
|
||||
bool CRenderer::LoadTexture(CTexture* texture)
|
||||
{
|
||||
Handle h=texture->GetHandle();
|
||||
if (h) {
|
||||
// already tried to load this texture, nothing to do here - just return accord to whether this
|
||||
// is a valid handle
|
||||
// already tried to load this texture, nothing to do here - just return success according
|
||||
// to whether this is a valid handle or not
|
||||
return h==0xfffffff ? true : false;
|
||||
} else {
|
||||
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
|
||||
void CRenderer::SetTexture(int unit,CTexture* texture)
|
||||
void CRenderer::SetTexture(int unit,CTexture* texture,u32 wrapflags)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0+unit);
|
||||
if (texture) {
|
||||
@ -258,6 +548,11 @@ void CRenderer::SetTexture(int unit,CTexture* texture)
|
||||
if (!h) {
|
||||
LoadTexture(texture);
|
||||
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
|
||||
@ -273,247 +568,147 @@ void CRenderer::SetTexture(int unit,CTexture* texture)
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::RenderPatchBase (CPatch *patch)
|
||||
bool CRenderer::IsTextureTransparent(CTexture* texture)
|
||||
{
|
||||
CMiniPatch *MPatch, *MPCurrent;
|
||||
|
||||
float StartU, StartV;
|
||||
|
||||
|
||||
for (int j=0; j<16; j++)
|
||||
{
|
||||
for (int i=0; i<16; i++)
|
||||
{
|
||||
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;
|
||||
if (texture) {
|
||||
Handle h=texture->GetHandle();
|
||||
if (!h) {
|
||||
LoadTexture(texture);
|
||||
h=texture->GetHandle();
|
||||
if (h!=0xffffffff) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
float StartU, StartV;
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for (int j=0; j<16; j++)
|
||||
{
|
||||
for (int i=0; i<16; i++)
|
||||
{
|
||||
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);
|
||||
/////////////////////////////////////
|
||||
if ((x & (x-1))==0) return x;
|
||||
int d=x;
|
||||
while (d & (d-1)) {
|
||||
d&=(d-1);
|
||||
}
|
||||
return d<<1;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
inline void CopyTriple(unsigned char* dst,const unsigned char* src)
|
||||
{
|
||||
dst[0]=src[0];
|
||||
dst[1]=src[1];
|
||||
dst[2]=src[2];
|
||||
}
|
||||
|
||||
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);
|
||||
// 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);
|
||||
|
||||
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);
|
||||
/////////////////////////////////////
|
||||
Handle textures[NumAlphaMaps];
|
||||
|
||||
StartU = 0.125f * (float)(i%8);
|
||||
StartV = 0.125f * (float)(j%8);
|
||||
int i;
|
||||
|
||||
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 ();
|
||||
}
|
||||
for (i=0;i<NumAlphaMaps;i++) {
|
||||
textures[i]=tex_load(fnames[i]);
|
||||
if (textures[i] <= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
glDisable (GL_BLEND);
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
|
||||
int base;//=textures[0].width;
|
||||
|
||||
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
|
||||
|
||||
#include <vector>
|
||||
#include "res/res.h"
|
||||
#include "ogl.h"
|
||||
#include "Camera.h"
|
||||
#include "Frustum.h"
|
||||
#include "PatchRData.h"
|
||||
#include "ModelRData.h"
|
||||
#include "SHCoeffs.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
// necessary declarations
|
||||
class CCamera;
|
||||
class CPatch;
|
||||
class CModel;
|
||||
class CVisual;
|
||||
class CSprite;
|
||||
class CParticleSys;
|
||||
class COverlay;
|
||||
class CMaterial;
|
||||
class CLightEnv;
|
||||
class SPatchRData;
|
||||
class CTexture;
|
||||
class CTerrain;
|
||||
|
||||
|
||||
// rendering modes
|
||||
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SSubmission: generalised class representating a submission of objects to renderer
|
||||
@ -63,8 +74,36 @@ struct SVertex2D
|
||||
class CRenderer
|
||||
{
|
||||
public:
|
||||
// various enumerations
|
||||
enum ETerrainMode { WIREFRAME, FILL };
|
||||
// various enumerations and renderer related constants
|
||||
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:
|
||||
// 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
|
||||
// the call to frame end, as must the object itself
|
||||
void Submit(CPatch* patch);
|
||||
void Submit(CModel* model,CMatrix3D* transform);
|
||||
void Submit(CVisual* visual);
|
||||
void Submit(CSprite* sprite,CMatrix3D* transform);
|
||||
void Submit(CParticleSys* psys,CMatrix3D* transform);
|
||||
void Submit(COverlay* overlay);
|
||||
|
||||
#if 0
|
||||
// basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in
|
||||
// editor tools (eg for highlighting specific terrain patches)
|
||||
// note:
|
||||
@ -115,30 +153,53 @@ public:
|
||||
void RenderLineLoop(int len,const SVertex3D* vertices);
|
||||
void RenderTri(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,
|
||||
// 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
|
||||
void SetTerrainMode(ETerrainMode mode) { m_TerrainMode=mode; }
|
||||
void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; }
|
||||
// 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
|
||||
bool LoadTexture(CTexture* texture);
|
||||
// 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
|
||||
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:
|
||||
friend class CPatchRData;
|
||||
friend class CModelRData;
|
||||
friend class CTransparencyRenderer;
|
||||
|
||||
// patch rendering stuff
|
||||
void RenderPatchBase(CPatch* patch);
|
||||
void RenderPatchTrans(CPatch* patch);
|
||||
void RenderPatchSubmissions();
|
||||
void RenderPatches();
|
||||
|
||||
// model rendering stuff
|
||||
void RenderModel(SSubmission<CModel*>& modelsub);
|
||||
void BuildTransparentPasses(CVisual* visual);
|
||||
void RenderModelSubmissions();
|
||||
void RenderModels();
|
||||
|
||||
// RENDERER DATA:
|
||||
// view width
|
||||
@ -150,15 +211,40 @@ protected:
|
||||
// frame counter
|
||||
int m_FrameCounter;
|
||||
// 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
|
||||
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<CParticleSys*> > m_ParticleSyses;
|
||||
std::vector<SSubmission<COverlay*> > m_Overlays;
|
||||
// current lighting setup
|
||||
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"
|
||||
|
||||
CSHCoeffs::CSHCoeffs()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CSHCoeffs::Clear()
|
||||
{
|
||||
for (int i=0;i<9;i++) {
|
||||
_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));
|
||||
}
|
||||
|
||||
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color)
|
||||
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color) const
|
||||
{
|
||||
#if 1
|
||||
color=_data[0];
|
||||
|
@ -19,10 +19,12 @@ class CSHCoeffs
|
||||
public:
|
||||
CSHCoeffs();
|
||||
|
||||
void Clear();
|
||||
|
||||
void AddAmbientLight(const RGBColor& color);
|
||||
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; }
|
||||
|
||||
|
@ -12,18 +12,9 @@
|
||||
#ifndef TERRGLOBALS_H
|
||||
#define TERRGLOBALS_H
|
||||
|
||||
const int PATCH_SIZE = 16;
|
||||
const int CELL_SIZE = 4; //horizontal scale of the patches
|
||||
const float HEIGHT_SCALE = 0.35f;
|
||||
|
||||
//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 );
|
||||
|
||||
|
||||
const int PATCH_SIZE = 16;
|
||||
const int CELL_SIZE = 4; //horizontal scale of the patches
|
||||
const float HEIGHT_SCALE = 0.35f/256.0f;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -14,182 +14,267 @@
|
||||
//
|
||||
//***********************************************************
|
||||
|
||||
#include "res/res.h"
|
||||
|
||||
#include "res/tex.h"
|
||||
#include "res/mem.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "Terrain.h"
|
||||
#include "LightEnv.h"
|
||||
#include "SHCoeffs.h"
|
||||
|
||||
bool g_HillShading = true;
|
||||
|
||||
CVector3D SeasonLight[2];
|
||||
float SeasonColor[2][3];
|
||||
|
||||
CTerrain::CTerrain ()
|
||||
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];
|
||||
if (m_pVertices == NULL)
|
||||
return false;
|
||||
// allocate data for new terrain
|
||||
m_Heightmap=new u16[m_MapSize*m_MapSize];
|
||||
m_Patches=new CPatch[m_MapSizePatches*m_MapSizePatches];
|
||||
|
||||
for (j=0; j<MAP_SIZE; j++)
|
||||
{
|
||||
for (int i=0; i<MAP_SIZE; i++)
|
||||
{
|
||||
int pos = j*MAP_SIZE + i;
|
||||
|
||||
m_pVertices[pos].m_Position.X = ((float)i)*CELL_SIZE;
|
||||
m_pVertices[pos].m_Position.Y = (*data++)*HEIGHT_SCALE;
|
||||
m_pVertices[pos].m_Position.Z = ((float)j)*CELL_SIZE;
|
||||
}
|
||||
// given a heightmap?
|
||||
if (data) {
|
||||
// yes; keep a copy of it
|
||||
memcpy(m_Heightmap,data,m_MapSize*m_MapSize*sizeof(u16));
|
||||
} else {
|
||||
// build a flat terrain
|
||||
memset(m_Heightmap,0,m_MapSize*m_MapSize*sizeof(u16));
|
||||
}
|
||||
|
||||
for (j=0; j<NUM_PATCHES_PER_SIDE; j++)
|
||||
{
|
||||
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();
|
||||
// setup patch parents, indices etc
|
||||
InitialisePatches();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTerrain::CalcLighting(const CLightEnv& lightEnv)
|
||||
void CTerrain::CalcPosition(u32 i,u32 j,CVector3D& pos)
|
||||
{
|
||||
CSHCoeffs coeffs;
|
||||
coeffs.AddAmbientLight(lightEnv.m_TerrainAmbientColor);
|
||||
|
||||
CVector3D dirlight;
|
||||
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);
|
||||
}
|
||||
u16 height=m_Heightmap[j*m_MapSize + i];
|
||||
pos.X = float(i)*CELL_SIZE;
|
||||
pos.Y = float(height)*HEIGHT_SCALE;
|
||||
pos.Z = float(j)*CELL_SIZE;
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
for (int i=0; i<MAP_SIZE; i++)
|
||||
{
|
||||
left.Clear();
|
||||
right.Clear();
|
||||
up.Clear();
|
||||
down.Clear();
|
||||
left.Clear();
|
||||
right.Clear();
|
||||
up.Clear();
|
||||
down.Clear();
|
||||
|
||||
if (i>0)
|
||||
left = m_pVertices[j*MAP_SIZE + i - 1].m_Position -
|
||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
||||
// get position of vertex where normal is being evaluated
|
||||
CVector3D basepos;
|
||||
CalcPosition(i,j,basepos);
|
||||
|
||||
if (i<MAP_SIZE-1)
|
||||
right = m_pVertices[j*MAP_SIZE + i + 1].m_Position -
|
||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
||||
CVector3D tmp;
|
||||
if (i>0) {
|
||||
CalcPosition(i-1,j,tmp);
|
||||
left=tmp-basepos;
|
||||
}
|
||||
|
||||
if (j>0)
|
||||
up = m_pVertices[(j-1)*MAP_SIZE + i].m_Position -
|
||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
||||
if (i<m_MapSize-1) {
|
||||
CalcPosition(i+1,j,tmp);
|
||||
right=tmp-basepos;
|
||||
}
|
||||
|
||||
if (j<MAP_SIZE-1)
|
||||
down = m_pVertices[(j+1)*MAP_SIZE + i].m_Position -
|
||||
m_pVertices[j*MAP_SIZE + i].m_Position;
|
||||
if (j>0) {
|
||||
CalcPosition(i,j-1,tmp);
|
||||
up=tmp-basepos;
|
||||
}
|
||||
|
||||
n[0] = up.Cross(left);
|
||||
n[1] = left.Cross(down);
|
||||
n[2] = down.Cross(right);
|
||||
n[3] = right.Cross(up);
|
||||
if (j<m_MapSize-1) {
|
||||
CalcPosition(i,j+1,tmp);
|
||||
down=tmp-basepos;
|
||||
}
|
||||
|
||||
float n0len=n[0].GetLength();
|
||||
if (n0len>0.0001f) n[0]*=1.0f/n0len;
|
||||
CVector3D n0 = up.Cross(left);
|
||||
CVector3D n1 = left.Cross(down);
|
||||
CVector3D n2 = down.Cross(right);
|
||||
CVector3D n3 = right.Cross(up);
|
||||
|
||||
float n1len=n[1].GetLength();
|
||||
if (n1len>0.0001f) n[1]*=1.0f/n1len;
|
||||
normal = n0 + n1 + n2 + n3;
|
||||
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();
|
||||
if (n3len>0.0001f) n[3]*=1.0f/n3len;
|
||||
CPatch* CTerrain::GetPatch(int32 x,int32 z)
|
||||
{
|
||||
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];
|
||||
float nlen=Normal.GetLength();
|
||||
if (nlen>0.00001f) Normal*=1.0f/nlen;
|
||||
CMiniPatch* CTerrain::GetTile(int32 x,int32 z)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::SetNeighbors ()
|
||||
{
|
||||
CPatch *ThisPatch, *RightPatch;
|
||||
|
||||
for (int pj=0; pj<NUM_PATCHES_PER_SIDE; pj++)
|
||||
{
|
||||
for (int pi=0; pi<NUM_PATCHES_PER_SIDE; pi++)
|
||||
{
|
||||
ThisPatch = &m_Patches[pj][pi];
|
||||
|
||||
if (pi < NUM_PATCHES_PER_SIDE-1)
|
||||
RightPatch = &m_Patches[pj][pi+1];
|
||||
else
|
||||
RightPatch = NULL;
|
||||
|
||||
|
||||
for (int tj=0; tj<16; tj++)
|
||||
{
|
||||
for (int ti=0; ti<16; ti++)
|
||||
{
|
||||
CMiniPatch *MPatch = &ThisPatch->m_MiniPatches[tj][ti];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
MPatch->m_pParrent = ThisPatch;
|
||||
// now build new patches
|
||||
for (j=0;j<size;j++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (j<m_MapSizePatches && size>m_MapSizePatches) {
|
||||
// copy over the last tile from each column
|
||||
for (u32 n=0;n<size-m_MapSizePatches;n++) {
|
||||
for (int m=0;m<16;m++) {
|
||||
CMiniPatch& src=m_Patches[j*m_MapSizePatches+m_MapSizePatches-1].m_MiniPatches[m][15];
|
||||
for (int k=0;k<16;k++) {
|
||||
CMiniPatch& dst=newPatches[j*size+m_MapSizePatches+n].m_MiniPatches[m][k];
|
||||
dst.Tex1=src.Tex1;
|
||||
dst.Tex1Priority=src.Tex1Priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
#define TERRAIN_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Patch.h"
|
||||
#include "Vector3D.h"
|
||||
#include "TerrGlobals.h"
|
||||
|
||||
class CLightEnv;
|
||||
class CSHCoeffs;
|
||||
|
||||
extern bool g_HillShading;
|
||||
|
||||
class CTerrain
|
||||
{
|
||||
public:
|
||||
CTerrain ();
|
||||
~CTerrain ();
|
||||
public:
|
||||
CTerrain();
|
||||
~CTerrain();
|
||||
|
||||
bool Load(char *filename);
|
||||
bool InitFromHeightmap(const u8* data);
|
||||
bool Initialize(u32 size,const u16* ptr);
|
||||
|
||||
// protected:
|
||||
//the patches currently loaded
|
||||
CPatch m_Patches[NUM_PATCHES_PER_SIDE][NUM_PATCHES_PER_SIDE];
|
||||
STerrainVertex *m_pVertices;
|
||||
// return number of vertices along edge of the terrain
|
||||
u32 GetVerticesPerSide() { return m_MapSize; }
|
||||
// return number of patches along edge of the terrain
|
||||
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
|
@ -80,7 +80,7 @@ CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
|
||||
{
|
||||
assert(type<m_TerrainTextures.size());
|
||||
|
||||
CStr pathname("terrains/textures/");
|
||||
CStr pathname("art/textures/terrain/types/");
|
||||
pathname+=m_TerrainTextures[type].m_Name;
|
||||
pathname+='/';
|
||||
pathname+=filename;
|
||||
@ -151,7 +151,7 @@ void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext)
|
||||
long handle;
|
||||
|
||||
// build pathname
|
||||
CStr pathname("terrains\\textures\\");
|
||||
CStr pathname("mods\\official\\art\\textures\\terrain\\types\\");
|
||||
pathname+=m_TerrainTextures[terraintype].m_Name;
|
||||
pathname+="\\";
|
||||
|
||||
@ -181,7 +181,7 @@ void CTextureManager::BuildTerrainTypes()
|
||||
long handle;
|
||||
|
||||
// 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]!='_') {
|
||||
AddTextureType(file.name);
|
||||
|
@ -1,14 +1,16 @@
|
||||
#include "Matrix3D.h"
|
||||
#include "Renderer.h"
|
||||
#include "Terrain.h"
|
||||
#include "Camera.h"
|
||||
#include "LightEnv.h"
|
||||
#include "TextureManager.h"
|
||||
#include "Prometheus.h"
|
||||
|
||||
#include "detect.h"
|
||||
#include "time.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
|
||||
//#include "win.h" // REMOVEME
|
||||
@ -37,15 +39,8 @@ double g_LastTime;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
void terr_init()
|
||||
{
|
||||
int xres,yres;
|
||||
@ -69,10 +64,10 @@ void terr_update()
|
||||
g_Renderer.BeginFrame();
|
||||
g_Renderer.SetCamera(g_Camera);
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/*POINT MousePos;
|
||||
// switch on wireframe for terrain if we want it
|
||||
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||
|
||||
GetCursorPos (&MousePos);*/
|
||||
/////////////////////////////////////////////
|
||||
CVector3D right(1,0,1);
|
||||
CVector3D up(1,0,-1);
|
||||
right.Normalize ();
|
||||
@ -106,12 +101,12 @@ void terr_update()
|
||||
CFrustum frustum=g_Camera.GetFustum();
|
||||
|
||||
// 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)) {
|
||||
g_Renderer.Submit(&g_Terrain.m_Patches[j][i]);
|
||||
if (frustum.IsBoxVisible (CVector3D(0,0,0),g_Terrain.GetPatch(j, i)->GetBounds())) {
|
||||
g_Renderer.Submit(g_Terrain.GetPatch(j, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,7 +116,6 @@ void terr_update()
|
||||
|
||||
// g_Renderer.RenderTileOutline (&(g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX]));
|
||||
|
||||
// mark end of frame
|
||||
g_Renderer.EndFrame();
|
||||
}
|
||||
|
||||
@ -143,10 +137,10 @@ bool terr_handler(const SDL_Event& ev)
|
||||
switch(ev.key.keysym.sym)
|
||||
{
|
||||
case 'W':
|
||||
if (g_Renderer.GetTerrainMode()==CRenderer::WIREFRAME) {
|
||||
g_Renderer.SetTerrainMode(CRenderer::FILL);
|
||||
if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) {
|
||||
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||
} else {
|
||||
g_Renderer.SetTerrainMode(CRenderer::WIREFRAME);
|
||||
g_Renderer.SetTerrainRenderMode(WIREFRAME);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -158,14 +152,14 @@ bool terr_handler(const SDL_Event& ev)
|
||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* case 'L':
|
||||
g_HillShading = !g_HillShading;
|
||||
break;
|
||||
break;*/
|
||||
|
||||
// tile selection
|
||||
case SDLK_DOWN:
|
||||
if(++SelTX > 15)
|
||||
if(SelPX == NUM_PATCHES_PER_SIDE-1)
|
||||
if(SelPX == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTX = 15;
|
||||
else
|
||||
SelTX = 0, SelPX++;
|
||||
@ -180,7 +174,7 @@ bool terr_handler(const SDL_Event& ev)
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(++SelTY > 15)
|
||||
if(SelPY == NUM_PATCHES_PER_SIDE-1)
|
||||
if(SelPY == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTY = 15;
|
||||
else
|
||||
SelTY = 0, SelPY++;
|
||||
@ -197,8 +191,8 @@ bool terr_handler(const SDL_Event& ev)
|
||||
|
||||
case SDLK_KP0:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||
if (!MPatch->Tex2)
|
||||
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||
/*if (!MPatch->Tex2)
|
||||
{
|
||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||
@ -207,13 +201,13 @@ bool terr_handler(const SDL_Event& ev)
|
||||
{
|
||||
MPatch->Tex2 = 0;
|
||||
MPatch->m_AlphaMap = 0;
|
||||
}
|
||||
}*/
|
||||
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++;
|
||||
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];
|
||||
|
||||
if (MPatch->/*m_pTransitionTexture*/m_AlphaMap)
|
||||
if (MPatch->m_AlphaMap)
|
||||
{
|
||||
g_TransTexCounter++;
|
||||
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
|
||||
@ -253,7 +247,7 @@ bool terr_handler(const SDL_Event& ev)
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
@ -267,32 +261,61 @@ bool terr_handler(const SDL_Event& ev)
|
||||
void InitScene ()
|
||||
{
|
||||
// setup default lighting environment
|
||||
g_LightEnv.m_SunColor=RGBColor(0.75f,0.70f,0.65f);
|
||||
g_LightEnv.m_Rotation=270;
|
||||
g_LightEnv.m_Elevation=DEGTORAD(30);
|
||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0.0f,0.0f,0.0f);
|
||||
g_LightEnv.m_SunColor=RGBColor(1,1,1);
|
||||
g_LightEnv.m_Rotation=DEGTORAD(270);
|
||||
g_LightEnv.m_Elevation=DEGTORAD(45);
|
||||
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");
|
||||
|
||||
for (int pj=0; pj<NUM_PATCHES_PER_SIDE; pj++)
|
||||
// load terrain
|
||||
Handle ht = tex_load("terrain.raw");
|
||||
if(ht > 0)
|
||||
{
|
||||
for (int pi=0; pi<NUM_PATCHES_PER_SIDE; pi++)
|
||||
{
|
||||
for (int tj=0; tj<16; tj++)
|
||||
{
|
||||
for (int ti=0; ti<16; ti++)
|
||||
{
|
||||
g_Terrain.m_Patches[pj][pi].m_MiniPatches[tj][ti].Tex1 = BaseTexs[0];//rand()%5];
|
||||
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];
|
||||
const u8* p;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
tex_info(ht, &w, &h, NULL, NULL, (void **)&p);
|
||||
|
||||
printf("terrain.raw: %dx%d\n", w, h);
|
||||
|
||||
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.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
@ -304,75 +327,29 @@ void InitScene ()
|
||||
|
||||
void InitResources()
|
||||
{
|
||||
int i;
|
||||
char* base_fns[] =
|
||||
{
|
||||
"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;
|
||||
#ifndef _WIN32
|
||||
g_TexMan.AddTextureType("grass");
|
||||
g_TexMan.AddTexture("Base1.tga", 0);
|
||||
#else
|
||||
|
||||
char* fns[NUM_ALPHA_MAPS] = {
|
||||
"Transition1.bmp",
|
||||
"Transition2.bmp",
|
||||
"Transition3.bmp",
|
||||
"Transition4.bmp",
|
||||
"Transition5.bmp",
|
||||
};
|
||||
cnt=5;
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
#endif
|
||||
|
||||
for(i = 0; i < cnt; i++)
|
||||
{
|
||||
AlphaMaps[i] = tex_load(fns[i]);
|
||||
tex_upload(AlphaMaps[i], GL_LINEAR, GL_INTENSITY4);
|
||||
}
|
||||
const char* fns[CRenderer::NumAlphaMaps] = {
|
||||
"art/textures/terrain/alphamaps/special/blendcircle.png",
|
||||
"art/textures/terrain/alphamaps/special/blendlshape.png",
|
||||
"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