# More consistent terrain-space coordinate names
# Removed more ancient unused code # Partial VC2005 compatibility for Atlas editor / AoE3Ed # Terrain overlay rendering system; used to implemented Atlas brush display # Renamed 'right' to 'left' This was SVN commit r3771.
This commit is contained in:
parent
ca12496c2f
commit
8a11f53011
@ -83,9 +83,9 @@ void CTerrain::CalcPosition(i32 i, i32 j, CVector3D& pos) const
|
||||
height = m_Heightmap[j*m_MapSize + i];
|
||||
else
|
||||
height = 0;
|
||||
pos.X = float(i)*CELL_SIZE;
|
||||
pos.Y = float(height)*HEIGHT_SCALE;
|
||||
pos.Z = float(j)*CELL_SIZE;
|
||||
pos.X = float(i*CELL_SIZE);
|
||||
pos.Y = float(height*HEIGHT_SCALE);
|
||||
pos.Z = float(j*CELL_SIZE);
|
||||
}
|
||||
|
||||
|
||||
@ -137,58 +137,50 @@ void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal) const
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
|
||||
// GetPatch: return the patch at (i,j) in patch space, or null if the patch is
|
||||
// out of bounds
|
||||
CPatch* CTerrain::GetPatch(i32 x, i32 z) const
|
||||
CPatch* CTerrain::GetPatch(i32 i, i32 j) const
|
||||
{
|
||||
if (x<0 || x>=i32(m_MapSizePatches)) return 0;
|
||||
if (z<0 || z>=i32(m_MapSizePatches)) return 0;
|
||||
return &m_Patches[(z*m_MapSizePatches)+x];
|
||||
if (i<0 || i>=i32(m_MapSizePatches)) return 0;
|
||||
if (j<0 || j>=i32(m_MapSizePatches)) return 0;
|
||||
return &m_Patches[(j*m_MapSizePatches)+i];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
|
||||
// GetPatch: return the tile at (i,j) in tile space, or null if the tile is out
|
||||
// of bounds
|
||||
CMiniPatch* CTerrain::GetTile(i32 x, i32 z) const
|
||||
CMiniPatch* CTerrain::GetTile(i32 i, i32 j) const
|
||||
{
|
||||
if (x<0 || x>=i32(m_MapSize)-1) return 0;
|
||||
if (z<0 || z>=i32(m_MapSize)-1) return 0;
|
||||
if (i<0 || i>=i32(m_MapSize)-1) return 0;
|
||||
if (j<0 || j>=i32(m_MapSize)-1) return 0;
|
||||
|
||||
CPatch* patch=GetPatch(x/PATCH_SIZE,z/PATCH_SIZE);
|
||||
return &patch->m_MiniPatches[z%PATCH_SIZE][x%PATCH_SIZE];
|
||||
CPatch* patch=GetPatch(i/PATCH_SIZE, j/PATCH_SIZE);
|
||||
return &patch->m_MiniPatches[j%PATCH_SIZE][i%PATCH_SIZE];
|
||||
}
|
||||
|
||||
float CTerrain::getVertexGroundLevel(int x, int z) const
|
||||
float CTerrain::getVertexGroundLevel(int i, int j) const
|
||||
{
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
else if (x >= (int) m_MapSize)
|
||||
{
|
||||
x = m_MapSize - 1;
|
||||
}
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
else if (i >= (int) m_MapSize)
|
||||
i = m_MapSize - 1;
|
||||
|
||||
if (z < 0)
|
||||
{
|
||||
z = 0;
|
||||
}
|
||||
else if (z >= (int) m_MapSize)
|
||||
{
|
||||
z = m_MapSize - 1;
|
||||
}
|
||||
if (j < 0)
|
||||
j = 0;
|
||||
else if (j >= (int) m_MapSize)
|
||||
j = m_MapSize - 1;
|
||||
|
||||
return HEIGHT_SCALE * m_Heightmap[z*m_MapSize + x];
|
||||
return HEIGHT_SCALE * m_Heightmap[j*m_MapSize + i];
|
||||
}
|
||||
|
||||
float CTerrain::getSlope(float x, float y) const
|
||||
float CTerrain::getSlope(float x, float z) const
|
||||
{
|
||||
x /= (float)CELL_SIZE;
|
||||
y /= (float)CELL_SIZE;
|
||||
z /= (float)CELL_SIZE;
|
||||
|
||||
int xi = (int)floor(x);
|
||||
int yi = (int)floor(y);
|
||||
int zi = (int)floor(z);
|
||||
|
||||
if (xi < 0)
|
||||
{
|
||||
@ -199,33 +191,33 @@ float CTerrain::getSlope(float x, float y) const
|
||||
xi = m_MapSize - 2;
|
||||
}
|
||||
|
||||
if (yi < 0)
|
||||
if (zi < 0)
|
||||
{
|
||||
yi = 0;
|
||||
zi = 0;
|
||||
}
|
||||
else if (yi >= (int)m_MapSize-1)
|
||||
else if (zi >= (int)m_MapSize-1)
|
||||
{
|
||||
yi = m_MapSize - 2;
|
||||
zi = m_MapSize - 2;
|
||||
}
|
||||
|
||||
float h00 = m_Heightmap[yi*m_MapSize + xi];
|
||||
float h01 = m_Heightmap[yi*m_MapSize + xi + m_MapSize];
|
||||
float h10 = m_Heightmap[yi*m_MapSize + xi + 1];
|
||||
float h11 = m_Heightmap[yi*m_MapSize + xi + m_MapSize + 1];
|
||||
float h00 = m_Heightmap[zi*m_MapSize + xi];
|
||||
float h01 = m_Heightmap[zi*m_MapSize + xi + m_MapSize];
|
||||
float h10 = m_Heightmap[zi*m_MapSize + xi + 1];
|
||||
float h11 = m_Heightmap[zi*m_MapSize + xi + m_MapSize + 1];
|
||||
|
||||
return MAX(MAX(h00, h01), MAX(h10, h11)) -
|
||||
MIN(MIN(h00, h01), MIN(h10, h11));
|
||||
}
|
||||
|
||||
float CTerrain::getExactGroundLevel(float x, float y) const
|
||||
float CTerrain::getExactGroundLevel(float x, float z) const
|
||||
{
|
||||
x /= (float)CELL_SIZE;
|
||||
y /= (float)CELL_SIZE;
|
||||
z /= (float)CELL_SIZE;
|
||||
|
||||
int xi = (int)floor(x);
|
||||
int yi = (int)floor(y);
|
||||
int zi = (int)floor(z);
|
||||
float xf = x - (float)xi;
|
||||
float yf = y - (float)yi;
|
||||
float zf = z - (float)zi;
|
||||
|
||||
if (xi < 0)
|
||||
{
|
||||
@ -236,13 +228,13 @@ float CTerrain::getExactGroundLevel(float x, float y) const
|
||||
xi = m_MapSize - 2; xf = 1.0f;
|
||||
}
|
||||
|
||||
if (yi < 0)
|
||||
if (zi < 0)
|
||||
{
|
||||
yi = 0; yf = 0.0f;
|
||||
zi = 0; zf = 0.0f;
|
||||
}
|
||||
else if (yi >= (int)m_MapSize-1)
|
||||
else if (zi >= (int)m_MapSize-1)
|
||||
{
|
||||
yi = m_MapSize - 2; yf = 1.0f;
|
||||
zi = m_MapSize - 2; zf = 1.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -252,13 +244,13 @@ float CTerrain::getExactGroundLevel(float x, float y) const
|
||||
return 0.0f;
|
||||
*/
|
||||
|
||||
float h00 = m_Heightmap[yi*m_MapSize + xi];
|
||||
float h01 = m_Heightmap[yi*m_MapSize + xi + m_MapSize];
|
||||
float h10 = m_Heightmap[yi*m_MapSize + xi + 1];
|
||||
float h11 = m_Heightmap[yi*m_MapSize + xi + m_MapSize + 1];
|
||||
float h00 = m_Heightmap[zi*m_MapSize + xi];
|
||||
float h01 = m_Heightmap[zi*m_MapSize + xi + m_MapSize];
|
||||
float h10 = m_Heightmap[zi*m_MapSize + xi + 1];
|
||||
float h11 = m_Heightmap[zi*m_MapSize + xi + m_MapSize + 1];
|
||||
return (HEIGHT_SCALE * (
|
||||
(1 - yf) * ((1 - xf) * h00 + xf * h10)
|
||||
+ yf * ((1 - xf) * h01 + xf * h11)));
|
||||
(1 - zf) * ((1 - xf) * h00 + xf * h10)
|
||||
+ zf * ((1 - xf) * h01 + xf * h11)));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -407,12 +399,12 @@ void CTerrain::SetHeightMap(u16* heightmap)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// FlattenArea: flatten out an area of terrain (specified in world space
|
||||
// coords); return the average height of the flattened area
|
||||
float CTerrain::FlattenArea(float x0,float x1,float z0,float z1)
|
||||
float CTerrain::FlattenArea(float x0, float x1, float z0, float z1)
|
||||
{
|
||||
u32 tx0=u32(clamp(int(float(x0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tx1=u32(clamp(int(float(x1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
u32 tz0=u32(clamp(int(float(z0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tz1=u32(clamp(int(float(z1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
u32 tx0=u32(clamp(int(float(x0/CELL_SIZE)), 0, int(m_MapSize)));
|
||||
u32 tx1=u32(clamp(int(float(x1/CELL_SIZE)+1.0f), 0, int(m_MapSize)));
|
||||
u32 tz0=u32(clamp(int(float(z0/CELL_SIZE)), 0, int(m_MapSize)));
|
||||
u32 tz1=u32(clamp(int(float(z1/CELL_SIZE)+1.0f), 0, int(m_MapSize)));
|
||||
|
||||
u32 count=0;
|
||||
u32 y=0;
|
||||
@ -437,15 +429,15 @@ float CTerrain::FlattenArea(float x0,float x1,float z0,float z1)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CTerrain::MakeDirty(int x0, int z0, int x1, int z1, int dirtyFlags)
|
||||
void CTerrain::MakeDirty(int i0, int j0, int i1, int j1, int dirtyFlags)
|
||||
{
|
||||
// flag vertex data as dirty for affected patches, and rebuild bounds of these patches
|
||||
int px0 = clamp((x0/PATCH_SIZE)-1, 0, (int)m_MapSizePatches);
|
||||
int px1 = clamp((x1/PATCH_SIZE)+1, 0, (int)m_MapSizePatches);
|
||||
int pz0 = clamp((z0/PATCH_SIZE)-1, 0, (int)m_MapSizePatches);
|
||||
int pz1 = clamp((z1/PATCH_SIZE)+1, 0, (int)m_MapSizePatches);
|
||||
for (int j = pz0; j < pz1; j++) {
|
||||
for (int i = px0; i < px1; i++) {
|
||||
int pi0 = clamp((i0/PATCH_SIZE)-1, 0, (int)m_MapSizePatches);
|
||||
int pi1 = clamp((i1/PATCH_SIZE)+1, 0, (int)m_MapSizePatches);
|
||||
int pj0 = clamp((j0/PATCH_SIZE)-1, 0, (int)m_MapSizePatches);
|
||||
int pj1 = clamp((j1/PATCH_SIZE)+1, 0, (int)m_MapSizePatches);
|
||||
for (int j = pj0; j < pj1; j++) {
|
||||
for (int i = pi0; i < pi1; i++) {
|
||||
CPatch* patch = GetPatch(i,j);
|
||||
if (dirtyFlags & RENDERDATA_UPDATE_VERTICES)
|
||||
patch->CalcBounds();
|
||||
|
@ -23,26 +23,28 @@ public:
|
||||
CTerrain();
|
||||
~CTerrain();
|
||||
|
||||
bool Initialize(u32 size,const u16* ptr);
|
||||
// Coordinate naming convention: world-space coordinates are float x,z;
|
||||
// tile-space coordinates are int i,j.
|
||||
|
||||
bool Initialize(u32 size, const u16* ptr);
|
||||
|
||||
// return number of vertices along edge of the terrain
|
||||
u32 GetVerticesPerSide() const { return m_MapSize; }
|
||||
// return number of tiles along edge of the terrain
|
||||
u32 GetTilesPerSide() const { return GetVerticesPerSide()-1; }
|
||||
// return number of patches along edge of the terrain
|
||||
u32 GetPatchesPerSide() const { return m_MapSizePatches; }
|
||||
|
||||
inline bool isOnMap( float x, float y ) const
|
||||
inline bool isOnMap(float x, float z) const
|
||||
{
|
||||
return( ( x >= 0.0f ) && ( x < (float)( (m_MapSize-1) * CELL_SIZE ) ) && ( y >= 0.0f ) && ( y < (float)( (m_MapSize-1) * CELL_SIZE ) ) );
|
||||
return ((x >= 0.0f) && (x < (float)((m_MapSize-1) * CELL_SIZE)) && (z >= 0.0f) && (z < (float)((m_MapSize-1) * CELL_SIZE)));
|
||||
}
|
||||
inline bool isOnMap( const CVector2D& v ) const
|
||||
{
|
||||
return( ( v.x >= 0.0f ) && ( v.x < (float)( (m_MapSize-1) * CELL_SIZE ) ) && ( v.y >= 0.0f ) && ( v.y < (float)( (m_MapSize-1) * CELL_SIZE ) ) );
|
||||
}
|
||||
float getVertexGroundLevel( int x, int y ) const ;
|
||||
float getExactGroundLevel( float x, float y ) const ;
|
||||
inline float getExactGroundLevel( const CVector2D& v ) const { return( getExactGroundLevel( v.x, v.y ) ); }
|
||||
inline bool isOnMap(const CVector2D& v) const { return isOnMap(v.x, v.y); }
|
||||
float getVertexGroundLevel(int i, int j) const;
|
||||
float getExactGroundLevel(float x, float z) const;
|
||||
inline float getExactGroundLevel(const CVector2D& v) const { return getExactGroundLevel(v.x, v.y); }
|
||||
|
||||
float getSlope(float x, float y) const ;
|
||||
float getSlope(float x, float z) const ;
|
||||
|
||||
// resize this terrain such that each side has given number of patches
|
||||
void Resize(u32 size);
|
||||
@ -54,10 +56,10 @@ public:
|
||||
|
||||
// get patch at given coordinates, expressed in patch-space; return 0 if
|
||||
// coordinates represent patch off the edge of the map
|
||||
CPatch* GetPatch(i32 x, i32 z) const;
|
||||
CPatch* GetPatch(i32 i, i32 j) const;
|
||||
// get tile at given coordinates, expressed in tile-space; return 0 if
|
||||
// coordinates represent tile off the edge of the map
|
||||
CMiniPatch* GetTile(i32 x, i32 z) const;
|
||||
CMiniPatch* GetTile(i32 i, i32 j) const;
|
||||
|
||||
// calculate the position of a given vertex
|
||||
void CalcPosition(i32 i, i32 j, CVector3D& pos) const;
|
||||
@ -68,20 +70,20 @@ public:
|
||||
j = i32_from_float(pos.Z/CELL_SIZE);
|
||||
}
|
||||
// calculate the vertex under a given position (rounding down coordinates)
|
||||
static void CalcFromPosition(float x, float y, i32& i, i32& j)
|
||||
static void CalcFromPosition(float x, float z, i32& i, i32& j)
|
||||
{
|
||||
i = i32_from_float(x/CELL_SIZE);
|
||||
j = i32_from_float(y/CELL_SIZE);
|
||||
j = i32_from_float(z/CELL_SIZE);
|
||||
}
|
||||
// calculate the normal at a given vertex
|
||||
void CalcNormal(u32 i, u32 j, CVector3D& normal) const;
|
||||
|
||||
// flatten out an area of terrain (specified in world space coords); return
|
||||
// the average height of the flattened area
|
||||
float FlattenArea(float x0,float x1,float z0,float z1);
|
||||
float FlattenArea(float x0, float x1, float z0, float z1);
|
||||
|
||||
// mark a specific square of tiles as dirty - use this after modifying the heightmap
|
||||
void MakeDirty(int x0, int z0, int x1, int z1, int dirtyFlags);
|
||||
void MakeDirty(int i0, int j0, int i1, int j1, int dirtyFlags);
|
||||
// mark the entire map as dirty
|
||||
void MakeDirty(int dirtyFlags);
|
||||
|
||||
|
@ -1,250 +0,0 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#if 0
|
||||
// last modified Thursday, May 08, 2003
|
||||
|
||||
#include <time.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
|
||||
// MathUtil Errors
|
||||
DEFINE_ERROR(ERRONEOUS_BOUND_ERROR, "Lower Bound is >= Upper Bound");
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: CompareFloat
|
||||
// PURPOSE: Returns true if two floating point numbers are within
|
||||
// FL_FP_TOLERANCE of each other.
|
||||
//
|
||||
bool MathUtil::CompareFloat(const double &num1, const double &num2)
|
||||
{
|
||||
if( Abs(num1 - num2) < FL_FP_TOLERANCE )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: RadiansToDegrees
|
||||
// PURPOSE: Converts from Radians to Degrees
|
||||
//
|
||||
inline double MathUtil::RadiansToDegrees(const double &num)
|
||||
{
|
||||
return num*(PI/180);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: RadiansToDegrees
|
||||
// PURPOSE: Converts from Degrees to Radians
|
||||
//
|
||||
inline double MathUtil::DegreesToRadians(const double &num)
|
||||
{
|
||||
return (num*180)/PI;
|
||||
}
|
||||
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: Random
|
||||
// PURPOSE: returns a random floating point number between lowerBound
|
||||
// and upperBound
|
||||
// NOTES: returns -1 if lowerBound >= upperBound
|
||||
//
|
||||
float MathUtil::Random(const float &lowerBound, const float &upperBound)
|
||||
{
|
||||
|
||||
if( lowerBound >= upperBound)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
// seed generator with current time
|
||||
srand( static_cast<unsigned>( time(NULL) ) );
|
||||
|
||||
// finds a floating point number between 0 and 1.0
|
||||
float randVar = ( static_cast<float>( rand() )/RAND_MAX );
|
||||
|
||||
// maps the number onto the set from 0 to upperBound
|
||||
randVar *= Abs(lowerBound - upperBound ) + 1;
|
||||
|
||||
//translate to the proper range
|
||||
randVar += lowerBound;
|
||||
|
||||
return randVar;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: Random
|
||||
// PURPOSE: returns a random number between lowerBound and upperBound
|
||||
// NOTES: returns -1 if lowerBound >= upperBound
|
||||
//
|
||||
int MathUtil::Random(const int &lowerBound,const int &upperBound)
|
||||
{
|
||||
if( lowerBound >= upperBound)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
// seed generator with current time
|
||||
srand( static_cast<unsigned>( time(NULL) ) );
|
||||
|
||||
// find a random variable between 0 and range size
|
||||
int randVar = rand()%( Abs(upperBound - lowerBound) + 1);
|
||||
|
||||
// translate to proper range
|
||||
randVar += lowerBound;
|
||||
|
||||
return randVar;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Round
|
||||
// PURPOSE: Rounds a number.
|
||||
// NOTES: Round rounds to the nearest representable number
|
||||
// float version.
|
||||
//
|
||||
int MathUtil::Round(const float &num)
|
||||
{
|
||||
if( num > 0 )
|
||||
return static_cast<int>(num + .5);
|
||||
else if (num < 0 )
|
||||
return static_cast<int>(num - .5);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Round
|
||||
// PURPOSE: Rounds a number.
|
||||
// NOTES: Round rounds to the nearest representable number
|
||||
// double version.
|
||||
//
|
||||
int MathUtil::Round(const double &num)
|
||||
{
|
||||
if( num > 0 )
|
||||
return static_cast<int>(num + .5);
|
||||
else if (num < 0 )
|
||||
return static_cast<int>(num - .5);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: SignedModulus
|
||||
// PURPOSE: returns a mathematically correct modulus for int
|
||||
//
|
||||
int MathUtil::SignedModulus(const int &num, const int &n)
|
||||
{
|
||||
if( num >= 0 )
|
||||
return num%n;
|
||||
else
|
||||
{
|
||||
// the % operator reflects the range if num < 0, so
|
||||
// we have to multiply by -1 to reflect it back. This method
|
||||
// is faster than calling Abs() and then doing the modulus.
|
||||
int Tnum = -1*(num%n);
|
||||
|
||||
// if num%n equals 0, then n - Tnum will be n, which, logically
|
||||
// speaking, is 0 in a different form, but we have to make sure it's
|
||||
// in the form 0, and not n. Therefore, if Tnum = 0, simply leave
|
||||
// it like that.
|
||||
if( Tnum != 0)
|
||||
Tnum = n - Tnum;
|
||||
|
||||
return Tnum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: SignedModulus
|
||||
// PURPOSE: returns a mathematically correct modulus for long
|
||||
//
|
||||
long MathUtil::SignedModulus(const long &num, const long &n)
|
||||
{
|
||||
if( num >= 0 )
|
||||
return num%n;
|
||||
else
|
||||
{
|
||||
// the % operator reflects the range if num < 0, so
|
||||
// we have to multiply by -1 to reflect it back. This method
|
||||
// is faster than calling Abs() and then doing the modulus.
|
||||
long Tnum = -1*(num%n);
|
||||
|
||||
// if num%n equals 0, then n - Tnum will be n, which, logically
|
||||
// speaking, is 0 in a different form, but we have to make sure it's
|
||||
// in the form 0, and not n. Therefore, if Tnum = 0, simply leave
|
||||
// it like that.
|
||||
if( Tnum != 0)
|
||||
Tnum = n - Tnum;
|
||||
|
||||
return Tnum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: SignedModulus
|
||||
// PURPOSE: returns a mathematically correct modulus for float
|
||||
// NOTES: uses fmod() in math.h, which returns the modulus of floats
|
||||
//
|
||||
float MathUtil::SignedModulus(const float &num, const float &n)
|
||||
{
|
||||
if( num >=0 )
|
||||
return static_cast<float>( fmod(num,n) );
|
||||
else
|
||||
{
|
||||
// the % operator reflects the range if num < 0, so
|
||||
// we have to multiply by -1 to reflect it back. This method
|
||||
// is faster than calling Abs() and then doing the modulus.
|
||||
float Tnum = -1*( static_cast<float>( fmod(num,n) ) );
|
||||
|
||||
// if num%n equals 0, then n - Tnum will be n, which, logically
|
||||
// speaking, is 0 in a different form, but we have to make sure it's
|
||||
// in the form 0, and not n. Therefore, if Tnum = 0, simply leave
|
||||
// it like that.
|
||||
if( Tnum != 0)
|
||||
Tnum = n - Tnum;
|
||||
|
||||
return Tnum;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// NAME: SignedModulus
|
||||
// PURPOSE: returns a mathematically correct modulus for double
|
||||
// NOTES: uses fmod() in math.h, which returns the modulus of floats
|
||||
//
|
||||
double MathUtil::SignedModulus(const double &num, const double &n)
|
||||
{
|
||||
if( num >=0 )
|
||||
return fmod(num,n);
|
||||
else
|
||||
{
|
||||
// the % operator reflects the range if num < 0, so
|
||||
// we have to multiply by -1 to reflect it back. This method
|
||||
// is faster than calling Abs() and then doing the modulus.
|
||||
double Tnum = -1*( fmod(num,n) );
|
||||
|
||||
// if num%n equals 0, then n - Tnum will be n, which, logically
|
||||
// speaking, is 0 in a different form, but we have to make sure it's
|
||||
// in the form 0, and not n. Therefore, if Tnum = 0, simply leave
|
||||
// it like that.
|
||||
if( Tnum != 0)
|
||||
Tnum = n - Tnum;
|
||||
|
||||
return Tnum;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -43,209 +43,4 @@ static inline int RoundUpToPowerOf2(int x)
|
||||
return d<<1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
Math utility functions
|
||||
by Michael Reiland
|
||||
recondite_phreak@yahool.com
|
||||
|
||||
--Overview--
|
||||
|
||||
Contains common math functions like Abs, Sign, Max, Min, etc.
|
||||
|
||||
|
||||
--More info--
|
||||
|
||||
TODO: actually write corresponding documentation
|
||||
http://wildfiregames.com/0ad/codepit/TDD/math_utils.html
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
|
||||
#include "Pyrogenesis.h" // Standard Engine Include
|
||||
#include <math.h> // Needed for fmod()
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Error declarations
|
||||
//--------------------------------------------------------
|
||||
|
||||
|
||||
// MathUtil Errors
|
||||
DECLARE_ERROR(ERRONEOUS_BOUND_ERROR);
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Declarations
|
||||
//--------------------------------------------------------
|
||||
|
||||
namespace MathUtil
|
||||
{
|
||||
const double PI = 3.14159265358932384;
|
||||
const double FL_FP_TOLERANCE = .000000001;
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Template functions
|
||||
//--------------------------------------------------------
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Declarations
|
||||
//--------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Abs
|
||||
// PURPOSE: Calculates the Absolute value
|
||||
//
|
||||
template <typename T>
|
||||
T Abs(const T &num)
|
||||
{
|
||||
if( num < 0)
|
||||
return -1*num;
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Clamp
|
||||
// PURPOSE: Forces num to be between lowerBound and upperBound
|
||||
//
|
||||
template <typename T>
|
||||
T Clamp(T &num, const int &lowerBound,const int &upperBound)
|
||||
{
|
||||
if(num <= lowerBound)
|
||||
num = static_cast<T>(lowerBound);
|
||||
else if( num >= upperBound)
|
||||
num = static_cast<T>(upperBound);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Max
|
||||
// PURPOSE: Returns the largest number.
|
||||
//
|
||||
template <typename T>
|
||||
T Max(const T &num1, const T &num2)
|
||||
{
|
||||
if( num1 > num2)
|
||||
return num1;
|
||||
else
|
||||
return num2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Min
|
||||
// PURPOSE: Returns the smallest number.
|
||||
//
|
||||
template <typename T>
|
||||
T Min(const T &num1, const T &num2)
|
||||
{
|
||||
if( num1 < num2)
|
||||
return num1;
|
||||
else
|
||||
return num2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Sign
|
||||
// PURPOSE: Returns 1 if the number is > 0, -1 if it's < 0,
|
||||
// otherwise returns 0.
|
||||
//
|
||||
template <typename T>
|
||||
int Sign(const T &num)
|
||||
{
|
||||
if( num > 0 )
|
||||
return 1;
|
||||
else if( num < 0 )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Square
|
||||
// PURPOSE: Returns the square of a number
|
||||
// NOTES: Num should be less than the square root of the
|
||||
// maximum representable number for the data type.
|
||||
//
|
||||
template <typename T>
|
||||
inline double Square(const T &num)
|
||||
{
|
||||
return num*num;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Swap
|
||||
// PURPOSE: Swaps two numbers
|
||||
//
|
||||
template <typename T>
|
||||
void Swap(T *num1, T *num2)
|
||||
{
|
||||
T temp = num1;
|
||||
num1 = num2;
|
||||
num2 = temp;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// NAME: Wrap
|
||||
// PURPOSE: Wraps num between lowerBound and upperBound.
|
||||
//
|
||||
template <typename T>
|
||||
int Wrap(T *num,const T &lowerBound, const T &upperBound)
|
||||
{
|
||||
if(lowerBound >= upperBound)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
// translate to range 0 to n-1, find the modulus, then
|
||||
// translate back to range lowerBound to upperBound.
|
||||
num -= lowerBound;
|
||||
num = SignedModulus( num, Abs(upperBound - lowerBound) );
|
||||
num += lowerBound;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Non-template functions
|
||||
//--------------------------------------------------------
|
||||
|
||||
int Ceiling(const float &num);
|
||||
int Ceiling(const double &num);
|
||||
|
||||
bool CompareFloat(const double &, const double &);
|
||||
|
||||
int Floor(const float &num);
|
||||
int Floor(const double &num);
|
||||
|
||||
inline double RadiansToDegrees(const double &num);
|
||||
inline double DegreesToRadians(const double &num);
|
||||
|
||||
float Random(const float &, const float &);
|
||||
int Random(const int &,const int &);
|
||||
|
||||
int Round(const float &num);
|
||||
int Round(const double &num);
|
||||
|
||||
int SignedModulus(const int &num, const int &n);
|
||||
long SignedModulus(const long &num, const long &n);
|
||||
float SignedModulus(const float &num, const float &n);
|
||||
double SignedModulus(const double &num, const double &n);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -60,6 +60,9 @@ class CVector3D
|
||||
//Returns length of the vector
|
||||
float GetLength () const;
|
||||
void Normalize ();
|
||||
|
||||
// Returns 3 element array of floats, e.g. for glVertex3fv
|
||||
const float* GetFloatArray() const { return &X; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
Sound.h
|
||||
by Raj
|
||||
|
||||
Classes to play sounds or music using FMOD
|
||||
|
||||
Usage: Create a CWindow object, call Create, call Run.
|
||||
|
||||
If you want to handle events like mouse clicks, you need to derive your
|
||||
own class from CBaseWindow, and override the OnXXX() functions. For example,
|
||||
OnActivate() or OnPaint().
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
-----support pan, volume, and crossfading
|
||||
|
||||
|
||||
|
||||
struct SSoundEffect
|
||||
{
|
||||
Position
|
||||
Radius
|
||||
Volume
|
||||
Actual sound effect
|
||||
Layer
|
||||
};
|
||||
|
||||
|
||||
struct SoundScheme
|
||||
{
|
||||
include several different sounds
|
||||
specify the looping time for this scheme
|
||||
and,
|
||||
}
|
||||
|
||||
|
||||
Class methods
|
||||
|
||||
-SetCrossFadeSpeed: how quickly it takes to crossfade between current music and new music
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
#pragma warning (disable: 4786)
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
|
||||
#include <Flamer.h>
|
||||
#include <Sound.h>
|
||||
#include <map>
|
||||
#include <fmod.h>
|
||||
#include <string>
|
||||
#include <FileIO.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
DECLARE_ERROR(PS_SOUND_INIT);
|
||||
|
||||
typedef bool STREAM_OPTION;
|
||||
const int STREAMING = true;
|
||||
const int NO_STREAMING = false;
|
||||
|
||||
class CSample
|
||||
{
|
||||
public:
|
||||
|
||||
operator FSOUND_STREAM * ();
|
||||
operator FSOUND_SAMPLE * ();
|
||||
|
||||
operator = (FSOUND_STREAM *);
|
||||
operator = (FSOUND_SAMPLE *);
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
FSOUND_STREAM *stream;
|
||||
FSOUND_SAMPLE *sample;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
// CSound: Class which plays sounds or music
|
||||
class CSound
|
||||
{
|
||||
public:
|
||||
CSound();
|
||||
~CSound();
|
||||
|
||||
PS_RESULT Init();
|
||||
PS_RESULT Release();
|
||||
|
||||
PS_RESULT Load(string filename, string nickname, STREAM_OPTION useStreaming=false);
|
||||
PS_RESULT Play(string nickname);
|
||||
|
||||
PS_RESULT SetMasterVolume(float vol);
|
||||
PS_RESULT SetSampleVolume(string sample, float vol);
|
||||
|
||||
PS_RESULT Pause();
|
||||
PS_RESULT Resume();
|
||||
|
||||
private:
|
||||
map <string, CSample> soundList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
PS_RESULT CSound::Load(string filename, string nickname, STREAM_OPTION useStreaming)
|
||||
{
|
||||
CSample newFile;
|
||||
|
||||
if(useStreaming == STREAMING)
|
||||
{
|
||||
|
||||
}
|
||||
else if(useStreaming == NO_STREAMING)
|
||||
{
|
||||
FSOUND_Sample_Load(FSOUND_FREE, //let FSOUND select an arbitrary sample slot
|
||||
filename.c_str(), //name of the file to load
|
||||
FSOUND_LOADMEMORY,
|
||||
);
|
||||
}
|
||||
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::Play(string nickname)
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::Release()
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::SetMasterVolume(float vol)
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::SetSampleVolume(string sample, float vol)
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::Pause()
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
PS_RESULT CSound::Resume()
|
||||
{
|
||||
return PS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -54,6 +54,7 @@
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/RenderPathVertexShader.h"
|
||||
#include "renderer/ShadowMap.h"
|
||||
#include "renderer/TerrainOverlay.h"
|
||||
#include "renderer/TerrainRenderer.h"
|
||||
#include "renderer/TransparencyRenderer.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
@ -962,6 +963,9 @@ void CRenderer::FlushFrame()
|
||||
RenderPatches();
|
||||
oglCheck();
|
||||
|
||||
// render debug-related terrain overlays
|
||||
TerrainOverlay::RenderOverlays();
|
||||
|
||||
MICROLOG(L"render models");
|
||||
RenderModels();
|
||||
oglCheck();
|
||||
|
184
source/renderer/TerrainOverlay.cpp
Normal file
184
source/renderer/TerrainOverlay.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "TerrainOverlay.h"
|
||||
|
||||
#include "ps/Game.h"
|
||||
#include "ps/World.h"
|
||||
#include "graphics/Terrain.h"
|
||||
#include "maths/MathUtil.h"
|
||||
#include "lib/ogl.h"
|
||||
|
||||
|
||||
// Handy things for STL:
|
||||
|
||||
/**
|
||||
* Functor for sorting pairs, using the <-ordering of their second values.
|
||||
*/
|
||||
struct compare2nd
|
||||
{
|
||||
template<typename S, typename T> bool operator()(const std::pair<S, T>& a, const std::pair<S, T>& b) const
|
||||
{
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Functor for comparing the firsts of pairs to a specified value.
|
||||
*/
|
||||
template<typename S> struct equal1st
|
||||
{
|
||||
const S& val;
|
||||
equal1st(const S& val) : val(val) {}
|
||||
template <typename T> bool operator()(const std::pair<S, T>& a) const
|
||||
{
|
||||
return a.first == val;
|
||||
}
|
||||
private:
|
||||
const equal1st& operator=(const equal1st& rhs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Functor for calling ->Render on pairs' firsts.
|
||||
*/
|
||||
struct render1st
|
||||
{
|
||||
template<typename S, typename T> void operator()(const std::pair<S, T>& a) const
|
||||
{
|
||||
a.first->Render();
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Global overlay list management:
|
||||
|
||||
static std::vector<std::pair<TerrainOverlay*, int> > g_TerrainOverlayList;
|
||||
|
||||
TerrainOverlay::TerrainOverlay(int priority)
|
||||
{
|
||||
// Add to global list of overlays
|
||||
g_TerrainOverlayList.push_back(std::make_pair(this, priority));
|
||||
// Sort by overlays by priority. Do stable sort so that adding/removing
|
||||
// overlays doesn't randomly disturb all the existing ones (which would
|
||||
// be noticeable if they have the same priority and overlap).
|
||||
std::stable_sort(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(),
|
||||
compare2nd());
|
||||
}
|
||||
|
||||
TerrainOverlay::~TerrainOverlay()
|
||||
{
|
||||
std::vector<std::pair<TerrainOverlay*, int> >::iterator newEnd =
|
||||
std::remove_if(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(),
|
||||
equal1st<TerrainOverlay*>(this));
|
||||
g_TerrainOverlayList.erase(newEnd, g_TerrainOverlayList.end());
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderOverlays()
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(GL_FALSE);
|
||||
// To ensure that outlines are drawn on top of the terrain correctly (and
|
||||
// don't Z-fight and flicker nastily), draw them as QUADS with the LINE
|
||||
// PolygonMode, and use PolygonOffset to pull them towards the camera.
|
||||
// (See e.g. http://www.opengl.org/resources/faq/technical/polygonoffset.htm)
|
||||
glPolygonOffset(-1.f, -1.f);
|
||||
glEnable(GL_POLYGON_OFFSET_LINE);
|
||||
|
||||
std::for_each(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(),
|
||||
render1st());
|
||||
|
||||
// Clean up state to at least be consistent
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TerrainOverlay::GetTileExtents(
|
||||
int& min_i_inclusive, int& min_j_inclusive,
|
||||
int& max_i_inclusive, int& max_j_inclusive)
|
||||
{
|
||||
// Default to whole map
|
||||
min_i_inclusive = min_j_inclusive = 0;
|
||||
max_i_inclusive = max_j_inclusive = m_Terrain->GetTilesPerSide()-1;
|
||||
}
|
||||
|
||||
void TerrainOverlay::Render()
|
||||
{
|
||||
m_Terrain = g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
int min_i, min_j, max_i, max_j;
|
||||
GetTileExtents(min_i, min_j, max_i, max_j);
|
||||
// Clamp the min to 0, but the max to -1 - so tile -1 can never be rendered,
|
||||
// but if unclamped_max<0 then no tiles at all will be rendered. And the same
|
||||
// for the upper limit.
|
||||
min_i = clamp(min_i, 0, (int)m_Terrain->GetTilesPerSide());
|
||||
min_j = clamp(min_j, 0, (int)m_Terrain->GetTilesPerSide());
|
||||
max_i = clamp(max_i, -1, (int)m_Terrain->GetTilesPerSide()-1);
|
||||
max_j = clamp(max_j, -1, (int)m_Terrain->GetTilesPerSide()-1);
|
||||
|
||||
for (m_j = min_j; m_j <= max_j; ++m_j)
|
||||
for (m_i = min_i; m_i <= max_i; ++m_i)
|
||||
ProcessTile(m_i, m_j);
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTile(const CColor& colour, bool draw_hidden)
|
||||
{
|
||||
// TODO: if this is unpleasantly slow, make it much more efficient
|
||||
// (e.g. buffering data and making a single draw call? or at least
|
||||
// far fewer calls than it makes now)
|
||||
|
||||
if (draw_hidden)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
CVector3D pos;
|
||||
glBegin(GL_QUADS);
|
||||
glColor4fv(colour.FloatArray());
|
||||
m_Terrain->CalcPosition(m_i, m_j, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i+1, m_j, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i+1, m_j+1, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i, m_j+1, pos); glVertex3fv(pos.GetFloatArray());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden)
|
||||
{
|
||||
if (draw_hidden)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
glLineWidth((float)line_width);
|
||||
|
||||
CVector3D pos;
|
||||
glBegin(GL_QUADS);
|
||||
glColor4fv(colour.FloatArray());
|
||||
m_Terrain->CalcPosition(m_i, m_j, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i+1, m_j, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i+1, m_j+1, pos); glVertex3fv(pos.GetFloatArray());
|
||||
m_Terrain->CalcPosition(m_i, m_j+1, pos); glVertex3fv(pos.GetFloatArray());
|
||||
glEnd();
|
||||
}
|
150
source/renderer/TerrainOverlay.h
Normal file
150
source/renderer/TerrainOverlay.h
Normal file
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : TerrainOverlay.h
|
||||
* Project : Pyrogenesis
|
||||
* Description : System for representing tile-based information on top of
|
||||
* : the terrain.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __TERRAINOVERLAY_H__
|
||||
#define __TERRAINOVERLAY_H__
|
||||
|
||||
#include "ps/Overlay.h" // for CColor
|
||||
|
||||
class CTerrain;
|
||||
|
||||
/**
|
||||
* Base class for (relatively) simple drawing of
|
||||
* data onto terrain tiles, intended for debugging purposes and for the Atlas
|
||||
* editor (hence not trying to be very efficient).
|
||||
* <p>
|
||||
* To start drawing a terrain overlay, first create a subclass of TerrainOverlay.
|
||||
* Override the method GetTileExtents if you want to change the range over which
|
||||
* it is drawn.
|
||||
* Override ProcessTile to do your processing for each tile, which should call
|
||||
* RenderTile and RenderTileOutline as appropriate.
|
||||
* See the end of TerrainOverlay.h for an example.
|
||||
* <p>
|
||||
* A TerrainOverlay object will be rendered for as long as it exists.
|
||||
*
|
||||
*/
|
||||
class TerrainOverlay
|
||||
{
|
||||
public:
|
||||
virtual ~TerrainOverlay();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Construct the object and register it with the global
|
||||
* list of terrain overlays.
|
||||
* <p>
|
||||
* The priority parameter controls the order in which overlays are drawn,
|
||||
* if several exist - they are processed in order of increasing priority,
|
||||
* so later ones draw on top of earlier ones.
|
||||
* Most should use the default of 100. Numbers from 200 are used
|
||||
* by Atlas.
|
||||
*
|
||||
* @param priority controls the order of drawing
|
||||
*/
|
||||
TerrainOverlay(int priority = 100);
|
||||
|
||||
/**
|
||||
* Override to limit the range over which ProcessTile will
|
||||
* be called. Defaults to the size of the map.
|
||||
*
|
||||
* @param min_i_inclusive [output] smallest <i>i</i> coordinate, in tile-space units
|
||||
* (1 unit per tile, <i>+i</i> is world-space <i>+x</i> and game-space East)
|
||||
* @param min_j_inclusive [output] smallest <i>j</i> coordinate
|
||||
* (<i>+j</i> is world-space <i>+z</i> and game-space North)
|
||||
* @param max_i_inclusive [output] largest <i>i</i> coordinate
|
||||
* @param max_j_inclusive [output] largest <i>j</i> coordinate
|
||||
*/
|
||||
virtual void GetTileExtents(int& min_i_inclusive, int& min_j_inclusive,
|
||||
int& max_i_inclusive, int& max_j_inclusive);
|
||||
|
||||
/**
|
||||
* Override to perform processing of each tile. Typically calls
|
||||
* RenderTile and/or RenderTileOutline.
|
||||
*
|
||||
* @param i <i>i</i> coordinate of tile being processed
|
||||
* @param j <i>j</i> coordinate of tile being processed
|
||||
*/
|
||||
virtual void ProcessTile(int i, int j) = 0;
|
||||
|
||||
/**
|
||||
* Draw a filled quad on top of the current tile.
|
||||
*
|
||||
* @param colour colour to draw. May be transparent (alpha < 1)
|
||||
* @param draw_hidden true if hidden tiles (i.e. those behind other tiles)
|
||||
* should be drawn
|
||||
*/
|
||||
void RenderTile(const CColor& colour, bool draw_hidden);
|
||||
|
||||
/**
|
||||
* Draw an outlined quad on top of the current tile.
|
||||
*
|
||||
* @param colour colour to draw. May be transparent (alpha < 1)
|
||||
* @param line_width width of lines in pixels. 1 is a sensible value
|
||||
* @param draw_hidden true if hidden tiles (i.e. those behind other tiles)
|
||||
* should be drawn
|
||||
*/
|
||||
void RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden);
|
||||
|
||||
public:
|
||||
/// Draw all TerrainOverlay objects that exist.
|
||||
static void RenderOverlays();
|
||||
|
||||
private:
|
||||
/// Copying not allowed.
|
||||
TerrainOverlay(const TerrainOverlay&);
|
||||
|
||||
friend struct render1st;
|
||||
|
||||
// Process all tiles
|
||||
void Render();
|
||||
|
||||
// Temporary storage of tile coordinates, so ProcessTile doesn't need to
|
||||
// pass it to RenderTile/etc (and doesn't have a chance to get it wrong)
|
||||
int m_i, m_j;
|
||||
|
||||
CTerrain* m_Terrain;
|
||||
};
|
||||
|
||||
|
||||
/* Example usage:
|
||||
|
||||
class ExampleTerrainOverlay : public TerrainOverlay
|
||||
{
|
||||
public:
|
||||
char random[1021];
|
||||
|
||||
ExampleTerrainOverlay()
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(random); ++i)
|
||||
random[i] = rand(0, 5);
|
||||
}
|
||||
|
||||
virtual void GetTileExtents(
|
||||
int& min_i_inclusive, int& min_j_inclusive,
|
||||
int& max_i_inclusive, int& max_j_inclusive)
|
||||
{
|
||||
min_i_inclusive = 5;
|
||||
min_j_inclusive = 10;
|
||||
max_i_inclusive = 70;
|
||||
max_j_inclusive = 50;
|
||||
}
|
||||
|
||||
virtual void ProcessTile(int i, int j)
|
||||
{
|
||||
if (!random[(i*97+j*101) % ARRAY_SIZE(random)])
|
||||
return;
|
||||
RenderTile(CColor(random[(i*79+j*13) % ARRAY_SIZE(random)]/4.f, 1, 0, 0.3f), false);
|
||||
RenderTileOutline(CColor(1, 1, 1, 1), 1, true);
|
||||
}
|
||||
};
|
||||
|
||||
ExampleTerrainOverlay test; // or allocate it dynamically somewhere
|
||||
*/
|
||||
|
||||
#endif // __TERRAINOVERLAY_H__
|
@ -69,7 +69,7 @@ CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Release: return given chunk to it's owner
|
||||
// Release: return given chunk to its owner
|
||||
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
|
||||
{
|
||||
debug_assert(chunk);
|
||||
|
@ -3,18 +3,18 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef NDEBUG
|
||||
# pragma comment(lib, "xerces-c_2D.lib")
|
||||
# else
|
||||
#ifdef _MSC_VER
|
||||
# ifndef NDEBUG
|
||||
# pragma comment(lib, "xerces-c_2D.lib")
|
||||
# else
|
||||
# pragma comment(lib, "xerces-c_2.lib")
|
||||
# endif
|
||||
|
||||
// Disable some warnings:
|
||||
# endif
|
||||
|
||||
// Disable some warnings:
|
||||
// "warning C4673: throwing 'blahblahException' the following types will not be considered at the catch site ..."
|
||||
// "warning C4671: 'XMemory' : the copy constructor is inaccessible"
|
||||
# pragma warning(disable: 4673 4671)
|
||||
|
||||
// "warning C4671: 'XMemory' : the copy constructor is inaccessible"
|
||||
# pragma warning(disable: 4673 4671)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
@ -136,7 +136,8 @@ static AtSmartPtr<AtNode> ConvertNode(DOMElement* element)
|
||||
// Text inside the element. Append it to the current node's string.
|
||||
|
||||
// TODO: Make this work on GCC, where wchar_t != XMLCh
|
||||
std::wstring value_wstr (node->getNodeValue());
|
||||
assert(sizeof(wchar_t) == sizeof(XMLCh));
|
||||
std::wstring value_wstr (reinterpret_cast<const wchar_t*>(node->getNodeValue()));
|
||||
obj->value += value_wstr;
|
||||
}
|
||||
}
|
||||
@ -152,7 +153,7 @@ static AtSmartPtr<AtNode> ConvertNode(DOMElement* element)
|
||||
|
||||
// Get name and value. (TODO: GCC)
|
||||
char* name = XMLString::transcode(attr->getName());
|
||||
const wchar_t* value = attr->getValue();
|
||||
const wchar_t* value = reinterpret_cast<const wchar_t*>(attr->getValue());
|
||||
|
||||
// Prefix the name with an @, to differentiate it from an element
|
||||
std::string newName ("@"); newName += name;
|
||||
@ -201,7 +202,8 @@ static DOMAttr* BuildDOMAttr(DOMDocument* doc, const XMLCh* name, AtNode::Ptr p)
|
||||
|
||||
DOMAttr* attr = doc->createAttribute(name);
|
||||
|
||||
attr->setValue(p->value.c_str());
|
||||
// TODO: make work on GCC
|
||||
attr->setValue(reinterpret_cast<const XMLCh*>(p->value.c_str()));
|
||||
|
||||
return attr;
|
||||
}
|
||||
@ -215,7 +217,7 @@ static DOMNode* BuildDOMNode(DOMDocument* doc, const XMLCh* name, AtNode::Ptr p)
|
||||
{
|
||||
// TODO: make this work on GCC
|
||||
if (p->value.length())
|
||||
node->setTextContent(p->value.c_str());
|
||||
node->setTextContent(reinterpret_cast<const XMLCh*>(p->value.c_str()));
|
||||
|
||||
XMLCh tempStr[256]; // urgh, nasty fixed-size buffer
|
||||
for (AtNode::child_maptype::const_iterator it = p->children.begin(); it != p->children.end(); ++it)
|
||||
|
@ -4,6 +4,12 @@
|
||||
# define HAVE_PCH
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Please shut up about all the deprecations
|
||||
# define _CRT_SECURE_NO_DEPRECATE
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PCH
|
||||
|
||||
// Exclude rarely-used stuff from Windows headers
|
||||
@ -37,8 +43,8 @@
|
||||
|
||||
// Nicer memory-leak detection:
|
||||
#ifdef _DEBUG
|
||||
#include <crtdbg.h>
|
||||
#define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
|
||||
# include <crtdbg.h>
|
||||
# define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#endif // HAVE_PCH
|
||||
|
@ -482,7 +482,8 @@ private:
|
||||
std::wstring errorText;
|
||||
void complain(const SAXParseException& err, const wchar_t* severity) {
|
||||
sawErrors = true;
|
||||
errorText += (std::wstring)L"XML "+severity+L": "+ err.getSystemId() + L" / " + err.getMessage();
|
||||
C_ASSERT(sizeof(wchar_t) == sizeof(XMLCh));
|
||||
errorText += (std::wstring)L"XML "+severity+L": "+ (wchar_t*)err.getSystemId() + L" / " + (wchar_t*)err.getMessage();
|
||||
}
|
||||
};
|
||||
|
||||
@ -569,7 +570,7 @@ void XeroHandler::endDocument()
|
||||
|
||||
void XeroHandler::startElement(const XMLCh* const /*uri*/, const XMLCh* const localname, const XMLCh* const /*qname*/, const Attributes& attrs)
|
||||
{
|
||||
utf16string elementName = localname;
|
||||
utf16string elementName = (utf16_t*)localname;
|
||||
|
||||
// Create a new element
|
||||
XMLElement* e = new XMLElement;
|
||||
@ -579,10 +580,10 @@ void XeroHandler::startElement(const XMLCh* const /*uri*/, const XMLCh* const lo
|
||||
// Store all the attributes in the new element
|
||||
for (unsigned int i = 0; i < attrs.getLength(); ++i)
|
||||
{
|
||||
utf16string attrName = attrs.getLocalName(i);
|
||||
utf16string attrName = (utf16_t*)attrs.getLocalName(i);
|
||||
XMLAttribute attr;
|
||||
attr.name = attrName;
|
||||
attr.value = attrs.getValue(i);
|
||||
attr.value = (utf16_t*)attrs.getValue(i);
|
||||
e->attrs.push_back(attr);
|
||||
}
|
||||
|
||||
@ -628,5 +629,5 @@ void XeroHandler::endElement(const XMLCh* const /*uri*/, const XMLCh* const /*lo
|
||||
|
||||
void XeroHandler::characters(const XMLCh* const chars, const unsigned int length)
|
||||
{
|
||||
ElementStack.top()->text += utf16string(chars, length);
|
||||
ElementStack.top()->text += utf16string((utf16_t*)chars, length);
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
# define HAVE_PCH
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define _SCL_SECURE_NO_DEPRECATE // shut up, std::copy isn't deprecated
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PCH
|
||||
|
||||
// Exclude rarely-used stuff from Windows headers
|
||||
|
@ -7,16 +7,55 @@
|
||||
#include "graphics/Terrain.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "maths/MathUtil.h"
|
||||
#include "renderer/TerrainOverlay.h"
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
class BrushTerrainOverlay : public TerrainOverlay
|
||||
{
|
||||
public:
|
||||
BrushTerrainOverlay(const Brush* brush)
|
||||
: TerrainOverlay(300), m_Brush(brush)
|
||||
{
|
||||
}
|
||||
|
||||
void GetTileExtents(
|
||||
int& min_i_inclusive, int& min_j_inclusive,
|
||||
int& max_i_inclusive, int& max_j_inclusive)
|
||||
{
|
||||
m_Brush->GetBottomLeft(min_i_inclusive, min_j_inclusive);
|
||||
m_Brush->GetTopRight(max_i_inclusive, max_j_inclusive);
|
||||
|
||||
// But since brushes deal with vertices instead of tiles,
|
||||
// we don't want to include the top/right row
|
||||
--max_i_inclusive;
|
||||
--max_j_inclusive;
|
||||
}
|
||||
|
||||
void ProcessTile(int i, int j)
|
||||
{
|
||||
int i0, j0;
|
||||
m_Brush->GetBottomLeft(i0, j0);
|
||||
// Colour this tile based on the average of the surrounding vertices
|
||||
float avg = (
|
||||
m_Brush->Get(i-i0, j-j0) + m_Brush->Get(i-i0+1, j-j0) +
|
||||
m_Brush->Get(i-i0, j-j0+1) + m_Brush->Get(i-i0+1, j-j0+1)
|
||||
) / 4.f;
|
||||
RenderTile(CColor(0, 1, 0, avg*0.8f), false);
|
||||
RenderTileOutline(CColor(1, 1, 1, 0.4f), 1, true);
|
||||
}
|
||||
|
||||
const AtlasMessage::Brush* m_Brush;
|
||||
};
|
||||
|
||||
Brush::Brush()
|
||||
: m_W(0), m_H(0), m_Data(NULL), m_Enabled(false)
|
||||
: m_W(0), m_H(0), m_TerrainOverlay(NULL), m_Data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Brush::~Brush()
|
||||
{
|
||||
delete m_TerrainOverlay;
|
||||
delete[] m_Data;
|
||||
}
|
||||
|
||||
@ -41,49 +80,31 @@ void Brush::GetCentre(int& x, int& y) const
|
||||
y = cy;
|
||||
}
|
||||
|
||||
void Brush::GetBottomRight(int& x, int& y) const
|
||||
void Brush::GetBottomLeft(int& x, int& y) const
|
||||
{
|
||||
GetCentre(x, y);
|
||||
x -= (m_W-1)/2;
|
||||
y -= (m_H-1)/2;
|
||||
}
|
||||
|
||||
void Brush::SetRenderEnabled(bool enabled)
|
||||
void Brush::GetTopRight(int& x, int& y) const
|
||||
{
|
||||
m_Enabled = enabled;
|
||||
GetBottomLeft(x, y);
|
||||
x += m_W-1;
|
||||
y += m_H-1;
|
||||
}
|
||||
|
||||
void Brush::Render()
|
||||
void Brush::SetRenderEnabled(bool enabled)
|
||||
{
|
||||
if (! m_Enabled)
|
||||
return;
|
||||
|
||||
glPointSize(4.f); // TODO: does this clobber state that other people expect to stay unchanged?
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
int x0, y0;
|
||||
GetBottomRight(x0, y0);
|
||||
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
|
||||
for (int dy = 0; dy < m_H; ++dy)
|
||||
if (enabled && !m_TerrainOverlay)
|
||||
{
|
||||
for (int dx = 0; dx < m_W; ++dx)
|
||||
{
|
||||
glColor3f(0.f, clamp(m_Data[dx + dy*m_W], 0.f, 1.f), 0.f);
|
||||
|
||||
CVector3D pos;
|
||||
terrain->CalcPosition(x0+dx, y0+dy, pos);
|
||||
glVertex3f(pos.X, pos.Y, pos.Z);
|
||||
//debug_printf("%f %f %f\n", pos.X, pos.Y, pos.Z);
|
||||
}
|
||||
m_TerrainOverlay = new BrushTerrainOverlay(this);
|
||||
}
|
||||
else if (!enabled && m_TerrainOverlay)
|
||||
{
|
||||
delete m_TerrainOverlay;
|
||||
m_TerrainOverlay = NULL;
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
Brush AtlasMessage::g_CurrentBrush;
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "maths/Vector3D.h"
|
||||
|
||||
class TerrainOverlay;
|
||||
|
||||
namespace AtlasMessage {
|
||||
|
||||
struct Brush
|
||||
@ -10,10 +12,10 @@ struct Brush
|
||||
void SetData(int w, int h, const float* data);
|
||||
|
||||
void SetRenderEnabled(bool enabled); // initial state is disabled
|
||||
void Render(); // only does anything if enabled
|
||||
|
||||
void GetCentre(int& x, int& y) const;
|
||||
void GetBottomRight(int& x, int& y) const;
|
||||
void GetBottomLeft(int& x, int& y) const;
|
||||
void GetTopRight(int& x, int& y) const;
|
||||
|
||||
float Get(int x, int y) const
|
||||
{
|
||||
@ -24,8 +26,8 @@ struct Brush
|
||||
int m_W, m_H;
|
||||
CVector3D m_Centre;
|
||||
private:
|
||||
TerrainOverlay* m_TerrainOverlay; // NULL if rendering is not enabled
|
||||
const float* m_Data;
|
||||
bool m_Enabled;
|
||||
};
|
||||
|
||||
extern Brush g_CurrentBrush;
|
||||
|
@ -31,7 +31,6 @@ namespace AtlasMessage
|
||||
void AtlasRender()
|
||||
{
|
||||
Render();
|
||||
g_CurrentBrush.Render();
|
||||
AtlasRenderSelection();
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ BEGIN_COMMAND(AlterElevation)
|
||||
previousPosition = g_CurrentBrush.m_Centre;
|
||||
|
||||
int x0, y0;
|
||||
g_CurrentBrush.GetBottomRight(x0, y0);
|
||||
g_CurrentBrush.GetBottomLeft(x0, y0);
|
||||
|
||||
for (int dy = 0; dy < g_CurrentBrush.m_H; ++dy)
|
||||
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
||||
@ -171,7 +171,7 @@ BEGIN_COMMAND(FlattenElevation)
|
||||
u16 height = m_TerrainDelta.GetVertex(xc, yc);
|
||||
|
||||
int x0, y0;
|
||||
g_CurrentBrush.GetBottomRight(x0, y0);
|
||||
g_CurrentBrush.GetBottomLeft(x0, y0);
|
||||
|
||||
for (int dy = 0; dy < g_CurrentBrush.m_H; ++dy)
|
||||
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
||||
|
@ -163,7 +163,7 @@ BEGIN_COMMAND(PaintTerrain)
|
||||
d->pos.GetWorldSpace(g_CurrentBrush.m_Centre);
|
||||
|
||||
int x0, y0;
|
||||
g_CurrentBrush.GetBottomRight(x0, y0);
|
||||
g_CurrentBrush.GetBottomLeft(x0, y0);
|
||||
|
||||
CTextureEntry* texentry = g_TexMan.FindTexture(CStrW(d->texture));
|
||||
if (! texentry)
|
||||
|
Loading…
Reference in New Issue
Block a user