Original Post
I need some help on rendering my wireframe terrain. On the face of it things seem fine, but if you look closely the terrain seems to be rendered four times, in four slightly different positions. Also the small separation between the different renderings increases with car speed. Any ideas? cheers in advance Heres the code that calls the terrain to be rendered
void
CarDemo::MainWindow::DrawScene(GUI::DrawListenerMessage& msg)
{
timer.Update();
deltaT = timer.Average();
fpsCounter->Update();
car->Update(deltaT);
glLoadIdentity();
GameX::GetEngine()->Load3DMatrix();
camera->focalPoint = car->position;
camera->LoadMatrix();
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_LIGHTING);
car->Render();
glDisable(GL_LIGHTING);
terrain->Render(camera->focalPoint);
glPopAttrib();
}
#include <stdio.h>
#include "GameX/GLHeaders.h"
#include "Terrain.h"
#include "GameX/LogFile.h"
// For now this is a simple **hard-coded** terrain
// The terrain was actually generated using Fourier
// techniques in Matlab and stored in a raw data file: 64x64x(1byte)
GameX::CLogFile logFile("terrain.log");
Terrain::Terrain()
: dataSize(64) // Hard coded for now
, drawSize(30) // Only 30x30 of the map is drawn
, hScale(100) // Height Scale
, xScale(10.0) // scale the map in the x direction by 10.0
, yScale(10.0) // scale the map in the y direction by 10.0
, data(NULL)
{
ReadMap("data//terrain64x64.raw", dataSize);
}
Terrain::~Terrain()
{
if (data) delete [] data;
}
unsigned int
Terrain::Size()
{
return dataSize;
}
void
Terrain::ReadMap(const char* filename, int N)
{
FILE* file = fopen(filename,"rb");
if (file)
{
data = new float[N*N];
for (int i=0; i<N*N; i++)
{
unsigned char tmp;
fread(&tmp, 1,1, file);
data = (float)tmp / 255;
}
}
fclose(file);
}
// Render the terrain.
// 'origin' is point where the 3rd person camera
// is centred about.
void
Terrain::Render(GameX::CVector origin)
{
// Calc the total (horiz) length of the lines (as the crow flies)
float xLineLength = xScale*drawSize;
float yLineLength = yScale*drawSize;
// Calc the starting i,j coordinates in the map
int iStart = floor((origin.x - xLineLength*0.5)/xScale);
int jStart = floor((origin.y - yLineLength*0.5)/yScale);
// Calc where to start drawing from
float xStart = iStart*xScale;
float yStart = jStart*yScale;
// Wrap the i,j values so that the map
// repeats infinitely
iStart = iStart % dataSize;
jStart = jStart % dataSize;
float x, y;
//==============================
// Draw lines in the x-direction
//==============================
for(int j=jStart, y=yStart; j < (drawSize+jStart); j++, y+=yScale)
{
glBegin(GL_LINE_STRIP);
for(int i=iStart, x=xStart; i < (drawSize+iStart); i++, x+=xScale)
{
// Fade the colour with distance
float color = 0.8 - 1.0*fabs(origin.x - x) / xLineLength;
glColor3f(color, color, color);
glVertex3f(x,y,Height(i,j));
}
glEnd();
}
//==============================
// Draw lines in the y-direction
//==============================
for(int i=iStart, x=xStart; i < (drawSize+iStart); i++, x+=xScale)
{
glBegin(GL_LINE_STRIP);
for(int j=jStart, y=yStart; j < (drawSize+jStart); j++, y+=yScale)
{
// Fade the colour with distance
float color = 0.8 - 1.0*fabs(origin.y - y) / yLineLength;
glColor3f(color, color, color);
glVertex3f(x,y,Height(i,j));
}
glEnd();
}
}
float
Terrain::Height(int x, int y)
{
x %= dataSize;
y %= dataSize;
return data[x + y*dataSize]*hScale;
}
void
Terrain::HeightAndNormal(float x, float y, float& height, GameX::CVector& normal)
{
// 2D lerping
x = x / xScale;
y = y / yScale;
int i = floor(x);
int j = floor(y);
float s2 = x - i;
float s1 = 1 - s2;
float t2 = y - j;
float t1 = 1 - t2;
float h1 = Height(i,j);
float h2 = Height(i+1,j);
float h3 = Height(i,j+1);
float h4 = Height(i+1,j+1);
float top = s1*h1 + s2*h2;
float bottom = s1*h3 + s2*h4;
height = t1*top + t2*bottom;
// Calc the normal by taking the average of two corners
GameX::CVector a(0,0,h1);
GameX::CVector b(xScale,0,h2);
GameX::CVector c(0,yScale,h3);
GameX::CVector d(xScale,yScale,h4);
normal = (b-a).Cross(c-a).UnitVec()*0.5 + (c-d).Cross(b-d).UnitVec()*0.5;
}