Ticket #169: terrain_triangulation_test4.patch
File terrain_triangulation_test4.patch, 12.4 KB (added by , 14 years ago) |
---|
-
PatchRData.cpp
88 88 89 89 struct STmpSplat { 90 90 Handle m_Texture; 91 u16 m_Indices[ 4];91 u16 m_Indices[6]; //a splat is now composed of two triangles instead of a single quad 92 92 }; 93 93 94 void CPatchRData::GetTriangulation(const CVector3D& v1, const CVector3D& v2, const CVector3D& v3, const CVector3D& v4, std::vector<CVector3D>& out) 95 { 96 std::list<unsigned short> triangulation = m_Triangulation[v3]; 97 std::list<unsigned short>::iterator it; 98 for (it = triangulation.begin(); it != triangulation.end(); it++) 99 { 100 if (m_Vertices[*it].m_Position == v1) 101 out.push_back(v1); 102 else if (m_Vertices[*it].m_Position == v2) 103 out.push_back(v2); 104 else if (m_Vertices[*it].m_Position == v3) 105 out.push_back(v3); 106 else 107 out.push_back(v4); 108 } 109 } 110 94 111 void CPatchRData::BuildBlends() 95 112 { 96 113 m_BlendIndices.clear(); … … 237 254 m_BlendVertices.push_back(dst); 238 255 m_BlendVertexIndices.push_back(((j+1)*vsize)+i); 239 256 240 // build a splat for this quad 257 // build a splat for this quad (really two tris) 241 258 STmpSplat splat; 242 259 splat.m_Texture=neighbourTextures[k].m_Handle; 243 splat.m_Indices[0]=(u16)(vindex);260 /*splat.m_Indices[0]=(u16)(vindex); 244 261 splat.m_Indices[1]=(u16)(vindex+1); 245 262 splat.m_Indices[2]=(u16)(vindex+2); 246 263 splat.m_Indices[3]=(u16)(vindex+3); 264 */ 265 266 //match up the triangulation calculated by BuildIndices() for this blend tile 267 std::list<unsigned short> triangulation = m_Triangulation[vtx2.m_Position]; 268 std::list<unsigned short>::iterator it; 269 int splatIndex = 0; 270 for (it = triangulation.begin(); it != triangulation.end(); it++) 271 { 272 CVector3D pos = m_Vertices[*it].m_Position; 273 if (m_Vertices[*it].m_Position == vtx0.m_Position) 274 { 275 splat.m_Indices[splatIndex++]=((u16)(vindex)); 276 } 277 else if (m_Vertices[*it].m_Position == vtx1.m_Position) 278 { 279 splat.m_Indices[splatIndex++]=((u16)(vindex+1)); 280 } 281 else if (m_Vertices[*it].m_Position == vtx2.m_Position) 282 { 283 splat.m_Indices[splatIndex++]=((u16)(vindex+2)); 284 } 285 else if (m_Vertices[*it].m_Position == vtx3.m_Position) 286 { 287 splat.m_Indices[splatIndex++]=((u16)(vindex+3)); 288 } 289 else 290 { 291 debug_printf(L"WARNING: Triangulation matching failed."); 292 debug_break(); 293 } 294 } 247 295 splats.push_back(splat); 248 296 249 297 // add this texture to set of unique splat textures … … 284 332 m_BlendIndices.push_back(splats[k].m_Indices[1]+base); 285 333 m_BlendIndices.push_back(splats[k].m_Indices[2]+base); 286 334 m_BlendIndices.push_back(splats[k].m_Indices[3]+base); 287 splat.m_IndexCount+=4; 335 m_BlendIndices.push_back(splats[k].m_Indices[4]+base); 336 m_BlendIndices.push_back(splats[k].m_Indices[5]+base); 337 splat.m_IndexCount+=6; 288 338 } 289 339 } 290 340 splatCount++; … … 302 352 303 353 // release existing indices and bins 304 354 m_Indices.clear(); 305 m_ShadowMapIndices.clear();306 355 m_Splats.clear(); 307 356 308 357 // build grid of textures on this patch and boundaries of adjacent patches … … 332 381 for (ssize_t j=0;j<PATCH_SIZE;j++) { 333 382 for (ssize_t i=0;i<PATCH_SIZE;i++) { 334 383 if (texgrid[j][i]==h){ 384 385 //save these values for convenience 386 u16 index1 = u16(((j+0)*vsize+(i+0))+base); 387 u16 index2 = u16(((j+0)*vsize+(i+1))+base); 388 u16 index3 = u16(((j+1)*vsize+(i+1))+base); 389 u16 index4 = u16(((j+1)*vsize+(i+0))+base); 390 391 //calculate triangulation 392 //reminder: incrementing i shifts x coordinates, j shifts z 393 //first, get all the positions of the vertices in world space 394 CVector3D v1 = m_Vertices[(j+0)*vsize+(i+0)].m_Position; 395 CVector3D v2 = m_Vertices[(j+0)*vsize+(i+1)].m_Position; 396 CVector3D v3 = m_Vertices[(j+1)*vsize+(i+1)].m_Position; 397 CVector3D v4 = m_Vertices[(j+1)*vsize+(i+0)].m_Position; 398 399 /* 400 debug_printf(L"Vertex 1 is at position: %f, %f, %f\n", v1.X, v1.Y, v1.Z); 401 debug_printf(L"Vertex 2 is at position: %f, %f, %f\n", v2.X, v2.Y, v2.Z); 402 debug_printf(L"Vertex 3 is at position: %f, %f, %f\n", v3.X, v3.Y, v3.Z); 403 debug_printf(L"Vertex 4 is at position: %f, %f, %f\n", v4.X, v4.Y, v4.Z); 404 */ 405 406 407 //we have two possible triangulations to check: (123, 143) and (234, 214) 408 //our goal is to pick the one that minimizes the angle between the planes formed by the triangles 409 //the normals are constructed in such a way as to avoid having to normalize the vectors for the dot product 410 CVector3D normal1 = (v1-v2).Cross(v3-v2); 411 CVector3D normal2 = (v1-v4).Cross(v3-v4); 412 CVector3D normal3 = (v4-v3).Cross(v2-v3); 413 CVector3D normal4 = (v4-v1).Cross(v2-v1); 414 float angle1 = normal1.Dot(normal2); //since we don't need the exact angle, we can just use the value of the dot product 415 float angle2 = normal3.Dot(normal4); 416 417 //cos gets smaller as the angle increases so we take the triangulation with the larger value 418 if (angle1 < angle2) 419 { 420 m_Indices.push_back(index3); 421 m_Indices.push_back(index4); 422 m_Indices.push_back(index2); 423 m_Indices.push_back(index2); 424 m_Indices.push_back(index4); 425 m_Indices.push_back(index1); 426 427 //now add to the triangulation map 428 std::list<unsigned short> triangulation; 429 triangulation.push_back(index3-base); 430 triangulation.push_back(index4-base); 431 triangulation.push_back(index2-base); 432 triangulation.push_back(index2-base); 433 triangulation.push_back(index4-base); 434 triangulation.push_back(index1-base); 435 m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) ); 436 /* Debug code 437 std::pair<std::map<CVector3D, std::list<unsigned short>, veccmp>::iterator, bool> ret = m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) ); 438 if(ret.second == false) 439 debug_break(); 440 */ 441 } 442 else 443 { 444 m_Indices.push_back(index2); 445 m_Indices.push_back(index3); 446 m_Indices.push_back(index1); 447 m_Indices.push_back(index1); 448 m_Indices.push_back(index3); 449 m_Indices.push_back(index4); 450 451 //now add to the triangulation map 452 std::list<unsigned short> triangulation; 453 triangulation.push_back(index2-base); 454 triangulation.push_back(index3-base); 455 triangulation.push_back(index1-base); 456 triangulation.push_back(index1-base); 457 triangulation.push_back(index3-base); 458 triangulation.push_back(index4-base); 459 m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) ); 460 /* Debug code 461 std::pair<std::map<CVector3D, std::list<unsigned short>, veccmp>::iterator, bool> ret = m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) ); 462 if(ret.second == false) 463 debug_break(); 464 */ 465 } 466 467 /* 335 468 m_Indices.push_back(u16(((j+0)*vsize+(i+0))+base)); 336 469 m_Indices.push_back(u16(((j+0)*vsize+(i+1))+base)); 337 470 m_Indices.push_back(u16(((j+1)*vsize+(i+1))+base)); 338 471 m_Indices.push_back(u16(((j+1)*vsize+(i+0))+base)); 472 */ 473 339 474 } 340 475 } 341 476 } 342 477 splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart; 343 478 } 344 345 // build indices for the shadow map pass346 for (ssize_t j=0;j<PATCH_SIZE;j++) {347 for (ssize_t i=0;i<PATCH_SIZE;i++) {348 m_ShadowMapIndices.push_back(u16(((j+0)*vsize+(i+0))+base));349 m_ShadowMapIndices.push_back(u16(((j+0)*vsize+(i+1))+base));350 m_ShadowMapIndices.push_back(u16(((j+1)*vsize+(i+1))+base));351 m_ShadowMapIndices.push_back(u16(((j+1)*vsize+(i+0))+base));352 }353 }354 479 } 355 480 356 481 … … 519 644 ogl_tex_bind(splat.m_Texture); 520 645 521 646 if (!g_Renderer.m_SkipSubmit) { 522 glDrawElements(GL_ QUADS, (GLsizei)splat.m_IndexCount,647 glDrawElements(GL_TRIANGLES, (GLsizei)splat.m_IndexCount, 523 648 GL_UNSIGNED_SHORT, &m_Indices[splat.m_IndexStart]); 524 649 } 525 650 526 651 // bump stats 527 652 g_Renderer.m_Stats.m_DrawCalls++; 528 653 g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2; … … 552 677 553 678 // render all base splats at once 554 679 if (!g_Renderer.m_SkipSubmit) { 555 glDrawElements(GL_ QUADS,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);680 glDrawElements(GL_TRIANGLES,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]); 556 681 } 557 682 558 683 // bump stats … … 591 716 ogl_tex_bind(splat.m_Texture); 592 717 593 718 if (!g_Renderer.m_SkipSubmit) { 594 glDrawElements(GL_ QUADS, (GLsizei)splat.m_IndexCount,719 glDrawElements(GL_TRIANGLES, (GLsizei)splat.m_IndexCount, 595 720 GL_UNSIGNED_SHORT, &m_BlendIndices[splat.m_IndexStart]); 596 721 } 597 722 -
PatchRData.h
40 40 void RenderBlends(); 41 41 void RenderOutline(); 42 42 void RenderStreams(int streamflags, bool losColor); 43 void GetTriangulation(const CVector3D& v1, const CVector3D& v2, const CVector3D& v3, const CVector3D& v4, std::vector<CVector3D>& out); 43 44 44 45 private: 45 46 struct SSplat { … … 82 83 int m_Priority; 83 84 }; 84 85 86 struct veccmp 87 { 88 //comparison function for use by the triangulation map 89 bool operator() (const CVector3D& lhs, const CVector3D& rhs) const 90 { 91 if (lhs.Y < rhs.Y) 92 return true; 93 else if (lhs.Y == rhs.Y) 94 { 95 if (lhs.Z < rhs.Z) 96 return true; 97 else if (lhs.Z == rhs.Z) 98 { 99 if (lhs.X < rhs.X) 100 return true; 101 else 102 return false; 103 } 104 else 105 return false; 106 } 107 else 108 return false; 109 } 110 }; 111 85 112 // build this renderdata object 86 113 void Build(); 87 114 … … 104 131 // indices into base vertices for the base splats 105 132 std::vector<unsigned short> m_Indices; 106 133 107 // indices into base vertices for the shadow map pass108 std::vector<unsigned short> m_ShadowMapIndices;109 110 134 // list of base splats to apply to this patch 111 135 std::vector<SSplat> m_Splats; 112 136 … … 122 146 123 147 // splats used in blend pass 124 148 std::vector<SSplat> m_BlendSplats; 149 150 // stores the triangulation used for individual tiles to improve triangulation matching performance 151 // it is keyed on the third vertex of a tile (the i+1, j+1 one) 152 std::map<CVector3D, std::list<unsigned short>, veccmp> m_Triangulation; 125 153 }; 126 154 127 155 -
TerrainOverlay.cpp
23 23 #include "ps/Game.h" 24 24 #include "ps/World.h" 25 25 #include "graphics/Terrain.h" 26 #include "graphics/Patch.h" 27 #include "renderer/PatchRData.h" 26 28 #include "maths/MathUtil.h" 27 29 #include "lib/ogl.h" 28 30 … … 182 184 183 185 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 184 186 187 /* 185 188 CVector3D pos; 186 189 glBegin(GL_QUADS); 187 190 glColor4fv(colour.FloatArray()); … … 190 193 m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray()); 191 194 m_Terrain->CalcPosition(i, j+1, pos); glVertex3fv(pos.GetFloatArray()); 192 195 glEnd(); 196 */ 197 198 //because the terrain now renders as triangles instead of quads, trying to draw a quad on top of the terrain results in nasty z-fighting so 199 //we draw triangles and match it up to the triangulation of the underlying patch 200 CPatch* patch = m_Terrain->GetPatch(i/PATCH_SIZE,j/PATCH_SIZE); 201 if (patch != NULL) 202 { 203 if (patch->GetRenderData() != NULL) 204 { 205 CPatchRData* renderPatch = (CPatchRData*)patch->GetRenderData(); 206 CVector3D v1; m_Terrain->CalcPosition(i, j, v1); 207 CVector3D v2; m_Terrain->CalcPosition(i+1, j, v2); 208 CVector3D v3; m_Terrain->CalcPosition(i+1, j+1, v3); 209 CVector3D v4; m_Terrain->CalcPosition(i, j+1, v4); 210 211 std::vector<CVector3D> vertices(6); 212 renderPatch->GetTriangulation(v1,v2,v3,v4, vertices); 213 214 /* I clearly have no idea what I'm doing here... 215 unsigned short indices[] = {0,1,2,3,4,5,6}; 216 glVertexPointer (3, GL_FLOAT, (GLsizei)sizeof(CVector3D), &vertices); 217 glColorPointer(4,GL_FLOAT,(GLsizei)sizeof(colour.FloatArray()),colour.FloatArray()); 218 glDrawElements(GL_TRIANGLES, (GLsizei)vertices.size(),GL_UNSIGNED_SHORT, indices); 219 */ 220 221 glBegin(GL_TRIANGLES); 222 glColor4fv(colour.FloatArray()); 223 for (size_t k = 0; k < vertices.size(); k++) 224 glVertex3fv(vertices[k].GetFloatArray()); 225 glEnd(); 226 } 227 } 193 228 } 194 229 195 230 void TerrainOverlay::RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden)