| 247 | */ |
| 248 | //save these for convenience |
| 249 | CVector3D vertex1 = vtx0.m_Position; |
| 250 | CVector3D vertex2 = vtx1.m_Position; |
| 251 | CVector3D vertex3 = vtx2.m_Position; |
| 252 | CVector3D vertex4 = vtx3.m_Position; |
| 253 | |
| 254 | //find the set of indices in m_Indices that correspond to the vertices |
| 255 | //being used by the current blend texture so that we can match up the triangulation used |
| 256 | std::list<u16> IndexList; //store the order indices should be added to m_BlendIndices |
| 257 | size_t indexBase=m_VBBase->m_Index; //used to get correct index position in m_Vertices |
| 258 | for (int p = 0; p < m_Indices.size()-5; p++) |
| 259 | { |
| 260 | if ( |
| 261 | m_Vertices[m_Indices[p]-indexBase].m_Position == vertex1 || |
| 262 | m_Vertices[m_Indices[p]-indexBase].m_Position == vertex2 || |
| 263 | m_Vertices[m_Indices[p]-indexBase].m_Position == vertex3 || |
| 264 | m_Vertices[m_Indices[p]-indexBase].m_Position == vertex4 |
| 265 | ) |
| 266 | { |
| 267 | //we've found a match to one of the vertices, but that does not necessarily mean we're at the right set of |
| 268 | //indices so we check the block of 6 vertices to see if they contain all the vertices we're using |
| 269 | for (int q = p; q < p+6; q++) |
| 270 | { |
| 271 | if (m_Vertices[m_Indices[q]-indexBase].m_Position == vertex1) |
| 272 | { |
| 273 | IndexList.push_back((u16)(vindex)); |
| 274 | } |
| 275 | else if (m_Vertices[m_Indices[q]-indexBase].m_Position == vertex2) |
| 276 | { |
| 277 | IndexList.push_back((u16)(vindex+1)); |
| 278 | } |
| 279 | else if (m_Vertices[m_Indices[q]-indexBase].m_Position == vertex3) |
| 280 | { |
| 281 | IndexList.push_back((u16)(vindex+2)); |
| 282 | } |
| 283 | else if (m_Vertices[m_Indices[q]-indexBase].m_Position == vertex4) |
| 284 | { |
| 285 | IndexList.push_back((u16)(vindex+3)); |
| 286 | } |
| 287 | else |
| 288 | { |
| 289 | //this means we've encountered a vertex that's not one of the ones we're looking for so exit out |
| 290 | IndexList.clear(); |
| 291 | p = q; //so that we don't recheck the vertices we know can't possibly match |
| 292 | break; |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | if (IndexList.size() == 6) |
| 297 | { |
| 298 | //found our triangulation so early out for the search |
| 299 | break; |
| 300 | } |
| 301 | } |
| 302 | if (IndexList.size() != 6) |
| 303 | { |
| 304 | //tried to use debug_assert(IndexList.size() == 6), but that started throwing memory access violations for some reason |
| 305 | debug_printf(L"WARNING: Blend Indices building failed. IndexList does not contain 6 elements.\n"); |
| 306 | debug_break(); |
| 307 | } |
| 308 | std::list<u16>::iterator it; |
| 309 | int splatIndex = 0; |
| 310 | for (it = IndexList.begin(); it != IndexList.end(); it++) |
| 311 | { |
| 312 | //add the indices in the order we found them in |
| 313 | splat.m_Indices[splatIndex++] = *it; |
| 314 | } |
| 404 | |
| 405 | //save these values for convenience |
| 406 | u16 index1 = u16(((j+0)*vsize+(i+0))+base); |
| 407 | u16 index2 = u16(((j+0)*vsize+(i+1))+base); |
| 408 | u16 index3 = u16(((j+1)*vsize+(i+1))+base); |
| 409 | u16 index4 = u16(((j+1)*vsize+(i+0))+base); |
| 410 | |
| 411 | //calculate triangulation |
| 412 | //reminder: incrementing i shifts x coordinates, j shifts z |
| 413 | //first, get all the positions of the vertices in world space |
| 414 | CVector3D v1 = m_Vertices[(j+0)*vsize+(i+0)].m_Position; |
| 415 | CVector3D v2 = m_Vertices[(j+0)*vsize+(i+1)].m_Position; |
| 416 | CVector3D v3 = m_Vertices[(j+1)*vsize+(i+1)].m_Position; |
| 417 | CVector3D v4 = m_Vertices[(j+1)*vsize+(i+0)].m_Position; |
| 418 | |
| 419 | /* |
| 420 | debug_printf(L"Vertex 1 is at position: %f, %f, %f\n", v1.X, v1.Y, v1.Z); |
| 421 | debug_printf(L"Vertex 2 is at position: %f, %f, %f\n", v2.X, v2.Y, v2.Z); |
| 422 | debug_printf(L"Vertex 3 is at position: %f, %f, %f\n", v3.X, v3.Y, v3.Z); |
| 423 | debug_printf(L"Vertex 4 is at position: %f, %f, %f\n", v4.X, v4.Y, v4.Z); |
| 424 | */ |
| 425 | |
| 426 | |
| 427 | //we have two possible triangulations to check: (123, 143) and (234, 214) |
| 428 | //our goal is to pick the one that minimizes the angle between the planes formed by the triangles |
| 429 | //the normals are constructed in such a way as to avoid having to normalize the vectors for the dot product |
| 430 | CVector3D normal1 = (v1-v2).Cross(v3-v2); |
| 431 | CVector3D normal2 = (v1-v4).Cross(v3-v4); |
| 432 | CVector3D normal3 = (v4-v3).Cross(v2-v3); |
| 433 | CVector3D normal4 = (v4-v1).Cross(v2-v1); |
| 434 | float angle1 = normal1.Dot(normal2); //since we don't need the exact angle, we can just use the value of the dot product |
| 435 | float angle2 = normal3.Dot(normal4); |
| 436 | |
| 437 | //cos gets smaller as the angle increases so we take the triangulation with the larger value |
| 438 | if (angle1 < angle2) |
| 439 | { |
| 440 | |
| 441 | |
| 442 | m_Indices.push_back(index3); |
| 443 | m_Indices.push_back(index4); |
| 444 | m_Indices.push_back(index2); |
| 445 | m_Indices.push_back(index2); |
| 446 | m_Indices.push_back(index4); |
| 447 | m_Indices.push_back(index1); |
| 448 | |
| 449 | /* |
| 450 | //for triangle strip |
| 451 | m_Indices.push_back(index3); |
| 452 | m_Indices.push_back(index4); |
| 453 | m_Indices.push_back(index2); |
| 454 | m_Indices.push_back(index1); |
| 455 | */ |
| 456 | } |
| 457 | else |
| 458 | { |
| 459 | |
| 460 | m_Indices.push_back(index2); |
| 461 | m_Indices.push_back(index3); |
| 462 | m_Indices.push_back(index1); |
| 463 | m_Indices.push_back(index1); |
| 464 | m_Indices.push_back(index3); |
| 465 | m_Indices.push_back(index4); |
| 466 | |
| 467 | /* |
| 468 | //for triangle strip |
| 469 | m_Indices.push_back(index2); |
| 470 | m_Indices.push_back(index3); |
| 471 | m_Indices.push_back(index1); |
| 472 | m_Indices.push_back(index4); |
| 473 | */ |
| 474 | } |
| 475 | |
| 476 | /* |