#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; iTexList.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 fileArr = CreateMemFromFile((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 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; //Открываем файл 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;iTexList.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(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(&(VBOLandVertexArr.norm[0]))); VertexAttribPointer3fv(CONST_STRING_TANGENT_ATTRIB, 0, reinterpret_cast(&(VBOLandVertexArr.tangent[0]))); VertexAttribPointer3fv(CONST_STRING_BINORMAL_ATTRIB, 0, reinterpret_cast(&(VBOLandVertexArr.binorm[0]))); VertexAttribPointer2fv(CONST_STRING_TEXCOORD_ATTRIB, 0, reinterpret_cast(&(VBOLandVertexArr.texCoord[0]))); VertexAttribPointer3fv(CONST_STRING_POSITION_ATTRIB, 0, reinterpret_cast(&(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(floor((Width-1)*(pos.v[0]-xMin)/(xMax - xMin))); ir = static_cast(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;i0) ? 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