?? landscape.cpp.svn-base
字號:
#include "LandScape.h"
#include <windows.h>
#include <GL/gl.h>
#include "gamedata.h"
unsigned char *LandScape::m_HeightMap;
int LandScape::m_MapSize;
LandScape::LandScape(void)
{
}
LandScape::~LandScape(void)
{
// if(m_HeightMap) delete m_HeightMap;
// if(m_TriPool) delete m_TriPool;
// if(m_Patches) delete m_Patches;
}
// ---------------------------------------------------------------------
// Points p1, p2, & p3 specified in counter clock-wise order
//
void calcNormal(float v[3][3], float out[3])
{
float v1[3],v2[3];
static const int x = 0;
static const int y = 1;
static const int z = 2;
// Calculate two vectors from the three points
v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];
v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];
// Take the cross product of the two vectors to get
// the normal vector which will be stored in out
out[x] = v1[y]*v2[z] - v1[z]*v2[y];
out[y] = v1[z]*v2[x] - v1[x]*v2[z];
out[z] = v1[x]*v2[y] - v1[y]*v2[x];
}
void LandScape::ComputeNormal(int x,int y, Vertex *out)
{
if(x<=0 || x>=m_MapSize || y<=0 ||y >=m_MapSize) return;
float z[5];
z[0] = m_HeightMap[x+y*m_MapSize];
z[1] = m_HeightMap[x-1+y*m_MapSize];
z[2] = m_HeightMap[x+(y+1)*m_MapSize];
z[3] = m_HeightMap[x+1+y*m_MapSize];
z[4] = m_HeightMap[x+(y-1)*m_MapSize];
float v[4][3][3] = {
{{x,y,z[0]},{x-1,y,z[1]},{x,y+1,z[2]}},
{{x,y,z[0]},{x,y+1,z[2]},{x+1,y,z[3]}},
{{x,y,z[0]},{x+1,y,z[3]},{x,y-1,z[4]}},
{{x,y,z[0]},{x,y-1,z[4]},{x-1,y,z[1]}}};
float vector[4][3];
for(int i=0;i<4;++i)
calcNormal(v[i], vector[i]);
out->x = vector[0][0]+vector[1][0]+vector[2][0]+vector[3][0];
out->y = vector[0][1]+vector[1][1]+vector[2][1]+vector[3][1];
out->z = vector[0][2]+vector[1][2]+vector[2][2]+vector[3][2];
}
//***********************
//Initialize all Patches
//
void LandScape::Init(unsigned char *hMap,int mapSize )
{
Patch *patch;
int X,Y;
// Initialize all terrain data
m_TriPool = new TriPool(SIZE_TRIPOOL);
m_HeightMap = hMap;
m_MapSize = mapSize;
m_Vectors = (Vertex*)malloc(sizeof(Vertex)*m_MapSize*m_MapSize);
m_Patches = new Patch[NUM_PATCHES_PER_SIDE*NUM_PATCHES_PER_SIDE];
// Initialize all terrain patches
for(X=0;X<NUM_PATCHES_PER_SIDE;++X)
for(Y=0;Y<NUM_PATCHES_PER_SIDE;++Y)
{
patch = &m_Patches[NUM_PATCHES_PER_SIDE*X+Y];
patch->Init(Y*PATCH_SIZE,X*PATCH_SIZE,Y*PATCH_SIZE,X*PATCH_SIZE,m_HeightMap,mapSize,m_Vectors,m_TriPool);
patch->ComputeVariance();
}
// for(X=0;X<m_MapSize;++X)
// for(Y=0;Y<m_MapSize;++Y)
// ComputeNormal(X,Y, &m_Vectors[X+m_MapSize*Y]);
}
//************************
// reset all Patches ,recompute Variance
//
void LandScape::Reset()
{
//
// Perform simple visibility culling on entire patches.
// - Define a triangle set back from the camera by one patch size, following
// the angle of the frustum.
// - A patch is visible if it's center point is included in the angle: Left,Eye,Right
// - This visibility test is only accurate if the camera cannot look up or down significantly.
//
/* const float PI_DIV_180 = M_PI / 180.0f;
const float FOV_DIV_2 = gFovX/2;
int eyeX = (int)(gViewPosition[0] - PATCH_SIZE * sinf( gClipAngle * PI_DIV_180 ));
int eyeY = (int)(gViewPosition[2] + PATCH_SIZE * cosf( gClipAngle * PI_DIV_180 ));
int leftX = (int)(eyeX + 100.0f * sinf( (gClipAngle-FOV_DIV_2) * PI_DIV_180 ));
int leftY = (int)(eyeY - 100.0f * cosf( (gClipAngle-FOV_DIV_2) * PI_DIV_180 ));
int rightX = (int)(eyeX + 100.0f * sinf( (gClipAngle+FOV_DIV_2) * PI_DIV_180 ));
int rightY = (int)(eyeY - 100.0f * cosf( (gClipAngle+FOV_DIV_2) * PI_DIV_180 ));
*/
int X, Y;
Patch *patch;
// Set the next free triangle pointer back to the beginning
m_TriPool->SetNextTriNode(0);
// Go through the patches performing resets, compute variances, and linking.
for ( Y=0; Y < NUM_PATCHES_PER_SIDE; Y++ )
for ( X=0; X < NUM_PATCHES_PER_SIDE; X++)
{
patch = &(m_Patches[Y*NUM_PATCHES_PER_SIDE+X]);
// Reset the patch
patch->Reset();
patch->SetVisibility( );
// Check to see if this patch has been deformed since last frame.
// If so, recompute the varience tree for it.
if ( patch->isDirty() )
patch->ComputeVariance();
if ( patch->isVisibile() )
{
// Link all the patches together.
if ( X > 0 )
patch->GetBaseLeft()->LeftNeighbor = m_Patches[Y*NUM_PATCHES_PER_SIDE+X-1].GetBaseRight();
else
patch->GetBaseLeft()->LeftNeighbor = NULL; // Link to bordering Landscape here..
if ( X < (NUM_PATCHES_PER_SIDE-1) )
patch->GetBaseRight()->LeftNeighbor = m_Patches[Y*NUM_PATCHES_PER_SIDE+X+1].GetBaseLeft();
else
patch->GetBaseRight()->LeftNeighbor = NULL; // Link to bordering Landscape here..
if ( Y > 0 )
patch->GetBaseLeft()->RightNeighbor = m_Patches[(Y-1)*NUM_PATCHES_PER_SIDE+X].GetBaseRight();
else
patch->GetBaseLeft()->RightNeighbor = NULL; // Link to bordering Landscape here..
if ( Y < (NUM_PATCHES_PER_SIDE-1) )
patch->GetBaseRight()->RightNeighbor = m_Patches[(Y+1)*NUM_PATCHES_PER_SIDE+X].GetBaseLeft();
else
patch->GetBaseRight()->RightNeighbor = NULL; // Link to bordering Landscape here..
}
}
}
// ---------------------------------------------------------------------
// Create an approximate mesh of the landscape.
//
void LandScape::Tessellate()
{
// Perform Tessellation
Patch *patch = &(m_Patches[0]);
for (int i=0; i < NUM_PATCHES_PER_SIDE*NUM_PATCHES_PER_SIDE; i++, patch++ )
{
if (patch->isVisibile())
patch->Tessellate( );
}
}
// ---------------------------------------------------------------------
// Render each patch of the landscape & adjust the frame variance.
//
int LandScape::Render()
{
//Number of Triangles
int NumTrisRendered = 0;
int nCount;
Patch *patch = &(m_Patches[0]);
// Store old matrix
glPushMatrix();
// Scale the terrain by the terrain scale specified at compile time.
glScalef( TERRAIN_MULTIPL, MULT_SCALE, TERRAIN_MULTIPL );
glColor3f(1,1,1);
for (nCount=0; nCount < NUM_PATCHES_PER_SIDE*NUM_PATCHES_PER_SIDE; nCount++, patch++ )
{
if (patch->isVisibile())
NumTrisRendered += patch->Render();
}
// Restore the matrix
glPopMatrix();
return NumTrisRendered;
}
// 計算任意點的高度y:
//
// 假設(shè)三角形三個頂點為:A(x1,y1,z1),B(x2,y2,z2),C(x3,y3,z3)
// 則有2變量 u,v 使得三角形上任意點的坐標(x,y,z)滿足:
//
// x = ( 1 - u - v )*x1 +u*x2 +v*x3; (1)
//
// 對于y,z亦如此
//
// 應(yīng)此可以根據(jù)三角形上點D的x,z坐標計算出u,v變量的值,
// 然后用y,y1,y2,y3代入公式(1)計算出D點的y值
//
float LandScape::GetY(float xp,float zp)
{
float x = xp/TERRAIN_MULTIPL;
float z = zp/TERRAIN_MULTIPL;
//如果超出地圖范圍,返回0
if(x<0 || x>m_MapSize*TERRAIN_MULTIPL || z<0 || z>m_MapSize*TERRAIN_MULTIPL)
return 0;
//(x,z)點所在三角形的3個頂點坐標
float x1,x2,x3,y1,y2,y3,z1,z2,z3;
//(x,z)點所在方格的左下頂點x,z坐標
int intx,intz;
//u,v變量
float u,v;
//(x,z)點對應(yīng)高度y
float y;
intx = (int)x;
intz = (int)z;
//計算點所在三角形3頂點坐標
x1 = intx+1;
z1 = intz;
y1 = m_HeightMap[(int)(x1+z1*m_MapSize)];
x2 = intx;
z2 = intz+1;
y2 = m_HeightMap[int(x2+z2*m_MapSize)];
if( x-intx + z-intz >1 )
{
x3 = intx+1;
z3 = intz+1;
}
else
{
x3 = intx;
z3 = intz;
}
y3 = m_HeightMap[(int)(x3+z3*m_MapSize)];
//根據(jù)三角形三頂點坐標和點的x,z坐標計算u,v變量的值
v = (z1*(x-x2)+z2*(x1-x)+z*(x2-x1))/(x1*z2-x1*z3-x2*z1+x2*z3+x3*z1-x3*z2);
u = (x-x1+v*(x1-x3))/(x2-x1);
//計算點的y值
y = (1-u-v)*y1+u*y2+v*y3;
return y;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -