1/* 2Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc. 3 4Permission is hereby granted, free of charge, to any person obtaining a copy 5of this software and associated documentation files (the "Software"), to deal 6in the Software without restriction, including without limitation the rights 7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8copies of the Software, and to permit persons to whom the Software is 9furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20THE SOFTWARE. 21*/ 22 23#pragma once 24#ifndef O3DGC_TRIANGLE_LIST_ENCODER_INL 25#define O3DGC_TRIANGLE_LIST_ENCODER_INL 26 27namespace o3dgc 28{ 29 // extract opposite edge 30 template <class T> 31 inline void CompueOppositeEdge(const long focusVertex, 32 const T * triangle, 33 long & a, long & b) 34 { 35 if ((long) triangle[0] == focusVertex) 36 { 37 a = triangle[1]; 38 b = triangle[2]; 39 } 40 else if ((long) triangle[1] == focusVertex) 41 { 42 a = triangle[2]; 43 b = triangle[0]; 44 } 45 else 46 { 47 a = triangle[0]; 48 b = triangle[1]; 49 } 50 } 51 inline bool IsCase0(long degree, long numIndices, const long * const ops, const long * const indices) 52 { 53 // ops: 1000001 vertices: -1 -2 54 if ((numIndices != 2) || (degree < 2)) { 55 return false; 56 } 57 if ((indices[0] != -1) ||(indices[1] != -2) || 58 (ops[0] != 1) ||(ops[degree-1] != 1) ) return false; 59 for (long u = 1; u < degree-1; u++) { 60 if (ops[u] != 0) return false; 61 } 62 return true; 63 } 64 inline bool IsCase1(long degree, long numIndices, const long * const ops, const long * const indices) 65 { 66 // ops: 1xxxxxx1 indices: -1 x x x x x -2 67 if ((degree < 2) || (numIndices < 1)) 68 { 69 return false; 70 } 71 if ((indices[0] != -1) ||(indices[numIndices-1] != -2) || 72 (ops[0] != 1) ||(ops[degree-1] != 1) ) return false; 73 return true; 74 } 75 inline bool IsCase2(long degree, long numIndices, const long * const ops, const long * const indices) 76 { 77 // ops: 00000001 indices: -1 78 if ((degree < 2) || (numIndices!= 1)) 79 { 80 return false; 81 } 82 if ((indices[0] != -1) || (ops[degree-1] != 1) ) return false; 83 for (long u = 0; u < degree-1; u++) { 84 if (ops[u] != 0) return false; 85 } 86 return true; 87 } 88 inline bool IsCase3(long degree, long numIndices, const long * const ops, const long * const indices) 89 { 90 // ops: 00000001 indices: -2 91 if ((degree < 2) || (numIndices!= 1)) 92 { 93 return false; 94 } 95 if ((indices[0] != -2) || (ops[degree-1] != 1) ) return false; 96 for (long u = 0; u < degree-1; u++) { 97 if (ops[u] != 0) return false; 98 } 99 return true; 100 } 101 inline bool IsCase4(long degree, long numIndices, const long * const ops, const long * const indices) 102 { 103 // ops: 10000000 indices: -1 104 if ((degree < 2) || (numIndices!= 1)) 105 { 106 return false; 107 } 108 if ((indices[0] != -1) || (ops[0] != 1) ) return false; 109 for (long u = 1; u < degree; u++) 110 { 111 if (ops[u] != 0) return false; 112 } 113 return true; 114 } 115 inline bool IsCase5(long degree, long numIndices, const long * const ops, const long * const indices) 116 { 117 // ops: 10000000 indices: -2 118 if ((degree < 2) || (numIndices!= 1)) 119 { 120 return false; 121 } 122 if ((indices[0] != -2) || (ops[0] != 1) ) return false; 123 for (long u = 1; u < degree; u++) { 124 if (ops[u] != 0) return false; 125 } 126 return true; 127 } 128 inline bool IsCase6(long degree, long numIndices, const long * const ops, const long * const /*indices*/) 129 { 130 // ops: 0000000 indices: 131 if (numIndices!= 0) 132 { 133 return false; 134 } 135 for (long u = 0; u < degree; u++) 136 { 137 if (ops[u] != 0) return false; 138 } 139 return true; 140 } 141 inline bool IsCase7(long degree, long numIndices, const long * const ops, const long * const indices) 142 { 143 // ops: 1000001 indices: -2 -1 144 if ((numIndices!= 2) || (degree < 2)) 145 { 146 return false; 147 } 148 if ((indices[0] != -2) ||(indices[1] != -1) || 149 (ops[0] != 1) ||(ops[degree-1] != 1) ) return false; 150 for (long u = 1; u < degree-1; u++) 151 { 152 if (ops[u] != 0) return false; 153 } 154 return true; 155 } 156 inline bool IsCase8(long degree, long numIndices, const long * const ops, const long * const indices) 157 { 158 // ops: 1xxxxxx1 indices: -1 x x x x x -2 159 if ((degree < 2) || (numIndices < 1)) 160 { 161 return false; 162 } 163 if ((indices[0] != -2) ||(indices[numIndices-1] != -1) || 164 (ops[0] != 1) ||(ops[degree-1] != 1) ) return false; 165 return true; 166 } 167 template <class T> 168 TriangleListEncoder<T>::TriangleListEncoder(void) 169 { 170 m_vtags = 0; 171 m_ttags = 0; 172 m_tmap = 0; 173 m_vmap = 0; 174 m_count = 0; 175 m_invVMap = 0; 176 m_invTMap = 0; 177 m_nonConqueredTriangles = 0; 178 m_nonConqueredEdges = 0; 179 m_visitedVertices = 0; 180 m_visitedVerticesValence = 0; 181 m_vertexCount = 0; 182 m_triangleCount = 0; 183 m_maxNumVertices = 0; 184 m_maxNumTriangles = 0; 185 m_numTriangles = 0; 186 m_numVertices = 0; 187 m_triangles = 0; 188 m_maxSizeVertexToTriangle = 0; 189 m_streamType = O3DGC_STREAM_TYPE_UNKOWN; 190 } 191 template <class T> 192 TriangleListEncoder<T>::~TriangleListEncoder() 193 { 194 delete [] m_vtags; 195 delete [] m_vmap; 196 delete [] m_invVMap; 197 delete [] m_invTMap; 198 delete [] m_visitedVerticesValence; 199 delete [] m_visitedVertices; 200 delete [] m_ttags; 201 delete [] m_tmap; 202 delete [] m_count; 203 delete [] m_nonConqueredTriangles; 204 delete [] m_nonConqueredEdges; 205 } 206 template <class T> 207 O3DGCErrorCode TriangleListEncoder<T>::Init(const T * const triangles, 208 long numTriangles, 209 long numVertices) 210 { 211 assert(numVertices > 0); 212 assert(numTriangles > 0); 213 214 m_numTriangles = numTriangles; 215 m_numVertices = numVertices; 216 m_triangles = triangles; 217 m_vertexCount = 0; 218 m_triangleCount = 0; 219 220 if (m_numVertices > m_maxNumVertices) 221 { 222 delete [] m_vtags; 223 delete [] m_vmap; 224 delete [] m_invVMap; 225 delete [] m_visitedVerticesValence; 226 delete [] m_visitedVertices; 227 m_maxNumVertices = m_numVertices; 228 m_vtags = new long [m_numVertices]; 229 m_vmap = new long [m_numVertices]; 230 m_invVMap = new long [m_numVertices]; 231 m_visitedVerticesValence = new long [m_numVertices]; 232 m_visitedVertices = new long [m_numVertices]; 233 } 234 235 if (m_numTriangles > m_maxNumTriangles) 236 { 237 delete [] m_ttags; 238 delete [] m_tmap; 239 delete [] m_invTMap; 240 delete [] m_nonConqueredTriangles; 241 delete [] m_nonConqueredEdges; 242 delete [] m_count; 243 m_maxNumTriangles = m_numTriangles; 244 m_ttags = new long [m_numTriangles]; 245 m_tmap = new long [m_numTriangles]; 246 m_invTMap = new long [m_numTriangles]; 247 m_count = new long [m_numTriangles+1]; 248 m_nonConqueredTriangles = new long [m_numTriangles]; 249 m_nonConqueredEdges = new long [2*m_numTriangles]; 250 } 251 252 memset(m_vtags , 0x00, sizeof(long) * m_numVertices ); 253 memset(m_vmap , 0xFF, sizeof(long) * m_numVertices ); 254 memset(m_invVMap, 0xFF, sizeof(long) * m_numVertices ); 255 memset(m_ttags , 0x00, sizeof(long) * m_numTriangles); 256 memset(m_tmap , 0xFF, sizeof(long) * m_numTriangles); 257 memset(m_invTMap, 0xFF, sizeof(long) * m_numTriangles); 258 memset(m_count , 0x00, sizeof(long) * (m_numTriangles+1)); 259 260 m_vfifo.Allocate(m_numVertices); 261 m_ctfans.SetStreamType(m_streamType); 262 m_ctfans.Allocate(m_numVertices, m_numTriangles); 263 264 // compute vertex-to-triangle adjacency information 265 m_vertexToTriangle.AllocateNumNeighborsArray(numVertices); 266 m_vertexToTriangle.ClearNumNeighborsArray(); 267 long * numNeighbors = m_vertexToTriangle.GetNumNeighborsBuffer(); 268 for(long i = 0, t = 0; i < m_numTriangles; ++i, t+=3) 269 { 270 ++numNeighbors[ triangles[t ] ]; 271 ++numNeighbors[ triangles[t+1] ]; 272 ++numNeighbors[ triangles[t+2] ]; 273 } 274 m_maxSizeVertexToTriangle = 0; 275 for(long i = 0; i < numVertices; ++i) 276 { 277 if (m_maxSizeVertexToTriangle < numNeighbors[i]) 278 { 279 m_maxSizeVertexToTriangle = numNeighbors[i]; 280 } 281 } 282 m_vertexToTriangle.AllocateNeighborsArray(); 283 m_vertexToTriangle.ClearNeighborsArray(); 284 for(long i = 0, t = 0; i < m_numTriangles; ++i, t+=3) 285 { 286 m_vertexToTriangle.AddNeighbor(triangles[t ], i); 287 m_vertexToTriangle.AddNeighbor(triangles[t+1], i); 288 m_vertexToTriangle.AddNeighbor(triangles[t+2], i); 289 } 290 return O3DGC_OK; 291 } 292 template <class T> 293 O3DGCErrorCode TriangleListEncoder<T>::Encode(const T * const triangles, 294 const unsigned long * const indexBufferIDs, 295 const long numTriangles, 296 const long numVertices, 297 BinaryStream & bstream) 298 { 299 assert(numVertices > 0); 300 assert(numTriangles > 0); 301 302 Init(triangles, numTriangles, numVertices); 303 unsigned char mask = 0; 304 bool encodeTrianglesOrder = (indexBufferIDs != 0); 305 306 307 if (encodeTrianglesOrder) 308 { 309 long numBufferIDs = 0; 310 for (long t = 0; t < numTriangles; t++) 311 { 312 if (numBufferIDs <= (long) indexBufferIDs[t]) 313 { 314 ++numBufferIDs; 315 assert(numBufferIDs <= numTriangles); 316 } 317 ++m_count[indexBufferIDs[t]+1]; 318 } 319 for (long i = 2; i <= numBufferIDs; i++) 320 { 321 m_count[i] += m_count[i-1]; 322 } 323 mask += 2; // preserved triangles order 324 } 325 bstream.WriteUChar(mask, m_streamType); 326 bstream.WriteUInt32(m_maxSizeVertexToTriangle, m_streamType); 327 328 long v0; 329 for (long v = 0; v < m_numVertices; v++) 330 { 331 if (!m_vtags[v]) 332 { 333 m_vfifo.PushBack(v); 334 m_vtags[v] = 1; 335 m_vmap[v] = m_vertexCount++; 336 m_invVMap[m_vmap[v]] = v; 337 while (m_vfifo.GetSize() > 0 ) 338 { 339 v0 = m_vfifo.PopFirst(); 340 ProcessVertex(v0); 341 } 342 } 343 } 344 if (encodeTrianglesOrder) 345 { 346 long t, prev = 0; 347 long pred; 348 for (long i = 0; i < numTriangles; ++i) 349 { 350 t = m_invTMap[i]; 351 m_tmap[t] = m_count[ indexBufferIDs[t] ]++; 352 pred = m_tmap[t] - prev; 353 m_ctfans.PushTriangleIndex(pred); 354 prev = m_tmap[t] + 1; 355 } 356 for (long tt = 0; tt < numTriangles; ++tt) 357 { 358 m_invTMap[m_tmap[tt]] = tt; 359 } 360 } 361 m_ctfans.Save(bstream, encodeTrianglesOrder, m_streamType); 362 return O3DGC_OK; 363 } 364 template <class T> 365 O3DGCErrorCode TriangleListEncoder<T>::CompueLocalConnectivityInfo(const long focusVertex) 366 { 367 long t, v, p; 368 m_numNonConqueredTriangles = 0; 369 m_numConqueredTriangles = 0; 370 m_numVisitedVertices = 0; 371 for(long i = m_vertexToTriangle.Begin(focusVertex); i < m_vertexToTriangle.End(focusVertex); ++i) 372 { 373 t = m_vertexToTriangle.GetNeighbor(i); 374 375 if ( m_ttags[t] == 0) // non-processed triangle 376 { 377 m_nonConqueredTriangles[m_numNonConqueredTriangles] = t; 378 CompueOppositeEdge( focusVertex, 379 m_triangles + (3*t), 380 m_nonConqueredEdges[m_numNonConqueredTriangles*2], 381 m_nonConqueredEdges[m_numNonConqueredTriangles*2+1]); 382 ++m_numNonConqueredTriangles; 383 } 384 else // triangle already processed 385 { 386 m_numConqueredTriangles++; 387 p = 3*t; 388 // extract visited vertices 389 for(long k = 0; k < 3; ++k) 390 { 391 v = m_triangles[p+k]; 392 if (m_vmap[v] > m_vmap[focusVertex]) // vertices are insertices by increasing traversal order 393 { 394 bool foundOrInserted = false; 395 for (long j = 0; j < m_numVisitedVertices; ++j) 396 { 397 398 if (m_vmap[v] == m_visitedVertices[j]) 399 { 400 m_visitedVerticesValence[j]++; 401 foundOrInserted = true; 402 break; 403 } 404 else if (m_vmap[v] < m_visitedVertices[j]) 405 { 406 ++m_numVisitedVertices; 407 for (long h = m_numVisitedVertices-1; h > j; --h) 408 { 409 m_visitedVertices[h] = m_visitedVertices[h-1]; 410 m_visitedVerticesValence[h] = m_visitedVerticesValence[h-1]; 411 } 412 m_visitedVertices[j] = m_vmap[v]; 413 m_visitedVerticesValence[j] = 1; 414 foundOrInserted = true; 415 break; 416 } 417 } 418 if (!foundOrInserted) 419 { 420 m_visitedVertices[m_numVisitedVertices] = m_vmap[v]; 421 m_visitedVerticesValence[m_numVisitedVertices] = 1; 422 m_numVisitedVertices++; 423 } 424 } 425 } 426 } 427 } 428 // re-order visited vertices by taking into account their valence (i.e., # of conquered triangles incident to each vertex) 429 // in order to avoid config. 9 430 if (m_numVisitedVertices > 2) 431 { 432 long y; 433 for(long x = 1; x < m_numVisitedVertices; ++x) 434 { 435 436 if (m_visitedVerticesValence[x] == 1) 437 { 438 y = x; 439 while( (y > 0) && (m_visitedVerticesValence[y] < m_visitedVerticesValence[y-1]) ) 440 { 441 swap(m_visitedVerticesValence[y], m_visitedVerticesValence[y-1]); 442 swap(m_visitedVertices[y], m_visitedVertices[y-1]); 443 --y; 444 } 445 } 446 } 447 } 448 if (m_numNonConqueredTriangles > 0) 449 { 450 // compute triangle-to-triangle adjacency information 451 m_triangleToTriangle.AllocateNumNeighborsArray(m_numNonConqueredTriangles); 452 m_triangleToTriangle.ClearNumNeighborsArray(); 453 m_triangleToTriangleInv.AllocateNumNeighborsArray(m_numNonConqueredTriangles); 454 m_triangleToTriangleInv.ClearNumNeighborsArray(); 455 long * const numNeighbors = m_triangleToTriangle.GetNumNeighborsBuffer(); 456 long * const invNumNeighbors = m_triangleToTriangleInv.GetNumNeighborsBuffer(); 457 for(long i = 0; i < m_numNonConqueredTriangles; ++i) 458 { 459 for(long j = i+1; j < m_numNonConqueredTriangles; ++j) 460 { 461 if (m_nonConqueredEdges[2*i+1] == m_nonConqueredEdges[2*j]) // edge i is connected to edge j 462 { 463 ++numNeighbors[i]; 464 ++invNumNeighbors[j]; 465 } 466 if (m_nonConqueredEdges[2*i] == m_nonConqueredEdges[2*j+1]) // edge i is connected to edge j 467 { 468 ++numNeighbors[j]; 469 ++invNumNeighbors[i]; 470 } 471 } 472 } 473 m_triangleToTriangle.AllocateNeighborsArray(); 474 m_triangleToTriangle.ClearNeighborsArray(); 475 m_triangleToTriangleInv.AllocateNeighborsArray(); 476 m_triangleToTriangleInv.ClearNeighborsArray(); 477 for(long i = 0; i < m_numNonConqueredTriangles; ++i) 478 { 479 for(long j = 1; j < m_numNonConqueredTriangles; ++j) 480 { 481 if (m_nonConqueredEdges[2*i+1] == m_nonConqueredEdges[2*j]) // edge i is connected to edge j 482 { 483 m_triangleToTriangle.AddNeighbor(i, j); 484 m_triangleToTriangleInv.AddNeighbor(j, i); 485 } 486 if (m_nonConqueredEdges[2*i] == m_nonConqueredEdges[2*j+1]) // edge i is connected to edge j 487 { 488 m_triangleToTriangle.AddNeighbor(j, i); 489 m_triangleToTriangleInv.AddNeighbor(i, j); 490 } 491 } 492 } 493 } 494 return O3DGC_OK; 495 } 496 template <class T> 497 O3DGCErrorCode TriangleListEncoder<T>::ComputeTFANDecomposition(const long focusVertex) 498 { 499 long processedTriangles = 0; 500 long minNumInputEdges; 501 long numInputEdges; 502 long indexSeedTriangle; 503 long seedTriangle; 504 long currentIndex; 505 long currentTriangle; 506 long i0, i1, index; 507 508 m_tfans.Clear(); 509 while (processedTriangles != m_numNonConqueredTriangles) 510 { 511 // find non processed triangle with lowest number of inputs 512 minNumInputEdges = m_numTriangles; 513 indexSeedTriangle = -1; 514 for(long i = 0; i < m_numNonConqueredTriangles; ++i) 515 { 516 numInputEdges = m_triangleToTriangleInv.GetNumNeighbors(i); 517 if ( !m_ttags[m_nonConqueredTriangles[i]] && 518 numInputEdges < minNumInputEdges ) 519 { 520 minNumInputEdges = numInputEdges; 521 indexSeedTriangle = i; 522 if (minNumInputEdges == 0) // found boundary triangle 523 { 524 break; 525 } 526 } 527 } 528 assert(indexSeedTriangle >= 0); 529 seedTriangle = m_nonConqueredTriangles[indexSeedTriangle]; 530 m_tfans.AddTFAN(); 531 m_tfans.AddVertex( focusVertex ); 532 m_tfans.AddVertex( m_nonConqueredEdges[indexSeedTriangle*2] ); 533 m_tfans.AddVertex( m_nonConqueredEdges[indexSeedTriangle*2 + 1] ); 534 m_ttags[ seedTriangle ] = 1; // mark triangle as processed 535 m_tmap[seedTriangle] = m_triangleCount++; 536 m_invTMap[m_tmap[seedTriangle]] = seedTriangle; 537 ++processedTriangles; 538 currentIndex = indexSeedTriangle; 539 currentTriangle = seedTriangle; 540 do 541 { 542 // find next triangle 543 i0 = m_triangleToTriangle.Begin(currentIndex); 544 i1 = m_triangleToTriangle.End(currentIndex); 545 currentIndex = -1; 546 for(long i = i0; i < i1; ++i) 547 { 548 index = m_triangleToTriangle.GetNeighbor(i); 549 currentTriangle = m_nonConqueredTriangles[index]; 550 if ( !m_ttags[currentTriangle] ) 551 { 552 currentIndex = index; 553 m_tfans.AddVertex( m_nonConqueredEdges[currentIndex*2+1] ); 554 m_ttags[currentTriangle] = 1; // mark triangle as processed 555 m_tmap [currentTriangle] = m_triangleCount++; 556 m_invTMap[m_tmap [currentTriangle]] = currentTriangle; 557 ++processedTriangles; 558 break; 559 } 560 } 561 } while (currentIndex != -1); 562 } 563 564 return O3DGC_OK; 565 } 566 template <class T> 567 O3DGCErrorCode TriangleListEncoder<T>::CompressTFAN(const long focusVertex) 568 { 569 m_ctfans.PushNumTFans(m_tfans.GetNumTFANs()); 570 571 const long ntfans = m_tfans.GetNumTFANs(); 572 long degree; 573 long k0, k1; 574 long v0; 575 long ops[O3DGC_MAX_TFAN_SIZE]; 576 long indices[O3DGC_MAX_TFAN_SIZE]; 577 578 long numOps; 579 long numIndices; 580 long pos; 581 long found; 582 583 if (m_tfans.GetNumTFANs() > 0) 584 { 585 for(long f = 0; f != ntfans; f++) 586 { 587 degree = m_tfans.GetTFANSize(f) - 1; 588 m_ctfans.PushDegree(degree-2+ m_numConqueredTriangles); 589 numOps = 0; 590 numIndices = 0; 591 k0 = 1 + m_tfans.Begin(f); 592 k1 = m_tfans.End(f); 593 for(long k = k0; k < k1; k++) 594 { 595 v0 = m_tfans.GetVertex(k); 596 if (m_vtags[v0] == 0) 597 { 598 ops[numOps++] = 0; 599 m_vtags[v0] = 1; 600 m_vmap[v0] = m_vertexCount++; 601 m_invVMap[m_vmap[v0]] = v0; 602 m_vfifo.PushBack(v0); 603 m_visitedVertices[m_numVisitedVertices++] = m_vmap[v0]; 604 } 605 else 606 { 607 ops[numOps++] = 1; 608 pos = 0; 609 found = 0; 610 for(long u=0; u < m_numVisitedVertices; ++u) 611 { 612 pos++; 613 if (m_visitedVertices[u] == m_vmap[v0]) 614 { 615 found = 1; 616 break; 617 } 618 } 619 if (found == 1) 620 { 621 indices[numIndices++] = -pos; 622 } 623 else 624 { 625 indices[numIndices++] = m_vmap[v0] - m_vmap[focusVertex]; 626 } 627 } 628 } 629 //----------------------------------------------- 630 if (IsCase0(degree, numIndices, ops, indices)) 631 { 632 // ops: 1000001 vertices: -1 -2 633 m_ctfans.PushConfig(0); 634 } 635 else if (IsCase1(degree, numIndices, ops, indices)) 636 { 637 // ops: 1xxxxxx1 vertices: -1 x x x x x -2 638 long u = 1; 639 for(u = 1; u < degree-1; u++) 640 { 641 m_ctfans.PushOperation(ops[u]); 642 } 643 for(u =1; u < numIndices-1; u++) 644 { 645 m_ctfans.PushIndex(indices[u]); 646 } 647 m_ctfans.PushConfig(1); 648 } 649 else if (IsCase2(degree, numIndices, ops, indices)) 650 { 651 // ops: 00000001 vertices: -1 652 m_ctfans.PushConfig(2); 653 } 654 else if (IsCase3(degree, numIndices, ops, indices)) 655 { 656 // ops: 00000001 vertices: -2 657 m_ctfans.PushConfig(3); 658 } 659 else if (IsCase4(degree, numIndices, ops, indices)) 660 { 661 // ops: 10000000 vertices: -1 662 m_ctfans.PushConfig(4); 663 } 664 else if (IsCase5(degree, numIndices, ops, indices)) 665 { 666 // ops: 10000000 vertices: -2 667 m_ctfans.PushConfig(5); 668 } 669 else if (IsCase6(degree, numIndices, ops, indices)) 670 { 671 // ops: 00000000 vertices: 672 m_ctfans.PushConfig(6); 673 } 674 else if (IsCase7(degree, numIndices, ops, indices)) 675 { 676 // ops: 1000001 vertices: -1 -2 677 m_ctfans.PushConfig(7); 678 } 679 else if (IsCase8(degree, numIndices, ops, indices)) 680 { 681 // ops: 1xxxxxx1 vertices: -2 x x x x x -1 682 long u = 1; 683 for(u =1; u < degree-1; u++) 684 { 685 m_ctfans.PushOperation(ops[u]); 686 } 687 for(u =1; u < numIndices-1; u++) 688 { 689 m_ctfans.PushIndex(indices[u]); 690 } 691 m_ctfans.PushConfig(8); 692 } 693 else 694 { 695 long u = 0; 696 for(u =0; u < degree; u++) 697 { 698 m_ctfans.PushOperation(ops[u]); 699 } 700 for(u =0; u < numIndices; u++) 701 { 702 m_ctfans.PushIndex(indices[u]); 703 } 704 m_ctfans.PushConfig(9); 705 } 706 } 707 } 708 return O3DGC_OK; 709 } 710 template <class T> 711 O3DGCErrorCode TriangleListEncoder<T>::ProcessVertex(const long focusVertex) 712 { 713 CompueLocalConnectivityInfo(focusVertex); 714 ComputeTFANDecomposition(focusVertex); 715 CompressTFAN(focusVertex); 716 return O3DGC_OK; 717 } 718} 719#endif //O3DGC_TRIANGLE_LIST_ENCODER_INL 720