engine/src/SimpleLand/SimpleLand.cpp
2013-01-19 20:02:34 +00:00

826 lines
22 KiB
C++
Raw Blame History

#include "include/Engine.h"
namespace SE
{
const float CONST_LAND_Y_LIMIT = 15.0f;
//Limit for y pos of land (edge or trench/dip)
const float CONST_MIN_COS_BETWEEN_CURSOR_AND_VERTEX = 0.99f;
//See CalcCrossing() for explanation
TSimpleLandClass::TSimpleLandClass()
: Width(CONST_DEFAULT_LAND_WIDTH),
Height(CONST_DEFAULT_LAND_HEIGHT),
CellInterval(CONST_DEFAULT_LAND_CELL_INVERVAL),
TexID(0),
NormTexID(0)
{
int k;
VertexMatrix.resize(Width*Height);
for (int i=0; i<Height; i++)
for (int j=0; j<Width; j++)
{
k = j + i*Width;
VertexMatrix[k].norm = vec3(0.0f, 1.0f, 0.0f);
VertexMatrix[k].tangent = vec3(0.0f, 0.0f, 1.0f);
VertexMatrix[k].binorm = vec3(1.0f, 0.0f, 0.0f);
VertexMatrix[k].pos = vec3(
j*CellInterval - (CellInterval*Width)/2.0f,
1.0f,
i*CellInterval - (CellInterval*Height)/2.0f);
VertexMatrix[k].landtype = rand() % 2;
}
TriangleMatrix.resize(2*(Width-1)*(Height-1));
UpdateTriangleMatrix();
CreateVBO();
}
TSimpleLandClass::~TSimpleLandClass()
{
FreeVBO();
TriangleMatrix.clear();
VertexMatrix.clear();
if (TexID != 0)
{
ResourceManager->TexList.DeleteTexture(TexID);
TexID = 0;
}
if (NormTexID != 0)
{
ResourceManager->TexList.DeleteTexture(NormTexID);
NormTexID = 0;
}
}
void TSimpleLandClass::CreateVBO()
{
IndexArr.resize(6*(Width-1)*(Height-1));
//VBOLandVertexArr.resize(Width*Height);
VBOLandVertexArr.pos.resize(Width * Height);
VBOLandVertexArr.norm.resize(Width * Height);
VBOLandVertexArr.tangent.resize(Width * Height);
VBOLandVertexArr.binorm.resize(Width * Height);
VBOLandVertexArr.texCoord.resize(Width * Height);
for (int i = 0; i < Height-1; i++)
for (int j = 0; j < Width-1; j++)
{
IndexArr[6*(j + i*(Width-1))] = j + i*(Width);
IndexArr[6*(j + i*(Width-1)) + 1] = j + 1 + i*(Width);
IndexArr[6*(j + i*(Width-1)) + 2] = Width + j + i*(Width);
IndexArr[6*(j + i*(Width-1)) + 3] = j + 1 + i*(Width);
IndexArr[6*(j + i*(Width-1)) + 4] = Width + 1 + j + i*(Width);
IndexArr[6*(j + i*(Width-1)) + 5] = Width + j + i*(Width);
}
for (int i = 0; i < Height-1; i++)
for (int j = 0; j < Width-1; j++)
{
VBOLandVertexArr.pos[j + i*Width] = VertexMatrix[j + i*Width].pos;
VBOLandVertexArr.norm[j + i*Width] = VertexMatrix[j + i*Width].norm;
VBOLandVertexArr.tangent[j + i*Width] = VertexMatrix[j + i*Width].tangent;
VBOLandVertexArr.binorm[j + i*Width] = VertexMatrix[j + i*Width].binorm;
VBOLandVertexArr.texCoord[j + i*Width].v[0] = float(j) / Width;
VBOLandVertexArr.texCoord[j + i*Width].v[1] = float(i) / Height;
}
#ifdef TARGET_WIN32
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*(Width-1)*(Height-1)*4, &IndexArr[0], GL_STATIC_DRAW);
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, Width * Height * sizeof(vec3), &(VBOLandVertexArr.pos[0]), GL_STATIC_DRAW);
glGenBuffers(1, &NormBuffer);
glBindBuffer(GL_ARRAY_BUFFER, NormBuffer);
glBufferData(GL_ARRAY_BUFFER, Width * Height * sizeof(vec3), &(VBOLandVertexArr.norm[0]), GL_STATIC_DRAW);
glGenBuffers(1, &TangentBuffer);
glBindBuffer(GL_ARRAY_BUFFER, TangentBuffer);
glBufferData(GL_ARRAY_BUFFER, Width * Height * sizeof(vec3), &(VBOLandVertexArr.tangent[0]), GL_STATIC_DRAW);
glGenBuffers(1, &BinormBuffer);
glBindBuffer(GL_ARRAY_BUFFER, BinormBuffer);
glBufferData(GL_ARRAY_BUFFER, Width * Height * sizeof(vec3), &(VBOLandVertexArr.binorm[0]), GL_STATIC_DRAW);
glGenBuffers(1, &TexcoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, TexcoordBuffer);
glBufferData(GL_ARRAY_BUFFER, Width * Height * sizeof(vec2), &(VBOLandVertexArr.texCoord[0]), GL_STATIC_DRAW);
#endif
}
void TSimpleLandClass::FreeVBO()
{
#ifdef TARGET_WIN32
glDeleteBuffers(1, &VertexBuffer);
glDeleteBuffers(1, &NormBuffer);
glDeleteBuffers(1, &TangentBuffer);
glDeleteBuffers(1, &BinormBuffer);
glDeleteBuffers(1, &TexcoordBuffer);
glDeleteBuffers(1, &IndexBuffer);
#endif
VBOLandVertexArr.pos.clear();
VBOLandVertexArr.norm.clear();
VBOLandVertexArr.tangent.clear();
VBOLandVertexArr.binorm.clear();
VBOLandVertexArr.texCoord.clear();
IndexArr.clear();
}
void TSimpleLandClass::UpdateVBO()
{
//Index array remains the same - only vertex array is to be changed
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
VBOLandVertexArr.pos[j + i*Width] = VertexMatrix[j + i*Width].pos;
VBOLandVertexArr.norm[j + i*Width] = VertexMatrix[j + i*Width].norm;
VBOLandVertexArr.tangent[j + i*Width] = VertexMatrix[j + i*Width].tangent;
VBOLandVertexArr.binorm[j + i*Width] = VertexMatrix[j + i*Width].binorm;
VBOLandVertexArr.texCoord[j + i*Width].v[0] = float(j) / Width;
VBOLandVertexArr.texCoord[j + i*Width].v[1] = float(i) / Height;
}
}
#ifdef TARGET_WIN32
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, Width * Height * sizeof(vec3), &(VBOLandVertexArr.pos[0]));
glBindBuffer(GL_ARRAY_BUFFER, NormBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, Width * Height * sizeof(vec3), &(VBOLandVertexArr.norm[0]));
glBindBuffer(GL_ARRAY_BUFFER, TangentBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, Width * Height * sizeof(vec3), &(VBOLandVertexArr.tangent[0]));
glBindBuffer(GL_ARRAY_BUFFER, BinormBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, Width * Height * sizeof(vec3), &(VBOLandVertexArr.binorm[0]));
glBindBuffer(GL_ARRAY_BUFFER, TexcoordBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, Width * Height * sizeof(vec2), &(VBOLandVertexArr.texCoord[0]));
#endif
}
vec3 TSimpleLandClass::CalcCrossingForPoint(const vec3& pos, int i, int j)
{
vec3 lineFrom = pos;
vec3 lineTo = pos;
lineFrom.v[1] = CONST_LAND_Y_LIMIT;
lineTo.v[1] = -CONST_LAND_Y_LIMIT;
vec3 r = CalcCrossingForPoint(lineFrom, lineTo, i, j);
if (r == lineFrom)
return pos;
return r;
}
vec3 TSimpleLandClass::CalcCrossingForPoint(const vec3& lineFrom,const vec3& lineTo, int i, int j)
{
if (i >= Height-1 || i < 0 || j >= Width-1 || j < 0)
return lineFrom;
TSmpTriangle tr;
vec3 r;
tr.p[0] = VertexMatrix[j + i*Width].pos;
tr.p[1] = VertexMatrix[(j+1) + i*Width].pos;
tr.p[2] = VertexMatrix[(j+1) + (i+1)*Width].pos;
tr.v = tr.p[1] - tr.p[0];
tr.w = tr.p[2] - tr.p[1];
tr.n = CrossProduct(tr.v, tr.w);
if (LineCrossTriangle(lineFrom, lineTo, tr, r) == 1)
return r;
tr.p[0] = VertexMatrix[j + i*Width].pos;
tr.p[1] = VertexMatrix[j + (i+1)*Width].pos;
tr.p[2] = VertexMatrix[(j+1) + (i+1)*Width].pos;
tr.v = tr.p[1] - tr.p[0];
tr.w = tr.p[2] - tr.p[1];
tr.n = CrossProduct(tr.v, tr.w);
if (LineCrossTriangle(lineFrom, lineTo, tr, r) == 1)
return r;
return lineFrom;
}
bool TSimpleLandClass::LoadFromFile(const std::string& filename)
{
cardinal dwordCount;
boost::shared_array<cardinal> fileArr = CreateMemFromFile<cardinal>((ResourceManager->PathToResources + filename).c_str(), dwordCount);
if ((((char*)&fileArr[0])[0]!='L')||
(((char*)&fileArr[0])[1]!='S')||
(((char*)&fileArr[0])[2]!=0)||
(((char*)&fileArr[0])[3]!=1))
throw ErrorFileNotCorrect(filename);
Width = fileArr[1];
Height = fileArr[2];
CellInterval = ((float*)&fileArr[0])[3];
std::vector<TSimpleLandVertex> tempVertexMatrix;
tempVertexMatrix.resize(Width*Height);
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
{
int k = j + i * Width;
tempVertexMatrix[k] = ((TSimpleLandVertex*)(&fileArr[0] + 4))[k];
}
//Replace old matrices with new
TriangleMatrix.resize(2*(Width-1)*(Height-1));
VertexMatrix = tempVertexMatrix;
UpdateTriangleMatrix();
RecalcNormalVectors();
FreeVBO();
CreateVBO();
return true;
}
void TSimpleLandClass::SaveToFile(char* filename)
{
//NIU
//Need to clean up
#ifdef TARGET_WIN32
OFSTRUCT ofstruct;
DWORD FSize;
DWORD BytesWriten;
char* FileArr;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
HANDLE h=(HANDLE)OpenFile(filename,&ofstruct,OF_CREATE);
FSize = 16 + Width*Height*sizeof(TSimpleLandVertex);
FileArr = new char [FSize];
FileArr[0] = 'L';
FileArr[1] = 'S';
FileArr[2] = 0;
FileArr[3] = 1;
((int*)FileArr)[1] = Width;
((int*)FileArr)[2] = Height;
((float*)FileArr)[3] = CellInterval;
int k;
for (int i=0;i<Height;i++)
for (int j=0;j<Width;j++)
{
k = j+i*Width;
((TSimpleLandVertex*)(FileArr + 16))[k] = VertexMatrix[k];
}
WriteFile(h,FileArr,FSize,&BytesWriten,NULL);
delete [] FileArr;
CloseHandle(h);
#endif
}
void TSimpleLandClass::SetTexture(const std::string& texFilename)
{
if (TexID != 0)
{
ResourceManager->TexList.DeleteTexture(TexID);
}
TexID = ResourceManager->TexList.AddTexture(texFilename);
}
void TSimpleLandClass::SetNormTexture(const std::string& normTexFilename)
{
if (NormTexID != 0)
{
ResourceManager->TexList.DeleteTexture(NormTexID);
}
NormTexID = ResourceManager->TexList.AddTexture(normTexFilename);
}
void TSimpleLandClass::DrawImmediate()
{
//Need to speed up!
#ifdef TARGET_WIN32
int i, j, k, k_up, k_right, k_right_up;
if (NormTexID == 0)
{
RenderUniform1i(CONST_STRING_NORMALMAPEXISTS_UNIFORM, 0);
}
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,WhiteColor);
RenderUniformMatrix3fv(CONST_STRING_MODELROTATEMATRIX_UNIFORM, false, (float*)IdentityMatrix.m);
RenderUniform3fv(CONST_STRING_MODELTRANSLATEVECTOR_UNIFORM, (float*)ZeroVec3.v);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, NormTexID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TexID);
for (i = 0; i < Height-1; i++)
for (j = 0; j < Width-1; j++)
{
k = j + i*Width;
k_right = (j+1) + i*Width;
k_up = j + (i+1)*Width;
k_right_up = (j+1) + (i+1)*Width;
float tx0 = float(j)/(Width-1);
float ty0 = float(i)/(Height-1);
float tx1 = float(j+1)/(Width-1);
float ty1 = float(i+1)/(Height-1);
glBegin(GL_TRIANGLES);
glNormal3fv(VertexMatrix[k].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k].binorm.v);
glTexCoord2f(tx0,ty0);
glVertex3fv(VertexMatrix[k].pos.v);
glNormal3fv(VertexMatrix[k_right].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k_right].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k_right].binorm.v);
glTexCoord2f(tx1,ty0);
glVertex3fv(VertexMatrix[k_right].pos.v);
glNormal3fv(VertexMatrix[k_up].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k_up].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k_up].binorm.v);
glTexCoord2f(tx0,ty1);
glVertex3fv(VertexMatrix[k_up].pos.v);
glEnd();
glBegin(GL_TRIANGLES);
glNormal3fv(VertexMatrix[k_right_up].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k_right_up].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k_right_up].binorm.v);
glTexCoord2f(tx1,ty1);
glVertex3fv(VertexMatrix[k_right_up].pos.v);
glNormal3fv(VertexMatrix[k_up].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k_up].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k_up].binorm.v);
glTexCoord2f(tx0,ty1);
glVertex3fv(VertexMatrix[k_up].pos.v);
glNormal3fv(VertexMatrix[k_right].norm.v);
VertexAttrib3fv(CONST_STRING_TANGENT_ATTRIB, VertexMatrix[k_right].tangent.v);
VertexAttrib3fv(CONST_STRING_BINORMAL_ATTRIB, VertexMatrix[k_right].binorm.v);
glTexCoord2f(tx1,ty0);
glVertex3fv(VertexMatrix[k_right].pos.v);
glEnd();
}
RenderUniform1i(CONST_STRING_NORMALMAPEXISTS_UNIFORM, 1);
#endif
}
void TSimpleLandClass::DrawVBO()
{
//RenderUniform1i(CONST_STRING_NORMALMAPEXISTS_UNIFORM, min<cardinal>(NormTexID, 1));
//RenderUniformMatrix3fv(CONST_STRING_MODELROTATEMATRIX_UNIFORM, false, (float*)IdentityMatrix.m);
//RenderUniform3fv(CONST_STRING_MODELTRANSLATEVECTOR_UNIFORM, (float*)ZeroVec3.v);
if (NormTexID != 0)
{
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,NormTexID);
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,TexID);
#ifdef TARGET_WIN32
glBindBuffer(GL_ARRAY_BUFFER, NormBuffer);
VertexAttribPointer3fv(CONST_STRING_NORMAL_ATTRIB, 0, (char*)NULL);
glBindBuffer(GL_ARRAY_BUFFER, TangentBuffer);
VertexAttribPointer3fv(CONST_STRING_TANGENT_ATTRIB, 0, (char*)NULL);
glBindBuffer(GL_ARRAY_BUFFER, BinormBuffer);
VertexAttribPointer3fv(CONST_STRING_BINORMAL_ATTRIB, 0, (char*)NULL);
glBindBuffer(GL_ARRAY_BUFFER, TexcoordBuffer);
VertexAttribPointer2fv(CONST_STRING_TEXCOORD_ATTRIB, 0, (char*)NULL);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
VertexAttribPointer3fv(CONST_STRING_POSITION_ATTRIB, 0, (char*)NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glDrawElements(GL_TRIANGLES, 6*(Width-1)*(Height-1), GL_UNSIGNED_INT, NULL);
#endif
#ifdef TARGET_ANDROID
VertexAttribPointer3fv(CONST_STRING_NORMAL_ATTRIB, 0, reinterpret_cast<const char*>(&(VBOLandVertexArr.norm[0])));
VertexAttribPointer3fv(CONST_STRING_TANGENT_ATTRIB, 0, reinterpret_cast<const char*>(&(VBOLandVertexArr.tangent[0])));
VertexAttribPointer3fv(CONST_STRING_BINORMAL_ATTRIB, 0, reinterpret_cast<const char*>(&(VBOLandVertexArr.binorm[0])));
VertexAttribPointer2fv(CONST_STRING_TEXCOORD_ATTRIB, 0, reinterpret_cast<const char*>(&(VBOLandVertexArr.texCoord[0])));
VertexAttribPointer3fv(CONST_STRING_POSITION_ATTRIB, 0, reinterpret_cast<const char*>(&(VBOLandVertexArr.pos[0])));
glDrawElements(GL_TRIANGLES, 6*(Width-1)*(Height-1), GL_UNSIGNED_SHORT, &IndexArr[0]);
#endif
RenderUniform1i(CONST_STRING_NORMALMAPEXISTS_UNIFORM,1);
}
vec3 TSimpleLandClass::CalcCrossing(vec3 LineFrom,vec3 LineTo)
{
int i, j;
vec3 CursorVec = Normalize(LineTo - LineFrom);
vec3 CamPos = Renderer->GetCamPos();
for (i = 0; i < Height-1; i++)
for (j = 0; j < Width-1; j++)
{
vec3 CamToVertex = Normalize(VertexMatrix[j + i*Width].pos - CamPos);
float cosA = DotProduct(CamToVertex, CursorVec);
if (cosA > CONST_MIN_COS_BETWEEN_CURSOR_AND_VERTEX)
{
vec3 r = CalcCrossingForPoint(LineFrom, LineTo, i, j);
if (!(r == LineFrom))
return r;
}
}
return LineFrom;
}
vec3 TSimpleLandClass::CalcVerticalCrossing(const vec3& pos)
{
int ir = -1;
int jr = -1;
float xMin = VertexMatrix[0].pos.v[0];
float xMax = VertexMatrix[Width-1].pos.v[0];
float yMin = VertexMatrix[Height*Width-1].pos.v[2];
float yMax = VertexMatrix[0].pos.v[2];
jr = static_cast<int>(floor((Width-1)*(pos.v[0]-xMin)/(xMax - xMin)));
ir = static_cast<int>(floor((Height-1)*(pos.v[2]-yMax)/(yMin - yMax))); //Must be reversed
if (ir < 0 || ir >= Height-1 || jr < 0 || jr >= Width-1)
{
return pos;
}
else
{
vec3 r;
r = CalcCrossingForPoint(pos, ir, jr);
//r = CalcCrossingForPoint(r, ir+1, jr);
//r = CalcCrossingForPoint(r, ir+2, jr);
//r = CalcCrossingForPoint(r, ir-1, jr);
//r = CalcCrossingForPoint(r, ir-2, jr);
return r;
}
}
float TSimpleLandClass::CalcVerticalCrossingFast(const vec3& pos)
{
int ir = -1;
int jr = -1;
float xMin = VertexMatrix[0].pos.v[0];
float xMax = VertexMatrix[Width-1].pos.v[0];
float zMin = VertexMatrix[Height*Width-1].pos.v[2];
float zMax = VertexMatrix[0].pos.v[2];
float w = (xMax - xMin) / (Width-1);
float h = (zMax - zMin) / (Height-1);
jr = int((pos.v[0] - xMin)/w);
ir = (Height-1) - int(ceilf((pos.v[2] - zMin)/h));
if (ir < 0 || ir >= Height-1 || jr < 0 || jr >= Width-1)
{
return pos.v[1];
}
else
{
return max(VertexMatrix[jr + ir*Width].pos.v[1],
max(VertexMatrix[(jr+1) + ir*Width].pos.v[1],
max(VertexMatrix[jr + (ir+1)*Width].pos.v[1],
VertexMatrix[(jr+1) + (ir+1)*Width].pos.v[1])));
}
}
bool TSimpleLandClass::IsOnTheLand(const vec3& pos)
{
float xMin = VertexMatrix[0].pos.v[0];
float xMax = VertexMatrix[Width-1].pos.v[0];
float yMin = VertexMatrix[Height*Width-1].pos.v[2];
float yMax = VertexMatrix[0].pos.v[2];
return (pos.v[0] >= xMin) && (pos.v[0] <= xMax) && (pos.v[2] >= yMin) && (pos.v[2] <= yMax);
}
void TSimpleLandClass::MoveLandUp(vec3 CursorPos,float R)
{
//NIU
int i,j;
vec3 pointpos;
float r,k;
for (i=0;i<Height;i++)
for (j=0;j<Width;j++)
{
pointpos = VertexMatrix[j+i*Width].pos;
r = sqrtf((pointpos.v[0]-CursorPos.v[0])*(pointpos.v[0]-CursorPos.v[0])+(pointpos.v[2]-CursorPos.v[2])*(pointpos.v[2]-CursorPos.v[2]));
if (r<R)
{
k=sqrtf((R-r)/R);
VertexMatrix[j+i*Width].pos.v[1] += k*CONST_LAND_MOVE_STEP;
}
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
void TSimpleLandClass::MoveLandDown(vec3 CursorPos,float R)
{
//NIU
int i,j;
vec3 pointpos;
float r,k;
for (i=0;i<Height;i++)
for (j=0;j<Width;j++)
{
pointpos = VertexMatrix[j+i*Width].pos;
r = sqrtf((pointpos.v[0]-CursorPos.v[0])*(pointpos.v[0]-CursorPos.v[0])+(pointpos.v[2]-CursorPos.v[2])*(pointpos.v[2]-CursorPos.v[2]));
if (r<R)
{
k=sqrtf((R-r)/R);
VertexMatrix[j+i*Width].pos.v[1] -= k*CONST_LAND_MOVE_STEP;
}
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
void TSimpleLandClass::SmoothLand(vec3 CursorPos,float R)
{
//NIU
int i,j;
vec3 pointpos;
float r,k;
float h1,h2,h3,h4;
for (i=0;i<Height;i++)
for (j=0;j<Width;j++)
{
pointpos = VertexMatrix[j+i*Width].pos;
r = sqrtf((pointpos.v[0]-CursorPos.v[0])*(pointpos.v[0]-CursorPos.v[0])+(pointpos.v[2]-CursorPos.v[2])*(pointpos.v[2]-CursorPos.v[2]));
if (r<R)
{
k = sqrtf((R-r)/R);
h1 = (i>0) ? VertexMatrix[j+(i-1)*Width].pos.v[1] : pointpos.v[1];
h2 = (j>0) ? VertexMatrix[j-1+i*Width].pos.v[1] : pointpos.v[1];
h3 = (i<Height-1) ? VertexMatrix[j+(i+1)*Width].pos.v[1] : pointpos.v[1];
h4 = (j<Width-1) ? VertexMatrix[j+1+i*Width].pos.v[1] : pointpos.v[1];
h1 = (h1+h2+h3+h4)/4.0f - pointpos.v[1];
VertexMatrix[j+i*Width].pos.v[1] += h1;
}
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
void TSimpleLandClass::TextureLand(vec3 CursorPos,float R,int ltype)
{
//NIU
int i,j;
vec3 pointpos;
float r;
for (i=0;i<Height;i++)
for (j=0;j<Width;j++)
{
pointpos = VertexMatrix[j+i*Width].pos;
r = sqrtf((pointpos.v[0]-CursorPos.v[0])*(pointpos.v[0]-CursorPos.v[0])+(pointpos.v[2]-CursorPos.v[2])*(pointpos.v[2]-CursorPos.v[2]));
if (r<R)
{
VertexMatrix[j+i*Width].landtype = ltype;
}
}
}
void TSimpleLandClass::Scale(float s)
{
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
{
VertexMatrix[j + i*Width].pos *= s;
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
void TSimpleLandClass::Scale(vec3 s)
{
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
VertexMatrix[j + i*Width].pos.v[0] *= s.v[0];
VertexMatrix[j + i*Width].pos.v[1] *= s.v[1];
VertexMatrix[j + i*Width].pos.v[2] *= s.v[2];
}
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
void TSimpleLandClass::Move(const vec3& v)
{
for (int i = 0; i < Height; i++)
for (int j = 0; j < Width; j++)
{
VertexMatrix[j + i*Width].pos = VertexMatrix[j + i*Width].pos + v;
}
RecalcNormalVectors();
UpdateTriangleMatrix();
UpdateVBO();
}
int TSimpleLandClass::GetWidth()
{
return Width;
};
int TSimpleLandClass::GetHeight()
{
return Height;
};
float* TSimpleLandClass::GetTriangleMatrix()
{
return (float*)&TriangleMatrix[0];
};
void TSimpleLandClass::RecalcNormalVectors()
{
int i,j,ifrom,ito,jfrom,jto;
vec3 v1,v2;
for (i=0;i<Height;i++)
for (j=0;j<Width;j++)
{
ifrom = (i==0) ? i : i-1;
jfrom = (j==0) ? j : j-1;
ito = (i==Height-1) ? Height-1 : i+1;
jto = (j==Width-1) ? Width-1 : j+1;
v1 = VertexMatrix[j+ito*Width].pos - VertexMatrix[j+ifrom*Width].pos;
v2 = VertexMatrix[jto+i*Width].pos - VertexMatrix[jfrom+i*Width].pos;
VertexMatrix[j+i*Width].binorm = v1;
VertexMatrix[j+i*Width].tangent = v2;
VertexMatrix[j+i*Width].norm = CrossProduct(v2, v1);
}
}
void TSimpleLandClass::UpdateTriangleMatrix()
{
int k;
vec3 v,w;
for (int i=0;i<Height-1;i++)
for (int j=0;j<Width-1;j++)
{
k = 2*(j + i*(Width-1));
TriangleMatrix[k].PointList[0] = VertexMatrix[j + i*(Width)].pos;
TriangleMatrix[k].PointList[1] = VertexMatrix[j+1 + i*(Width)].pos;
TriangleMatrix[k].PointList[2] = VertexMatrix[j + (i+1)*(Width)].pos;
v = TriangleMatrix[k].PointList[1] - TriangleMatrix[k].PointList[0];
w = TriangleMatrix[k].PointList[2] - TriangleMatrix[k].PointList[1];
TriangleMatrix[k].NormVec = CrossProduct(v,w);
if (TriangleMatrix[k].NormVec.v[1] < 0.0f)
{
//Xperimental
TriangleMatrix[k].NormVec.v[0] = - TriangleMatrix[k].NormVec.v[0];
TriangleMatrix[k].NormVec.v[1] = - TriangleMatrix[k].NormVec.v[1];
TriangleMatrix[k].NormVec.v[2] = - TriangleMatrix[k].NormVec.v[2];
}
k++;
TriangleMatrix[k].PointList[0] = VertexMatrix[j+1 + (i+1)*(Width)].pos;
TriangleMatrix[k].PointList[1] = VertexMatrix[j + (i+1)*(Width)].pos;
TriangleMatrix[k].PointList[2] = VertexMatrix[j+1 + i*(Width)].pos;
v = TriangleMatrix[k].PointList[1] - TriangleMatrix[k].PointList[0];
w = TriangleMatrix[k].PointList[2] - TriangleMatrix[k].PointList[1];
TriangleMatrix[k].NormVec = CrossProduct(v, w);
if (TriangleMatrix[k].NormVec.v[1] < 0.0f)
{
//Xperimental
TriangleMatrix[k].NormVec.v[0] = - TriangleMatrix[k].NormVec.v[0];
TriangleMatrix[k].NormVec.v[1] = - TriangleMatrix[k].NormVec.v[1];
TriangleMatrix[k].NormVec.v[2] = - TriangleMatrix[k].NormVec.v[2];
}
}
}
} //namespace SE