├── .gitattributes ├── .gitignore ├── indexbuffercompression.cpp ├── indexbuffercompression.h ├── indexbuffercompressionformat.h ├── indexbufferdecodetables.h ├── indexbufferdecompression.cpp ├── indexbufferdecompression.h ├── indexcompressionconstants.h ├── readbitstream.h ├── readme.md └── writebitstream.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /indexbuffercompression.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #include "indexbuffercompression.h" 26 | #include "writebitstream.h" 27 | #include "indexcompressionconstants.h" 28 | #include 29 | 30 | #ifdef _MSC_VER 31 | #define IBC_INLINE __forceinline 32 | #else 33 | #define IBC_INLINE inline 34 | #endif 35 | 36 | // Individual vertex type classifications. 37 | enum VertexClassification 38 | { 39 | NEW_VERTEX = 0, 40 | CACHED_VERTEX = 1, 41 | FREE_VERTEX = 2 42 | }; 43 | 44 | // Individual case for handling a combination of vertice classifications. 45 | struct VertexCompressionCase 46 | { 47 | IndexBufferTriangleCodes code; 48 | uint32_t vertexOrder[ 3 ]; 49 | }; 50 | 51 | // This is a table for looking up the appropriate code and rotation for a set of vertex classifications. 52 | static const VertexCompressionCase CompressionCase[3][3][3] = 53 | { 54 | { // new 55 | { // new new 56 | { // new new new 57 | IB_NEW_NEW_NEW, { 0, 1, 2 } 58 | }, 59 | { // new new cached 60 | IB_NEW_NEW_CACHED, { 0, 1, 2 } 61 | }, 62 | { // new new free 63 | IB_NEW_NEW_FREE, { 0, 1, 2 } 64 | } 65 | }, 66 | { // new cached 67 | { // new cached new 68 | IB_NEW_NEW_CACHED, { 2, 0, 1 } 69 | }, 70 | { // new cached cached 71 | IB_NEW_CACHED_CACHED, { 0, 1, 2 } 72 | }, 73 | { // new cached free 74 | IB_NEW_CACHED_FREE, { 0, 1, 2 } 75 | } 76 | }, 77 | { // new free 78 | { // new free new 79 | IB_NEW_NEW_FREE, { 2, 0, 1 } 80 | }, 81 | { // new free cached 82 | IB_NEW_FREE_CACHED, { 0, 1, 2 } 83 | }, 84 | { // new free free 85 | IB_NEW_FREE_FREE, { 0, 1, 2 } 86 | } 87 | } 88 | }, 89 | { // cached 90 | { // cached new 91 | { // cached new new 92 | IB_NEW_NEW_CACHED, { 1, 2, 0 } 93 | }, 94 | { // cached new cached 95 | IB_NEW_CACHED_CACHED, { 1, 2, 0 } 96 | }, 97 | { // cached new free 98 | IB_NEW_FREE_CACHED, { 1, 2, 0 } 99 | } 100 | }, 101 | { // cached cached 102 | { // cached cached new 103 | IB_NEW_CACHED_CACHED, { 2, 0, 1 } 104 | }, 105 | { // cached cached cached 106 | IB_CACHED_CACHED_CACHED, { 0, 1, 2 } 107 | }, 108 | { // cached cached free 109 | IB_CACHED_CACHED_FREE, { 0, 1, 2 } 110 | } 111 | }, 112 | { // cached free 113 | { // cached free new 114 | IB_NEW_CACHED_FREE, { 2, 0, 1 } 115 | }, 116 | { // cached free cached 117 | IB_CACHED_CACHED_FREE, { 2, 0, 1 } 118 | }, 119 | { // cached free free 120 | IB_CACHED_FREE_FREE, { 0, 1, 2 } 121 | } 122 | } 123 | }, 124 | { // free 125 | { // free new 126 | { // free new new 127 | IB_NEW_NEW_FREE, { 1, 2, 0 } 128 | }, 129 | { // free new cached 130 | IB_NEW_CACHED_FREE, { 1, 2, 0 } 131 | }, 132 | { // free new free 133 | IB_NEW_FREE_FREE, { 1, 2, 0 } 134 | } 135 | }, 136 | { // free cached 137 | { // free cached new 138 | IB_NEW_FREE_CACHED, { 2, 0, 1 } 139 | }, 140 | { // free cached cached 141 | IB_CACHED_CACHED_FREE, { 1, 2, 0 } 142 | }, 143 | { // free cached free 144 | IB_CACHED_FREE_FREE, { 1, 2, 0 } 145 | } 146 | }, 147 | { // free free 148 | { // free free new 149 | IB_NEW_FREE_FREE, { 2, 0, 1 } 150 | }, 151 | { // free free cached 152 | IB_CACHED_FREE_FREE, { 2, 0, 1 } 153 | }, 154 | { // free free free 155 | IB_FREE_FREE_FREE, { 0, 1, 2 } 156 | } 157 | } 158 | } 159 | }; 160 | 161 | // Prefix code table used for encoding edge bits 162 | static const PrefixCode EdgePrefixCodes[] = 163 | { 164 | { 1, 2 }, 165 | { 2, 2 }, 166 | { 0, 3 }, 167 | { 15, 4 }, 168 | { 11, 4 }, 169 | { 3, 4 }, 170 | { 7, 5 }, 171 | { 28, 5 }, 172 | { 20, 5 }, 173 | { 55, 6 }, 174 | { 12, 6 }, 175 | { 36, 6 }, 176 | { 23, 7 }, 177 | { 44, 7 }, 178 | { 215, 8 }, 179 | { 87, 8 }, 180 | { 196, 8 }, 181 | { 132, 8 }, 182 | { 236, 9 }, 183 | { 364, 9 }, 184 | { 324, 9 }, 185 | { 68, 9 }, 186 | { 1004, 10 }, 187 | { 492, 10 }, 188 | { 108, 10 }, 189 | { 772, 10 }, 190 | { 516, 10 }, 191 | { 4, 10 }, 192 | { 1644, 11 }, 193 | { 620, 11 }, 194 | { 1284, 11 }, 195 | { 260, 11 } 196 | }; 197 | 198 | // Prefix code table used for vertices 199 | static const PrefixCode CachedVertexPrefixCodes[] = 200 | { 201 | { 215, 8 }, 202 | { 0, 1 }, 203 | { 5, 3 }, 204 | { 3, 4 }, 205 | { 15, 5 }, 206 | { 11, 5 }, 207 | { 9, 5 }, 208 | { 1, 5 }, 209 | { 55, 6 }, 210 | { 39, 6 }, 211 | { 27, 6 }, 212 | { 25, 6 }, 213 | { 17, 6 }, 214 | { 63, 7 }, 215 | { 31, 7 }, 216 | { 23, 7 }, 217 | { 7, 7 }, 218 | { 59, 7 }, 219 | { 121, 7 }, 220 | { 113, 7 }, 221 | { 49, 7 }, 222 | { 255, 8 }, 223 | { 127, 8 }, 224 | { 223, 8 }, 225 | { 95, 8 }, 226 | { 87, 8 }, 227 | { 199, 8 }, 228 | { 71, 8 }, 229 | { 251, 8 }, 230 | { 123, 8 }, 231 | { 185, 8 }, 232 | { 57, 8 } 233 | }; 234 | 235 | // Prefix code table used for triangles 236 | static const PrefixCode TrianglePrefixCodes[] = 237 | { 238 | { 0, 1 }, 239 | { 3, 2 }, 240 | { 5, 3 }, 241 | { 49, 7 }, 242 | { 33, 7 }, 243 | { 81, 7 }, 244 | { 9, 5 }, 245 | { 113, 7 }, 246 | { 57, 7 }, 247 | { 25, 6 }, 248 | { 121, 7 }, 249 | { 17, 7 }, 250 | { 1, 6 }, 251 | { 97, 7 } 252 | }; 253 | 254 | // Constant value for vertices that don't get mapped in the vertex re-map. 255 | static const uint32_t VERTEX_NOT_MAPPED = 0xFFFFFFFF; 256 | 257 | // Classify a vertex as new, cached or free, outputting the relative position in the vertex indice cache FIFO. 258 | static IBC_INLINE VertexClassification ClassifyVertex( uint32_t vertex, const uint32_t* vertexRemap, const uint32_t* vertexFifo, uint32_t verticesRead, uint32_t& cachedVertexIndex ) 259 | { 260 | if ( vertexRemap[ vertex ] == VERTEX_NOT_MAPPED ) 261 | { 262 | return NEW_VERTEX; 263 | } 264 | else 265 | { 266 | int32_t lowestVertexCursor = verticesRead >= VERTEX_FIFO_SIZE ? verticesRead - VERTEX_FIFO_SIZE : 0; 267 | 268 | // Probe backwards in the vertex FIFO for a cached vertex 269 | for ( int32_t vertexCursor = verticesRead - 1; vertexCursor >= lowestVertexCursor; --vertexCursor ) 270 | { 271 | if ( vertexFifo[ vertexCursor & VERTEX_FIFO_MASK ] == vertex ) 272 | { 273 | cachedVertexIndex = ( verticesRead - 1 ) - vertexCursor; 274 | 275 | return CACHED_VERTEX; 276 | } 277 | } 278 | 279 | return FREE_VERTEX; 280 | } 281 | } 282 | 283 | // Compress using triangle codes/prefix coding. 284 | template 285 | void CompressTriangleCodesPrefixCodes( 286 | const Ty* triangles, 287 | uint32_t triangleCount, 288 | uint32_t* vertexRemap, 289 | uint32_t vertexCount, 290 | WriteBitstream& output ) 291 | { 292 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 293 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 294 | 295 | uint32_t edgesRead = 0; 296 | uint32_t verticesRead = 0; 297 | uint32_t newVertices = 0; 298 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 299 | 300 | assert( vertexCount < 0xFFFFFFFF ); 301 | 302 | uint32_t* vertexRemapEnd = vertexRemap + vertexCount; 303 | 304 | // clear the vertex remapping to "not found" value of 0xFFFFFFFF - dirty, but low overhead. 305 | for ( uint32_t* remappedVertex = vertexRemap; remappedVertex < vertexRemapEnd; ++remappedVertex ) 306 | { 307 | *remappedVertex = VERTEX_NOT_MAPPED; 308 | } 309 | 310 | // iterate through the triangles 311 | for ( const Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 312 | { 313 | int32_t lowestEdgeCursor = edgesRead >= EDGE_FIFO_SIZE ? edgesRead - EDGE_FIFO_SIZE : 0; 314 | int32_t edgeCursor = edgesRead - 1; 315 | bool foundEdge = false; 316 | 317 | int32_t spareVertex = 0; 318 | 319 | // check to make sure that there are no degenerate triangles. 320 | assert( triangle[ 0 ] != triangle[ 1 ] && triangle[ 1 ] != triangle[ 2 ] && triangle[ 2 ] != triangle[ 0 ] ); 321 | 322 | // Probe back through the edge fifo to see if one of the triangle edges is in the FIFO 323 | for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor ) 324 | { 325 | const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ]; 326 | 327 | // check all the edges in order and save the free vertex. 328 | if ( edge.second == triangle[ 0 ] && edge.first == triangle[ 1 ] ) 329 | { 330 | foundEdge = true; 331 | spareVertex = 2; 332 | break; 333 | } 334 | else if ( edge.second == triangle[ 1 ] && edge.first == triangle[ 2 ] ) 335 | { 336 | foundEdge = true; 337 | spareVertex = 0; 338 | break; 339 | } 340 | else if ( edge.second == triangle[ 2 ] && edge.first == triangle[ 0 ] ) 341 | { 342 | foundEdge = true; 343 | spareVertex = 1; 344 | break; 345 | } 346 | } 347 | 348 | // we found an edge so write it out, so classify a vertex and then write out the correct code. 349 | if ( foundEdge ) 350 | { 351 | uint32_t cachedVertex; 352 | 353 | uint32_t spareVertexIndice = triangle[ spareVertex ]; 354 | VertexClassification freeVertexClass = ClassifyVertex( spareVertexIndice, vertexRemap, vertexFifo, verticesRead, cachedVertex ); 355 | uint32_t relativeEdge = ( edgesRead - 1 ) - edgeCursor; 356 | 357 | switch ( freeVertexClass ) 358 | { 359 | case NEW_VERTEX: 360 | 361 | output.WritePrefixCode( IB_EDGE_NEW, TrianglePrefixCodes ); 362 | output.WritePrefixCode( relativeEdge, EdgePrefixCodes ); 363 | 364 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; 365 | vertexRemap[ spareVertexIndice ] = newVertices; 366 | 367 | ++verticesRead; 368 | ++newVertices; 369 | break; 370 | 371 | case CACHED_VERTEX: 372 | 373 | output.WritePrefixCode( IB_EDGE_CACHED, TrianglePrefixCodes ); 374 | output.WritePrefixCode( relativeEdge, EdgePrefixCodes ); 375 | output.WritePrefixCode( cachedVertex, CachedVertexPrefixCodes ); 376 | 377 | break; 378 | 379 | case FREE_VERTEX: 380 | 381 | output.WritePrefixCode( IB_EDGE_FREE, TrianglePrefixCodes ); 382 | output.WritePrefixCode( relativeEdge, EdgePrefixCodes ); 383 | 384 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; 385 | 386 | ++verticesRead; 387 | 388 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ spareVertexIndice ] ); 389 | 390 | break; 391 | } 392 | 393 | // Populate the edge fifo with the remaining edges 394 | // Note - the winding order is important as we'll need to re-produce this on decompression. 395 | // The edges are put in as if the found edge is the first edge in the triangle (which it will be when we 396 | // reconstruct). 397 | switch ( spareVertex ) 398 | { 399 | case 0: 400 | 401 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 402 | 403 | ++edgesRead; 404 | 405 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 406 | 407 | ++edgesRead; 408 | break; 409 | 410 | case 1: 411 | 412 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 413 | 414 | ++edgesRead; 415 | 416 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 417 | 418 | ++edgesRead; 419 | break; 420 | 421 | case 2: 422 | 423 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 424 | 425 | ++edgesRead; 426 | 427 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 428 | 429 | ++edgesRead; 430 | break; 431 | } 432 | } 433 | else 434 | { 435 | VertexClassification classifications[ 3 ]; 436 | uint32_t cachedVertexIndices[ 3 ]; 437 | 438 | // classify each vertex as new, cached or free, potentially extracting a cached indice. 439 | classifications[ 0 ] = ClassifyVertex( triangle[ 0 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 0 ] ); 440 | classifications[ 1 ] = ClassifyVertex( triangle[ 1 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 1 ] ); 441 | classifications[ 2 ] = ClassifyVertex( triangle[ 2 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 2 ] ); 442 | 443 | // use the classifications to lookup the matching compression code and potentially rotate the order of the vertices. 444 | const VertexCompressionCase& compressionCase = CompressionCase[ classifications[ 0 ] ][ classifications[ 1 ] ][ classifications[ 2 ] ]; 445 | 446 | // rotate the order of the vertices based on the compression classification. 447 | uint32_t reorderedTriangle[ 3 ]; 448 | 449 | reorderedTriangle[ 0 ] = triangle[ compressionCase.vertexOrder[ 0 ] ]; 450 | reorderedTriangle[ 1 ] = triangle[ compressionCase.vertexOrder[ 1 ] ]; 451 | reorderedTriangle[ 2 ] = triangle[ compressionCase.vertexOrder[ 2 ] ]; 452 | 453 | output.WritePrefixCode( compressionCase.code, TrianglePrefixCodes ); 454 | 455 | switch ( compressionCase.code ) 456 | { 457 | case IB_NEW_NEW_NEW: 458 | { 459 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = triangle[ 0 ]; 460 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = triangle[ 1 ]; 461 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = triangle[ 2 ]; 462 | 463 | vertexRemap[ triangle[ 0 ] ] = newVertices; 464 | vertexRemap[ triangle[ 1 ] ] = newVertices + 1; 465 | vertexRemap[ triangle[ 2 ] ] = newVertices + 2; 466 | 467 | verticesRead += 3; 468 | newVertices += 3; 469 | 470 | break; 471 | } 472 | case IB_NEW_NEW_CACHED: 473 | { 474 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 475 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 476 | 477 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CachedVertexPrefixCodes ); 478 | 479 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 480 | vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; 481 | 482 | verticesRead += 2; 483 | newVertices += 2; 484 | 485 | break; 486 | } 487 | case IB_NEW_NEW_FREE: 488 | { 489 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 490 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 491 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 492 | 493 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 494 | 495 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 496 | vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; 497 | 498 | verticesRead += 3; 499 | newVertices += 2; 500 | 501 | break; 502 | } 503 | case IB_NEW_CACHED_CACHED: 504 | { 505 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 506 | 507 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CachedVertexPrefixCodes ); 508 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CachedVertexPrefixCodes ); 509 | 510 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 511 | verticesRead += 1; 512 | newVertices += 1; 513 | 514 | break; 515 | } 516 | case IB_NEW_CACHED_FREE: 517 | { 518 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 519 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 520 | 521 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CachedVertexPrefixCodes ); 522 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 523 | 524 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 525 | 526 | verticesRead += 2; 527 | newVertices += 1; 528 | 529 | break; 530 | } 531 | case IB_NEW_FREE_CACHED: 532 | { 533 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 534 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 535 | 536 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 537 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CachedVertexPrefixCodes ); 538 | 539 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 540 | 541 | verticesRead += 2; 542 | newVertices += 1; 543 | 544 | break; 545 | } 546 | case IB_NEW_FREE_FREE: 547 | { 548 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 549 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 550 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 551 | 552 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 553 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 554 | 555 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 556 | 557 | verticesRead += 3; 558 | newVertices += 1; 559 | 560 | break; 561 | } 562 | case IB_CACHED_CACHED_CACHED: 563 | { 564 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CachedVertexPrefixCodes ); 565 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CachedVertexPrefixCodes ); 566 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CachedVertexPrefixCodes ); 567 | 568 | break; 569 | } 570 | case IB_CACHED_CACHED_FREE: 571 | { 572 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 573 | 574 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CachedVertexPrefixCodes ); 575 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CachedVertexPrefixCodes ); 576 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 577 | 578 | verticesRead += 1; 579 | 580 | break; 581 | } 582 | case IB_CACHED_FREE_FREE: 583 | { 584 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 585 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 586 | 587 | output.WritePrefixCode( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CachedVertexPrefixCodes ); 588 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 589 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 590 | 591 | verticesRead += 2; 592 | 593 | break; 594 | } 595 | case IB_FREE_FREE_FREE: 596 | { 597 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 598 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 599 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 600 | 601 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 0 ] ] ); 602 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 603 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 604 | 605 | verticesRead += 3; 606 | break; 607 | } 608 | 609 | default: // IB_EDGE_NEW, IB_EDGE_CACHED, IB_EDGE_0_NEW, IB_EDGE_1_NEW 610 | break; 611 | } 612 | 613 | // populate the edge fifo with the 3 most recent edges 614 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 0 ], reorderedTriangle[ 1 ] ); 615 | 616 | ++edgesRead; 617 | 618 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 1 ], reorderedTriangle[ 2 ] ); 619 | 620 | ++edgesRead; 621 | 622 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 2 ], reorderedTriangle[ 0 ] ); 623 | 624 | ++edgesRead; 625 | } 626 | } 627 | 628 | // Pad out the buffer to make sure we don't overflow when trying to read the bits for the last prefix code table lookup. 629 | output.Write( 0, LONGEST_PREFIX_CODE - 1 ); 630 | } 631 | 632 | 633 | template 634 | void CompressTriangleCodes1( const Ty* triangles, 635 | uint32_t triangleCount, 636 | uint32_t* vertexRemap, 637 | uint32_t vertexCount, 638 | WriteBitstream& output ) 639 | { 640 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 641 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 642 | 643 | uint32_t edgesRead = 0; 644 | uint32_t verticesRead = 0; 645 | uint32_t newVertices = 0; 646 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 647 | 648 | assert( vertexCount < 0xFFFFFFFF ); 649 | 650 | uint32_t* vertexRemapEnd = vertexRemap + vertexCount; 651 | 652 | // clear the vertex remapping to "not found" value of 0xFFFFFFFF - dirty, but low overhead. 653 | for ( uint32_t* remappedVertex = vertexRemap; remappedVertex < vertexRemapEnd; ++remappedVertex ) 654 | { 655 | *remappedVertex = VERTEX_NOT_MAPPED; 656 | } 657 | 658 | // iterate through the triangles 659 | for ( const Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 660 | { 661 | int32_t lowestEdgeCursor = edgesRead >= EDGE_FIFO_SIZE ? edgesRead - EDGE_FIFO_SIZE : 0; 662 | int32_t edgeCursor = edgesRead - 1; 663 | bool foundEdge = false; 664 | 665 | int32_t spareVertex = 0; 666 | 667 | // check to make sure that there are no degenerate triangles. 668 | assert( triangle[ 0 ] != triangle[ 1 ] && triangle[ 1 ] != triangle[ 2 ] && triangle[ 2 ] != triangle[ 0 ] ); 669 | 670 | // Probe back through the edge fifo to see if one of the triangle edges is in the FIFO 671 | for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor ) 672 | { 673 | const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ]; 674 | 675 | // check all the edges in order and save the free vertex. 676 | if ( edge.second == triangle[ 0 ] && edge.first == triangle[ 1 ] ) 677 | { 678 | foundEdge = true; 679 | spareVertex = 2; 680 | break; 681 | } 682 | else if ( edge.second == triangle[ 1 ] && edge.first == triangle[ 2 ] ) 683 | { 684 | foundEdge = true; 685 | spareVertex = 0; 686 | break; 687 | } 688 | else if ( edge.second == triangle[ 2 ] && edge.first == triangle[ 0 ] ) 689 | { 690 | foundEdge = true; 691 | spareVertex = 1; 692 | break; 693 | } 694 | } 695 | 696 | // we found an edge so write it out, so classify a vertex and then write out the correct code. 697 | if ( foundEdge ) 698 | { 699 | uint32_t cachedVertex; 700 | 701 | uint32_t spareVertexIndice = triangle[ spareVertex ]; 702 | VertexClassification freeVertexClass = ClassifyVertex( spareVertexIndice, vertexRemap, vertexFifo, verticesRead, cachedVertex ); 703 | uint32_t relativeEdge = ( edgesRead - 1 ) - edgeCursor; 704 | 705 | switch ( freeVertexClass ) 706 | { 707 | case NEW_VERTEX: 708 | 709 | switch ( relativeEdge ) 710 | { 711 | case 0: 712 | 713 | output.Write( IB_EDGE_0_NEW, IB_TRIANGLE_CODE_BITS ); 714 | break; 715 | 716 | case 1: 717 | 718 | output.Write( IB_EDGE_1_NEW, IB_TRIANGLE_CODE_BITS ); 719 | break; 720 | 721 | default: 722 | 723 | output.Write( IB_EDGE_NEW, IB_TRIANGLE_CODE_BITS ); 724 | output.Write( relativeEdge, CACHED_EDGE_BITS ); 725 | break; 726 | 727 | } 728 | 729 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; 730 | vertexRemap[ spareVertexIndice ] = newVertices; 731 | 732 | ++verticesRead; 733 | ++newVertices; 734 | break; 735 | 736 | case CACHED_VERTEX: 737 | 738 | output.Write( IB_EDGE_CACHED, IB_TRIANGLE_CODE_BITS ); 739 | output.Write( relativeEdge, CACHED_EDGE_BITS ); 740 | output.Write( cachedVertex, CACHED_VERTEX_BITS ); 741 | 742 | break; 743 | 744 | case FREE_VERTEX: 745 | 746 | output.Write( IB_EDGE_FREE, IB_TRIANGLE_CODE_BITS ); 747 | output.Write( relativeEdge, CACHED_EDGE_BITS ); 748 | 749 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; 750 | 751 | ++verticesRead; 752 | 753 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ spareVertexIndice ] ); 754 | 755 | break; 756 | 757 | } 758 | 759 | // Populate the edge fifo with the remaining edges 760 | // Note - the winding order is important as we'll need to re-produce this on decompression. 761 | // The edges are put in as if the found edge is the first edge in the triangle (which it will be when we 762 | // reconstruct). 763 | switch ( spareVertex ) 764 | { 765 | case 0: 766 | 767 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 768 | 769 | ++edgesRead; 770 | 771 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 772 | 773 | ++edgesRead; 774 | break; 775 | 776 | case 1: 777 | 778 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 779 | 780 | ++edgesRead; 781 | 782 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 783 | 784 | ++edgesRead; 785 | break; 786 | 787 | case 2: 788 | 789 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 790 | 791 | ++edgesRead; 792 | 793 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 794 | 795 | ++edgesRead; 796 | break; 797 | } 798 | } 799 | else 800 | { 801 | VertexClassification classifications[ 3 ]; 802 | uint32_t cachedVertexIndices[ 3 ]; 803 | 804 | // classify each vertex as new, cached or free, potentially extracting a cached indice. 805 | classifications[ 0 ] = ClassifyVertex( triangle[ 0 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 0 ] ); 806 | classifications[ 1 ] = ClassifyVertex( triangle[ 1 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 1 ] ); 807 | classifications[ 2 ] = ClassifyVertex( triangle[ 2 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 2 ] ); 808 | 809 | // use the classifications to lookup the matching compression code and potentially rotate the order of the vertices. 810 | const VertexCompressionCase& compressionCase = CompressionCase[ classifications[ 0 ] ][ classifications[ 1 ] ][ classifications[ 2 ] ]; 811 | 812 | // rotate the order of the vertices based on the compression classification. 813 | uint32_t reorderedTriangle[ 3 ]; 814 | 815 | reorderedTriangle[ 0 ] = triangle[ compressionCase.vertexOrder[ 0 ] ]; 816 | reorderedTriangle[ 1 ] = triangle[ compressionCase.vertexOrder[ 1 ] ]; 817 | reorderedTriangle[ 2 ] = triangle[ compressionCase.vertexOrder[ 2 ] ]; 818 | 819 | output.Write( compressionCase.code, IB_TRIANGLE_CODE_BITS ); 820 | 821 | switch ( compressionCase.code ) 822 | { 823 | case IB_NEW_NEW_NEW: 824 | { 825 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = triangle[ 0 ]; 826 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = triangle[ 1 ]; 827 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = triangle[ 2 ]; 828 | 829 | vertexRemap[ triangle[ 0 ] ] = newVertices; 830 | vertexRemap[ triangle[ 1 ] ] = newVertices + 1; 831 | vertexRemap[ triangle[ 2 ] ] = newVertices + 2; 832 | 833 | verticesRead += 3; 834 | newVertices += 3; 835 | 836 | break; 837 | } 838 | case IB_NEW_NEW_CACHED: 839 | { 840 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 841 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 842 | 843 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); 844 | 845 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 846 | vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; 847 | 848 | verticesRead += 2; 849 | newVertices += 2; 850 | 851 | break; 852 | } 853 | case IB_NEW_NEW_FREE: 854 | { 855 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 856 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 857 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 858 | 859 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 860 | 861 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 862 | vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; 863 | 864 | verticesRead += 3; 865 | newVertices += 2; 866 | 867 | break; 868 | } 869 | case IB_NEW_CACHED_CACHED: 870 | { 871 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 872 | 873 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); 874 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); 875 | 876 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 877 | verticesRead += 1; 878 | newVertices += 1; 879 | 880 | break; 881 | } 882 | case IB_NEW_CACHED_FREE: 883 | { 884 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 885 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 886 | 887 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); 888 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 889 | 890 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 891 | 892 | verticesRead += 2; 893 | newVertices += 1; 894 | 895 | break; 896 | } 897 | case IB_NEW_FREE_CACHED: 898 | { 899 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 900 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 901 | 902 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 903 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); 904 | 905 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 906 | 907 | verticesRead += 2; 908 | newVertices += 1; 909 | 910 | break; 911 | } 912 | case IB_NEW_FREE_FREE: 913 | { 914 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 915 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 916 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 917 | 918 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 919 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 920 | 921 | vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; 922 | 923 | verticesRead += 3; 924 | newVertices += 1; 925 | 926 | break; 927 | } 928 | case IB_CACHED_CACHED_CACHED: 929 | { 930 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); 931 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); 932 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); 933 | 934 | break; 935 | } 936 | case IB_CACHED_CACHED_FREE: 937 | { 938 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 939 | 940 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); 941 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); 942 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 943 | 944 | verticesRead += 1; 945 | 946 | break; 947 | } 948 | case IB_CACHED_FREE_FREE: 949 | { 950 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 951 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 952 | 953 | output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); 954 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 955 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 956 | 957 | verticesRead += 2; 958 | 959 | break; 960 | } 961 | case IB_FREE_FREE_FREE: 962 | { 963 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; 964 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; 965 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; 966 | 967 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 0 ] ] ); 968 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); 969 | output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); 970 | 971 | verticesRead += 3; 972 | break; 973 | } 974 | 975 | default: // IB_EDGE_NEW, IB_EDGE_CACHED, IB_EDGE_0_NEW, IB_EDGE_1_NEW 976 | break; 977 | } 978 | 979 | // populate the edge fifo with the 3 most recent edges 980 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 0 ], reorderedTriangle[ 1 ] ); 981 | 982 | ++edgesRead; 983 | 984 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 1 ], reorderedTriangle[ 2 ] ); 985 | 986 | ++edgesRead; 987 | 988 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 2 ], reorderedTriangle[ 0 ] ); 989 | 990 | ++edgesRead; 991 | } 992 | } 993 | } 994 | 995 | 996 | 997 | // Output the compression information for a single vertex, remapping any new vertices and updating the vertex fifo where needed. 998 | static IBC_INLINE void OutputVertex( uint32_t vertex, 999 | uint32_t* vertexRemap, 1000 | uint32_t& newVertexCount, 1001 | uint32_t* vertexFifo, 1002 | uint32_t& verticesRead, 1003 | WriteBitstream& output ) 1004 | { 1005 | // Check if a vertex hasn't been remapped, 1006 | if ( vertexRemap[ vertex ] == VERTEX_NOT_MAPPED ) 1007 | { 1008 | // no remap, so remap to the current high watermark and output a new vertex code. 1009 | vertexRemap[ vertex ] = newVertexCount; 1010 | 1011 | output.Write( IB_NEW_VERTEX, IB_VERTEX_CODE_BITS ); 1012 | 1013 | ++newVertexCount; 1014 | 1015 | // new vertices go into the vertex FIFO 1016 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = vertex; 1017 | 1018 | ++verticesRead; 1019 | } 1020 | else 1021 | { 1022 | int32_t lowestVertexCursor = verticesRead >= VERTEX_FIFO_SIZE ? verticesRead - VERTEX_FIFO_SIZE : 0; 1023 | 1024 | // Probe backwards in the vertex FIFO for a cached vertex 1025 | for ( int32_t vertexCursor = verticesRead - 1; vertexCursor >= lowestVertexCursor; --vertexCursor ) 1026 | { 1027 | if ( vertexFifo[ vertexCursor & VERTEX_FIFO_MASK ] == vertex ) 1028 | { 1029 | // found a cached vertex, so write out the code for a cached vertex, as the relative index into the fifo. 1030 | output.Write( IB_CACHED_VERTEX, IB_VERTEX_CODE_BITS ); 1031 | output.Write( ( verticesRead - 1 ) - vertexCursor, CACHED_VERTEX_BITS ); 1032 | 1033 | return; 1034 | } 1035 | } 1036 | 1037 | // no cached vertex found, so write out a free vertex 1038 | output.Write( IB_FREE_VERTEX, IB_VERTEX_CODE_BITS ); 1039 | 1040 | // free vertices are relative to the latest new vertex. 1041 | uint32_t vertexOutput = ( newVertexCount - 1 ) - vertexRemap[ vertex ]; 1042 | 1043 | // v-int encode the free vertex index. 1044 | output.WriteVInt( vertexOutput ); 1045 | 1046 | // free vertices go back into the vertex cache. 1047 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = vertex; 1048 | 1049 | ++verticesRead; 1050 | } 1051 | 1052 | } 1053 | 1054 | template 1055 | void CompressIndiceCodes1( const Ty* triangles, 1056 | uint32_t triangleCount, 1057 | uint32_t* vertexRemap, 1058 | uint32_t vertexCount, 1059 | WriteBitstream& output ) 1060 | { 1061 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 1062 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 1063 | 1064 | uint32_t edgesRead = 0; 1065 | uint32_t verticesRead = 0; 1066 | uint32_t newVertices = 0; 1067 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 1068 | 1069 | assert( vertexCount < 0xFFFFFFFF ); 1070 | 1071 | uint32_t* vertexRemapEnd = vertexRemap + vertexCount; 1072 | 1073 | // clear the vertex remapping to "not found" value of 0xFFFFFFFF - dirty, but low overhead. 1074 | for ( uint32_t* remappedVertex = vertexRemap; remappedVertex < vertexRemapEnd; ++remappedVertex ) 1075 | { 1076 | *remappedVertex = VERTEX_NOT_MAPPED; 1077 | } 1078 | 1079 | // iterate through the triangles 1080 | for ( const Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 1081 | { 1082 | int32_t lowestEdgeCursor = edgesRead >= EDGE_FIFO_SIZE ? edgesRead - EDGE_FIFO_SIZE : 0; 1083 | int32_t edgeCursor = edgesRead - 1; 1084 | bool foundEdge = false; 1085 | 1086 | int32_t freeVertex = -1; // should not be negative 1 if found, this is not used as a signal, but for debugging. 1087 | 1088 | // Probe back through the edge fifo to see if one of the triangle edges is in the FIFO 1089 | for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor ) 1090 | { 1091 | const Edge& edge = edgeFifo[ edgeCursor & VERTEX_FIFO_MASK ]; 1092 | 1093 | // check all the edges in order and save the free vertex. 1094 | if ( edge.second == triangle[ 0 ] && edge.first == triangle[ 1 ] ) 1095 | { 1096 | foundEdge = true; 1097 | freeVertex = 2; 1098 | break; 1099 | } 1100 | else if ( edge.second == triangle[ 1 ] && edge.first == triangle[ 2 ] ) 1101 | { 1102 | foundEdge = true; 1103 | freeVertex = 0; 1104 | break; 1105 | } 1106 | else if ( edge.second == triangle[ 2 ] && edge.first == triangle[ 0 ] ) 1107 | { 1108 | foundEdge = true; 1109 | freeVertex = 1; 1110 | break; 1111 | } 1112 | } 1113 | 1114 | // we found an edge so write it out, then output the vertex 1115 | if ( foundEdge ) 1116 | { 1117 | output.Write( IB_CACHED_EDGE, IB_VERTEX_CODE_BITS ); 1118 | output.Write( ( edgesRead - 1 ) - edgeCursor, CACHED_EDGE_BITS ); 1119 | 1120 | const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ]; 1121 | 1122 | OutputVertex( triangle[ freeVertex ], vertexRemap, newVertices, vertexFifo, verticesRead, output ); 1123 | 1124 | // edge is in reverse order to last triangle it occurred on (and it will only be a match if this is the case). 1125 | // so put the vertices into the fifo in that order. 1126 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = edge.second; 1127 | 1128 | ++verticesRead; 1129 | 1130 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = edge.first; 1131 | 1132 | ++verticesRead; 1133 | 1134 | // Populate the edge fifo with the remaining edges 1135 | // Note - the winding order is important as we'll need to re-produce this on decompression. 1136 | // The edges are put in as if the found edge is the first edge in the triangle (which it will be when we 1137 | // reconstruct). 1138 | switch ( freeVertex ) 1139 | { 1140 | case 0: 1141 | 1142 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 1143 | 1144 | ++edgesRead; 1145 | 1146 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 1147 | 1148 | ++edgesRead; 1149 | break; 1150 | 1151 | case 1: 1152 | 1153 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 1154 | 1155 | ++edgesRead; 1156 | 1157 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 1158 | 1159 | ++edgesRead; 1160 | break; 1161 | 1162 | case 2: 1163 | 1164 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 1165 | 1166 | ++edgesRead; 1167 | 1168 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 1169 | 1170 | ++edgesRead; 1171 | break; 1172 | } 1173 | } 1174 | else 1175 | { 1176 | // no edge, so we need to output all the vertices. 1177 | OutputVertex( triangle[ 0 ], vertexRemap, newVertices, vertexFifo, verticesRead, output ); 1178 | OutputVertex( triangle[ 1 ], vertexRemap, newVertices, vertexFifo, verticesRead, output ); 1179 | OutputVertex( triangle[ 2 ], vertexRemap, newVertices, vertexFifo, verticesRead, output ); 1180 | 1181 | // populate the edge fifo with the 3 most recent edges 1182 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 1183 | 1184 | ++edgesRead; 1185 | 1186 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 1187 | 1188 | ++edgesRead; 1189 | 1190 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 1191 | 1192 | ++edgesRead; 1193 | } 1194 | } 1195 | } 1196 | 1197 | // Detects if there are any degenerate triangles in a set of triangles, where there is 1 or more duplicate vertices. 1198 | template 1199 | bool ContainsDegenerates( const Ty* triangles, uint32_t triangleCount ) 1200 | { 1201 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 1202 | bool result = false; 1203 | 1204 | for ( const Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 1205 | { 1206 | if ( triangle[ 0 ] == triangle[ 1 ] || triangle[ 0 ] == triangle[ 2 ] || triangle[ 1 ] == triangle[ 2 ] ) 1207 | { 1208 | result = true; 1209 | break; 1210 | } 1211 | } 1212 | 1213 | return result; 1214 | } 1215 | 1216 | template 1217 | void CompressIndexBuffer( const Ty* triangles, 1218 | uint32_t triangleCount, 1219 | uint32_t* vertexRemap, 1220 | uint32_t vertexCount, 1221 | IndexBufferCompressionFormat format, 1222 | WriteBitstream& output ) 1223 | { 1224 | switch ( format ) 1225 | { 1226 | case IBCF_PER_INDICE_1: 1227 | 1228 | output.WriteVInt( IBCF_PER_INDICE_1 ); 1229 | CompressIndiceCodes1( triangles, triangleCount, vertexRemap, vertexCount, output ); 1230 | break; 1231 | 1232 | case IBCF_PER_TRIANGLE_1: 1233 | 1234 | output.WriteVInt( IBCF_PER_TRIANGLE_1 ); 1235 | CompressTriangleCodes1( triangles, triangleCount, vertexRemap, vertexCount, output ); 1236 | break; 1237 | 1238 | case IBCF_AUTO: 1239 | 1240 | if ( ContainsDegenerates( triangles, triangleCount ) ) 1241 | { 1242 | output.WriteVInt( IBCF_PER_INDICE_1 ); 1243 | CompressIndiceCodes1( triangles, triangleCount, vertexRemap, vertexCount, output ); 1244 | } 1245 | else 1246 | { 1247 | output.WriteVInt( IBCF_PER_TRIANGLE_1 ); 1248 | CompressTriangleCodes1( triangles, triangleCount, vertexRemap, vertexCount, output ); 1249 | } 1250 | 1251 | break; 1252 | 1253 | case IBCF_PER_TRIANGLE_PREFIX_ENTROPY: 1254 | 1255 | output.WriteVInt( IBCF_PER_TRIANGLE_PREFIX_ENTROPY ); 1256 | CompressTriangleCodesPrefixCodes( triangles, triangleCount, vertexRemap, vertexCount, output ); 1257 | break; 1258 | 1259 | } 1260 | } 1261 | 1262 | void CompressIndexBuffer( const uint16_t* triangles, 1263 | uint32_t triangleCount, 1264 | uint32_t* vertexRemap, 1265 | uint32_t vertexCount, 1266 | IndexBufferCompressionFormat format, 1267 | WriteBitstream& output ) 1268 | { 1269 | 1270 | CompressIndexBuffer( triangles, triangleCount, vertexRemap, vertexCount, format, output ); 1271 | } 1272 | 1273 | void CompressIndexBuffer( const uint32_t* triangles, 1274 | uint32_t triangleCount, 1275 | uint32_t* vertexRemap, 1276 | uint32_t vertexCount, 1277 | IndexBufferCompressionFormat format, 1278 | WriteBitstream& output ) 1279 | { 1280 | CompressIndexBuffer( triangles, triangleCount, vertexRemap, vertexCount, format, output ); 1281 | } 1282 | 1283 | -------------------------------------------------------------------------------- /indexbuffercompression.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef INDEX_BUFFER_COMPRESSION_H__ 26 | #define INDEX_BUFFER_COMPRESSION_H__ 27 | #pragma once 28 | 29 | #include 30 | #include "writebitstream.h" 31 | #include "indexbuffercompressionformat.h" 32 | 33 | // Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised 34 | // order). 35 | // 36 | // It works by outputting a code (along with any required index symbols) per vertex. 37 | // 38 | // Parameters: 39 | // [in] triangles - A typical triangle list index buffer (3 indices to vertices per triangle). 16 bit indices. 40 | // [in] triangle count - The number of triangles to process. 41 | // [out] vertexRemap - This will be populated with re-mappings that map old vertices to new vertex locations (a new ordering), 42 | // where indexing with the old vertex index will get you the new one. Vertices that are unused will 43 | // be mapped to 0xFFFFFFFF. 44 | // You should re-order the vertices and removed unused ones based on the vertex remap, instead of storing 45 | // the remap. 46 | // It should be allocated as a with at least vertexCount entries. 47 | // [in] vertexCount - The number of vertices in the mesh. This should be less than 0xFFFFFFFF/2^32 - 1. 48 | // [in] format - The compression format to use for encoding - note the format will be encoded with the compressed data so the decompressor can select the correct algorithm. 49 | // [in] output - The stream that the compressed data will be written to. Note that we will not flush/finish the stream 50 | // in case something else is going to be written after, so WriteBitstream::Finish will need to be called after this. 51 | void CompressIndexBuffer( const uint16_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, IndexBufferCompressionFormat format, WriteBitstream& output ); 52 | 53 | // Same as above but 32bit indices. 54 | void CompressIndexBuffer( const uint32_t* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, IndexBufferCompressionFormat format, WriteBitstream& output ); 55 | 56 | #endif // -- INDEX_BUFFER_COMPRESSION_H__ 57 | -------------------------------------------------------------------------------- /indexbuffercompressionformat.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef INDEX_BUFFER_COMPRESSION_FORMAT_H__ 26 | #define INDEX_BUFFER_COMPRESSION_FORMAT_H__ 27 | #pragma once 28 | 29 | enum IndexBufferCompressionFormat 30 | { 31 | // Per indice encoding - handles degenerates, but has worse compression/decompression speed and compression. 32 | IBCF_PER_INDICE_1 = 0, 33 | 34 | // Per triangle encoding - better compression/speed, does not handle degenerates. 35 | IBCF_PER_TRIANGLE_1 = 1, 36 | 37 | // Automatically pick the best encoding dependent on whether degenerate triangles are detected in the mesh. 38 | // Will take longer to compress (due to the degenerate triangle check). 39 | IBCF_AUTO = 2, 40 | 41 | // Uses a similar coder to the ICBF_PER_TRIANGLE_1 coder, but does not use the edge 0 and 1 new codes 42 | // Uses a prefix based entropy encoder (same family as huffman and polar codes), with fixed 43 | // table coding. 44 | IBCF_PER_TRIANGLE_PREFIX_ENTROPY = 3 45 | }; 46 | 47 | #endif // -- INDEX_BUFFER_COMPRESSION_FORMAT_H__ -------------------------------------------------------------------------------- /indexbufferdecodetables.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | // NOTE - these tables are in this file for readability / navagability and should *only* be included in 27 | // indexbufferdecompression.cpp 28 | 29 | #pragma once 30 | 31 | // Prefix code decoding table used for triangle codes 32 | static const PrefixCodeTableEntry TriangleDecoding[] = 33 | { 34 | { 0, 1 }, 35 | { 12, 6 }, 36 | { 0, 1 }, 37 | { 1, 2 }, 38 | { 0, 1 }, 39 | { 2, 3 }, 40 | { 0, 1 }, 41 | { 1, 2 }, 42 | { 0, 1 }, 43 | { 6, 5 }, 44 | { 0, 1 }, 45 | { 1, 2 }, 46 | { 0, 1 }, 47 | { 2, 3 }, 48 | { 0, 1 }, 49 | { 1, 2 }, 50 | { 0, 1 }, 51 | { 11, 7 }, 52 | { 0, 1 }, 53 | { 1, 2 }, 54 | { 0, 1 }, 55 | { 2, 3 }, 56 | { 0, 1 }, 57 | { 1, 2 }, 58 | { 0, 1 }, 59 | { 9, 6 }, 60 | { 0, 1 }, 61 | { 1, 2 }, 62 | { 0, 1 }, 63 | { 2, 3 }, 64 | { 0, 1 }, 65 | { 1, 2 }, 66 | { 0, 1 }, 67 | { 4, 7 }, 68 | { 0, 1 }, 69 | { 1, 2 }, 70 | { 0, 1 }, 71 | { 2, 3 }, 72 | { 0, 1 }, 73 | { 1, 2 }, 74 | { 0, 1 }, 75 | { 6, 5 }, 76 | { 0, 1 }, 77 | { 1, 2 }, 78 | { 0, 1 }, 79 | { 2, 3 }, 80 | { 0, 1 }, 81 | { 1, 2 }, 82 | { 0, 1 }, 83 | { 3, 7 }, 84 | { 0, 1 }, 85 | { 1, 2 }, 86 | { 0, 1 }, 87 | { 2, 3 }, 88 | { 0, 1 }, 89 | { 1, 2 }, 90 | { 0, 1 }, 91 | { 8, 7 }, 92 | { 0, 1 }, 93 | { 1, 2 }, 94 | { 0, 1 }, 95 | { 2, 3 }, 96 | { 0, 1 }, 97 | { 1, 2 }, 98 | { 0, 1 }, 99 | { 12, 6 }, 100 | { 0, 1 }, 101 | { 1, 2 }, 102 | { 0, 1 }, 103 | { 2, 3 }, 104 | { 0, 1 }, 105 | { 1, 2 }, 106 | { 0, 1 }, 107 | { 6, 5 }, 108 | { 0, 1 }, 109 | { 1, 2 }, 110 | { 0, 1 }, 111 | { 2, 3 }, 112 | { 0, 1 }, 113 | { 1, 2 }, 114 | { 0, 1 }, 115 | { 5, 7 }, 116 | { 0, 1 }, 117 | { 1, 2 }, 118 | { 0, 1 }, 119 | { 2, 3 }, 120 | { 0, 1 }, 121 | { 1, 2 }, 122 | { 0, 1 }, 123 | { 9, 6 }, 124 | { 0, 1 }, 125 | { 1, 2 }, 126 | { 0, 1 }, 127 | { 2, 3 }, 128 | { 0, 1 }, 129 | { 1, 2 }, 130 | { 0, 1 }, 131 | { 13, 7 }, 132 | { 0, 1 }, 133 | { 1, 2 }, 134 | { 0, 1 }, 135 | { 2, 3 }, 136 | { 0, 1 }, 137 | { 1, 2 }, 138 | { 0, 1 }, 139 | { 6, 5 }, 140 | { 0, 1 }, 141 | { 1, 2 }, 142 | { 0, 1 }, 143 | { 2, 3 }, 144 | { 0, 1 }, 145 | { 1, 2 }, 146 | { 0, 1 }, 147 | { 7, 7 }, 148 | { 0, 1 }, 149 | { 1, 2 }, 150 | { 0, 1 }, 151 | { 2, 3 }, 152 | { 0, 1 }, 153 | { 1, 2 }, 154 | { 0, 1 }, 155 | { 10, 7 }, 156 | { 0, 1 }, 157 | { 1, 2 }, 158 | { 0, 1 }, 159 | { 2, 3 }, 160 | { 0, 1 }, 161 | { 1, 2 } 162 | }; 163 | 164 | // Prefix code decoding table used for vertex fifo codes. 165 | static const PrefixCodeTableEntry VertexDecoding[] = 166 | { 167 | { 1, 1 }, 168 | { 7, 5 }, 169 | { 1, 1 }, 170 | { 3, 4 }, 171 | { 1, 1 }, 172 | { 2, 3 }, 173 | { 1, 1 }, 174 | { 16, 7 }, 175 | { 1, 1 }, 176 | { 6, 5 }, 177 | { 1, 1 }, 178 | { 5, 5 }, 179 | { 1, 1 }, 180 | { 2, 3 }, 181 | { 1, 1 }, 182 | { 4, 5 }, 183 | { 1, 1 }, 184 | { 12, 6 }, 185 | { 1, 1 }, 186 | { 3, 4 }, 187 | { 1, 1 }, 188 | { 2, 3 }, 189 | { 1, 1 }, 190 | { 15, 7 }, 191 | { 1, 1 }, 192 | { 11, 6 }, 193 | { 1, 1 }, 194 | { 10, 6 }, 195 | { 1, 1 }, 196 | { 2, 3 }, 197 | { 1, 1 }, 198 | { 14, 7 }, 199 | { 1, 1 }, 200 | { 7, 5 }, 201 | { 1, 1 }, 202 | { 3, 4 }, 203 | { 1, 1 }, 204 | { 2, 3 }, 205 | { 1, 1 }, 206 | { 9, 6 }, 207 | { 1, 1 }, 208 | { 6, 5 }, 209 | { 1, 1 }, 210 | { 5, 5 }, 211 | { 1, 1 }, 212 | { 2, 3 }, 213 | { 1, 1 }, 214 | { 4, 5 }, 215 | { 1, 1 }, 216 | { 20, 7 }, 217 | { 1, 1 }, 218 | { 3, 4 }, 219 | { 1, 1 }, 220 | { 2, 3 }, 221 | { 1, 1 }, 222 | { 8, 6 }, 223 | { 1, 1 }, 224 | { 31, 8 }, 225 | { 1, 1 }, 226 | { 17, 7 }, 227 | { 1, 1 }, 228 | { 2, 3 }, 229 | { 1, 1 }, 230 | { 13, 7 }, 231 | { 1, 1 }, 232 | { 7, 5 }, 233 | { 1, 1 }, 234 | { 3, 4 }, 235 | { 1, 1 }, 236 | { 2, 3 }, 237 | { 1, 1 }, 238 | { 27, 8 }, 239 | { 1, 1 }, 240 | { 6, 5 }, 241 | { 1, 1 }, 242 | { 5, 5 }, 243 | { 1, 1 }, 244 | { 2, 3 }, 245 | { 1, 1 }, 246 | { 4, 5 }, 247 | { 1, 1 }, 248 | { 12, 6 }, 249 | { 1, 1 }, 250 | { 3, 4 }, 251 | { 1, 1 }, 252 | { 2, 3 }, 253 | { 1, 1 }, 254 | { 25, 8 }, 255 | { 1, 1 }, 256 | { 11, 6 }, 257 | { 1, 1 }, 258 | { 10, 6 }, 259 | { 1, 1 }, 260 | { 2, 3 }, 261 | { 1, 1 }, 262 | { 24, 8 }, 263 | { 1, 1 }, 264 | { 7, 5 }, 265 | { 1, 1 }, 266 | { 3, 4 }, 267 | { 1, 1 }, 268 | { 2, 3 }, 269 | { 1, 1 }, 270 | { 9, 6 }, 271 | { 1, 1 }, 272 | { 6, 5 }, 273 | { 1, 1 }, 274 | { 5, 5 }, 275 | { 1, 1 }, 276 | { 2, 3 }, 277 | { 1, 1 }, 278 | { 4, 5 }, 279 | { 1, 1 }, 280 | { 19, 7 }, 281 | { 1, 1 }, 282 | { 3, 4 }, 283 | { 1, 1 }, 284 | { 2, 3 }, 285 | { 1, 1 }, 286 | { 8, 6 }, 287 | { 1, 1 }, 288 | { 18, 7 }, 289 | { 1, 1 }, 290 | { 29, 8 }, 291 | { 1, 1 }, 292 | { 2, 3 }, 293 | { 1, 1 }, 294 | { 22, 8 }, 295 | { 1, 1 }, 296 | { 7, 5 }, 297 | { 1, 1 }, 298 | { 3, 4 }, 299 | { 1, 1 }, 300 | { 2, 3 }, 301 | { 1, 1 }, 302 | { 16, 7 }, 303 | { 1, 1 }, 304 | { 6, 5 }, 305 | { 1, 1 }, 306 | { 5, 5 }, 307 | { 1, 1 }, 308 | { 2, 3 }, 309 | { 1, 1 }, 310 | { 4, 5 }, 311 | { 1, 1 }, 312 | { 12, 6 }, 313 | { 1, 1 }, 314 | { 3, 4 }, 315 | { 1, 1 }, 316 | { 2, 3 }, 317 | { 1, 1 }, 318 | { 15, 7 }, 319 | { 1, 1 }, 320 | { 11, 6 }, 321 | { 1, 1 }, 322 | { 10, 6 }, 323 | { 1, 1 }, 324 | { 2, 3 }, 325 | { 1, 1 }, 326 | { 14, 7 }, 327 | { 1, 1 }, 328 | { 7, 5 }, 329 | { 1, 1 }, 330 | { 3, 4 }, 331 | { 1, 1 }, 332 | { 2, 3 }, 333 | { 1, 1 }, 334 | { 9, 6 }, 335 | { 1, 1 }, 336 | { 6, 5 }, 337 | { 1, 1 }, 338 | { 5, 5 }, 339 | { 1, 1 }, 340 | { 2, 3 }, 341 | { 1, 1 }, 342 | { 4, 5 }, 343 | { 1, 1 }, 344 | { 20, 7 }, 345 | { 1, 1 }, 346 | { 3, 4 }, 347 | { 1, 1 }, 348 | { 2, 3 }, 349 | { 1, 1 }, 350 | { 8, 6 }, 351 | { 1, 1 }, 352 | { 30, 8 }, 353 | { 1, 1 }, 354 | { 17, 7 }, 355 | { 1, 1 }, 356 | { 2, 3 }, 357 | { 1, 1 }, 358 | { 13, 7 }, 359 | { 1, 1 }, 360 | { 7, 5 }, 361 | { 1, 1 }, 362 | { 3, 4 }, 363 | { 1, 1 }, 364 | { 2, 3 }, 365 | { 1, 1 }, 366 | { 26, 8 }, 367 | { 1, 1 }, 368 | { 6, 5 }, 369 | { 1, 1 }, 370 | { 5, 5 }, 371 | { 1, 1 }, 372 | { 2, 3 }, 373 | { 1, 1 }, 374 | { 4, 5 }, 375 | { 1, 1 }, 376 | { 12, 6 }, 377 | { 1, 1 }, 378 | { 3, 4 }, 379 | { 1, 1 }, 380 | { 2, 3 }, 381 | { 1, 1 }, 382 | { 0, 8 }, 383 | { 1, 1 }, 384 | { 11, 6 }, 385 | { 1, 1 }, 386 | { 10, 6 }, 387 | { 1, 1 }, 388 | { 2, 3 }, 389 | { 1, 1 }, 390 | { 23, 8 }, 391 | { 1, 1 }, 392 | { 7, 5 }, 393 | { 1, 1 }, 394 | { 3, 4 }, 395 | { 1, 1 }, 396 | { 2, 3 }, 397 | { 1, 1 }, 398 | { 9, 6 }, 399 | { 1, 1 }, 400 | { 6, 5 }, 401 | { 1, 1 }, 402 | { 5, 5 }, 403 | { 1, 1 }, 404 | { 2, 3 }, 405 | { 1, 1 }, 406 | { 4, 5 }, 407 | { 1, 1 }, 408 | { 19, 7 }, 409 | { 1, 1 }, 410 | { 3, 4 }, 411 | { 1, 1 }, 412 | { 2, 3 }, 413 | { 1, 1 }, 414 | { 8, 6 }, 415 | { 1, 1 }, 416 | { 18, 7 }, 417 | { 1, 1 }, 418 | { 28, 8 }, 419 | { 1, 1 }, 420 | { 2, 3 }, 421 | { 1, 1 }, 422 | { 21, 8 } 423 | }; 424 | 425 | // Prefix code decoding table used for edge fifo codes 426 | static const PrefixCodeTableEntry EdgeDecoding[] = 427 | { 428 | { 2, 3 }, 429 | { 0, 2 }, 430 | { 1, 2 }, 431 | { 5, 4 }, 432 | { 27, 10 }, 433 | { 0, 2 }, 434 | { 1, 2 }, 435 | { 6, 5 }, 436 | { 2, 3 }, 437 | { 0, 2 }, 438 | { 1, 2 }, 439 | { 4, 4 }, 440 | { 10, 6 }, 441 | { 0, 2 }, 442 | { 1, 2 }, 443 | { 3, 4 }, 444 | { 2, 3 }, 445 | { 0, 2 }, 446 | { 1, 2 }, 447 | { 5, 4 }, 448 | { 8, 5 }, 449 | { 0, 2 }, 450 | { 1, 2 }, 451 | { 12, 7 }, 452 | { 2, 3 }, 453 | { 0, 2 }, 454 | { 1, 2 }, 455 | { 4, 4 }, 456 | { 7, 5 }, 457 | { 0, 2 }, 458 | { 1, 2 }, 459 | { 3, 4 }, 460 | { 2, 3 }, 461 | { 0, 2 }, 462 | { 1, 2 }, 463 | { 5, 4 }, 464 | { 11, 6 }, 465 | { 0, 2 }, 466 | { 1, 2 }, 467 | { 6, 5 }, 468 | { 2, 3 }, 469 | { 0, 2 }, 470 | { 1, 2 }, 471 | { 4, 4 }, 472 | { 13, 7 }, 473 | { 0, 2 }, 474 | { 1, 2 }, 475 | { 3, 4 }, 476 | { 2, 3 }, 477 | { 0, 2 }, 478 | { 1, 2 }, 479 | { 5, 4 }, 480 | { 8, 5 }, 481 | { 0, 2 }, 482 | { 1, 2 }, 483 | { 9, 6 }, 484 | { 2, 3 }, 485 | { 0, 2 }, 486 | { 1, 2 }, 487 | { 4, 4 }, 488 | { 7, 5 }, 489 | { 0, 2 }, 490 | { 1, 2 }, 491 | { 3, 4 }, 492 | { 2, 3 }, 493 | { 0, 2 }, 494 | { 1, 2 }, 495 | { 5, 4 }, 496 | { 21, 9 }, 497 | { 0, 2 }, 498 | { 1, 2 }, 499 | { 6, 5 }, 500 | { 2, 3 }, 501 | { 0, 2 }, 502 | { 1, 2 }, 503 | { 4, 4 }, 504 | { 10, 6 }, 505 | { 0, 2 }, 506 | { 1, 2 }, 507 | { 3, 4 }, 508 | { 2, 3 }, 509 | { 0, 2 }, 510 | { 1, 2 }, 511 | { 5, 4 }, 512 | { 8, 5 }, 513 | { 0, 2 }, 514 | { 1, 2 }, 515 | { 15, 8 }, 516 | { 2, 3 }, 517 | { 0, 2 }, 518 | { 1, 2 }, 519 | { 4, 4 }, 520 | { 7, 5 }, 521 | { 0, 2 }, 522 | { 1, 2 }, 523 | { 3, 4 }, 524 | { 2, 3 }, 525 | { 0, 2 }, 526 | { 1, 2 }, 527 | { 5, 4 }, 528 | { 11, 6 }, 529 | { 0, 2 }, 530 | { 1, 2 }, 531 | { 6, 5 }, 532 | { 2, 3 }, 533 | { 0, 2 }, 534 | { 1, 2 }, 535 | { 4, 4 }, 536 | { 24, 10 }, 537 | { 0, 2 }, 538 | { 1, 2 }, 539 | { 3, 4 }, 540 | { 2, 3 }, 541 | { 0, 2 }, 542 | { 1, 2 }, 543 | { 5, 4 }, 544 | { 8, 5 }, 545 | { 0, 2 }, 546 | { 1, 2 }, 547 | { 9, 6 }, 548 | { 2, 3 }, 549 | { 0, 2 }, 550 | { 1, 2 }, 551 | { 4, 4 }, 552 | { 7, 5 }, 553 | { 0, 2 }, 554 | { 1, 2 }, 555 | { 3, 4 }, 556 | { 2, 3 }, 557 | { 0, 2 }, 558 | { 1, 2 }, 559 | { 5, 4 }, 560 | { 17, 8 }, 561 | { 0, 2 }, 562 | { 1, 2 }, 563 | { 6, 5 }, 564 | { 2, 3 }, 565 | { 0, 2 }, 566 | { 1, 2 }, 567 | { 4, 4 }, 568 | { 10, 6 }, 569 | { 0, 2 }, 570 | { 1, 2 }, 571 | { 3, 4 }, 572 | { 2, 3 }, 573 | { 0, 2 }, 574 | { 1, 2 }, 575 | { 5, 4 }, 576 | { 8, 5 }, 577 | { 0, 2 }, 578 | { 1, 2 }, 579 | { 12, 7 }, 580 | { 2, 3 }, 581 | { 0, 2 }, 582 | { 1, 2 }, 583 | { 4, 4 }, 584 | { 7, 5 }, 585 | { 0, 2 }, 586 | { 1, 2 }, 587 | { 3, 4 }, 588 | { 2, 3 }, 589 | { 0, 2 }, 590 | { 1, 2 }, 591 | { 5, 4 }, 592 | { 11, 6 }, 593 | { 0, 2 }, 594 | { 1, 2 }, 595 | { 6, 5 }, 596 | { 2, 3 }, 597 | { 0, 2 }, 598 | { 1, 2 }, 599 | { 4, 4 }, 600 | { 13, 7 }, 601 | { 0, 2 }, 602 | { 1, 2 }, 603 | { 3, 4 }, 604 | { 2, 3 }, 605 | { 0, 2 }, 606 | { 1, 2 }, 607 | { 5, 4 }, 608 | { 8, 5 }, 609 | { 0, 2 }, 610 | { 1, 2 }, 611 | { 9, 6 }, 612 | { 2, 3 }, 613 | { 0, 2 }, 614 | { 1, 2 }, 615 | { 4, 4 }, 616 | { 7, 5 }, 617 | { 0, 2 }, 618 | { 1, 2 }, 619 | { 3, 4 }, 620 | { 2, 3 }, 621 | { 0, 2 }, 622 | { 1, 2 }, 623 | { 5, 4 }, 624 | { 16, 8 }, 625 | { 0, 2 }, 626 | { 1, 2 }, 627 | { 6, 5 }, 628 | { 2, 3 }, 629 | { 0, 2 }, 630 | { 1, 2 }, 631 | { 4, 4 }, 632 | { 10, 6 }, 633 | { 0, 2 }, 634 | { 1, 2 }, 635 | { 3, 4 }, 636 | { 2, 3 }, 637 | { 0, 2 }, 638 | { 1, 2 }, 639 | { 5, 4 }, 640 | { 8, 5 }, 641 | { 0, 2 }, 642 | { 1, 2 }, 643 | { 14, 8 }, 644 | { 2, 3 }, 645 | { 0, 2 }, 646 | { 1, 2 }, 647 | { 4, 4 }, 648 | { 7, 5 }, 649 | { 0, 2 }, 650 | { 1, 2 }, 651 | { 3, 4 }, 652 | { 2, 3 }, 653 | { 0, 2 }, 654 | { 1, 2 }, 655 | { 5, 4 }, 656 | { 11, 6 }, 657 | { 0, 2 }, 658 | { 1, 2 }, 659 | { 6, 5 }, 660 | { 2, 3 }, 661 | { 0, 2 }, 662 | { 1, 2 }, 663 | { 4, 4 }, 664 | { 18, 9 }, 665 | { 0, 2 }, 666 | { 1, 2 }, 667 | { 3, 4 }, 668 | { 2, 3 }, 669 | { 0, 2 }, 670 | { 1, 2 }, 671 | { 5, 4 }, 672 | { 8, 5 }, 673 | { 0, 2 }, 674 | { 1, 2 }, 675 | { 9, 6 }, 676 | { 2, 3 }, 677 | { 0, 2 }, 678 | { 1, 2 }, 679 | { 4, 4 }, 680 | { 7, 5 }, 681 | { 0, 2 }, 682 | { 1, 2 }, 683 | { 3, 4 }, 684 | { 2, 3 }, 685 | { 0, 2 }, 686 | { 1, 2 }, 687 | { 5, 4 }, 688 | { 31, 11 }, 689 | { 0, 2 }, 690 | { 1, 2 }, 691 | { 6, 5 }, 692 | { 2, 3 }, 693 | { 0, 2 }, 694 | { 1, 2 }, 695 | { 4, 4 }, 696 | { 10, 6 }, 697 | { 0, 2 }, 698 | { 1, 2 }, 699 | { 3, 4 }, 700 | { 2, 3 }, 701 | { 0, 2 }, 702 | { 1, 2 }, 703 | { 5, 4 }, 704 | { 8, 5 }, 705 | { 0, 2 }, 706 | { 1, 2 }, 707 | { 12, 7 }, 708 | { 2, 3 }, 709 | { 0, 2 }, 710 | { 1, 2 }, 711 | { 4, 4 }, 712 | { 7, 5 }, 713 | { 0, 2 }, 714 | { 1, 2 }, 715 | { 3, 4 }, 716 | { 2, 3 }, 717 | { 0, 2 }, 718 | { 1, 2 }, 719 | { 5, 4 }, 720 | { 11, 6 }, 721 | { 0, 2 }, 722 | { 1, 2 }, 723 | { 6, 5 }, 724 | { 2, 3 }, 725 | { 0, 2 }, 726 | { 1, 2 }, 727 | { 4, 4 }, 728 | { 13, 7 }, 729 | { 0, 2 }, 730 | { 1, 2 }, 731 | { 3, 4 }, 732 | { 2, 3 }, 733 | { 0, 2 }, 734 | { 1, 2 }, 735 | { 5, 4 }, 736 | { 8, 5 }, 737 | { 0, 2 }, 738 | { 1, 2 }, 739 | { 9, 6 }, 740 | { 2, 3 }, 741 | { 0, 2 }, 742 | { 1, 2 }, 743 | { 4, 4 }, 744 | { 7, 5 }, 745 | { 0, 2 }, 746 | { 1, 2 }, 747 | { 3, 4 }, 748 | { 2, 3 }, 749 | { 0, 2 }, 750 | { 1, 2 }, 751 | { 5, 4 }, 752 | { 20, 9 }, 753 | { 0, 2 }, 754 | { 1, 2 }, 755 | { 6, 5 }, 756 | { 2, 3 }, 757 | { 0, 2 }, 758 | { 1, 2 }, 759 | { 4, 4 }, 760 | { 10, 6 }, 761 | { 0, 2 }, 762 | { 1, 2 }, 763 | { 3, 4 }, 764 | { 2, 3 }, 765 | { 0, 2 }, 766 | { 1, 2 }, 767 | { 5, 4 }, 768 | { 8, 5 }, 769 | { 0, 2 }, 770 | { 1, 2 }, 771 | { 15, 8 }, 772 | { 2, 3 }, 773 | { 0, 2 }, 774 | { 1, 2 }, 775 | { 4, 4 }, 776 | { 7, 5 }, 777 | { 0, 2 }, 778 | { 1, 2 }, 779 | { 3, 4 }, 780 | { 2, 3 }, 781 | { 0, 2 }, 782 | { 1, 2 }, 783 | { 5, 4 }, 784 | { 11, 6 }, 785 | { 0, 2 }, 786 | { 1, 2 }, 787 | { 6, 5 }, 788 | { 2, 3 }, 789 | { 0, 2 }, 790 | { 1, 2 }, 791 | { 4, 4 }, 792 | { 19, 9 }, 793 | { 0, 2 }, 794 | { 1, 2 }, 795 | { 3, 4 }, 796 | { 2, 3 }, 797 | { 0, 2 }, 798 | { 1, 2 }, 799 | { 5, 4 }, 800 | { 8, 5 }, 801 | { 0, 2 }, 802 | { 1, 2 }, 803 | { 9, 6 }, 804 | { 2, 3 }, 805 | { 0, 2 }, 806 | { 1, 2 }, 807 | { 4, 4 }, 808 | { 7, 5 }, 809 | { 0, 2 }, 810 | { 1, 2 }, 811 | { 3, 4 }, 812 | { 2, 3 }, 813 | { 0, 2 }, 814 | { 1, 2 }, 815 | { 5, 4 }, 816 | { 17, 8 }, 817 | { 0, 2 }, 818 | { 1, 2 }, 819 | { 6, 5 }, 820 | { 2, 3 }, 821 | { 0, 2 }, 822 | { 1, 2 }, 823 | { 4, 4 }, 824 | { 10, 6 }, 825 | { 0, 2 }, 826 | { 1, 2 }, 827 | { 3, 4 }, 828 | { 2, 3 }, 829 | { 0, 2 }, 830 | { 1, 2 }, 831 | { 5, 4 }, 832 | { 8, 5 }, 833 | { 0, 2 }, 834 | { 1, 2 }, 835 | { 12, 7 }, 836 | { 2, 3 }, 837 | { 0, 2 }, 838 | { 1, 2 }, 839 | { 4, 4 }, 840 | { 7, 5 }, 841 | { 0, 2 }, 842 | { 1, 2 }, 843 | { 3, 4 }, 844 | { 2, 3 }, 845 | { 0, 2 }, 846 | { 1, 2 }, 847 | { 5, 4 }, 848 | { 11, 6 }, 849 | { 0, 2 }, 850 | { 1, 2 }, 851 | { 6, 5 }, 852 | { 2, 3 }, 853 | { 0, 2 }, 854 | { 1, 2 }, 855 | { 4, 4 }, 856 | { 13, 7 }, 857 | { 0, 2 }, 858 | { 1, 2 }, 859 | { 3, 4 }, 860 | { 2, 3 }, 861 | { 0, 2 }, 862 | { 1, 2 }, 863 | { 5, 4 }, 864 | { 8, 5 }, 865 | { 0, 2 }, 866 | { 1, 2 }, 867 | { 9, 6 }, 868 | { 2, 3 }, 869 | { 0, 2 }, 870 | { 1, 2 }, 871 | { 4, 4 }, 872 | { 7, 5 }, 873 | { 0, 2 }, 874 | { 1, 2 }, 875 | { 3, 4 }, 876 | { 2, 3 }, 877 | { 0, 2 }, 878 | { 1, 2 }, 879 | { 5, 4 }, 880 | { 16, 8 }, 881 | { 0, 2 }, 882 | { 1, 2 }, 883 | { 6, 5 }, 884 | { 2, 3 }, 885 | { 0, 2 }, 886 | { 1, 2 }, 887 | { 4, 4 }, 888 | { 10, 6 }, 889 | { 0, 2 }, 890 | { 1, 2 }, 891 | { 3, 4 }, 892 | { 2, 3 }, 893 | { 0, 2 }, 894 | { 1, 2 }, 895 | { 5, 4 }, 896 | { 8, 5 }, 897 | { 0, 2 }, 898 | { 1, 2 }, 899 | { 14, 8 }, 900 | { 2, 3 }, 901 | { 0, 2 }, 902 | { 1, 2 }, 903 | { 4, 4 }, 904 | { 7, 5 }, 905 | { 0, 2 }, 906 | { 1, 2 }, 907 | { 3, 4 }, 908 | { 2, 3 }, 909 | { 0, 2 }, 910 | { 1, 2 }, 911 | { 5, 4 }, 912 | { 11, 6 }, 913 | { 0, 2 }, 914 | { 1, 2 }, 915 | { 6, 5 }, 916 | { 2, 3 }, 917 | { 0, 2 }, 918 | { 1, 2 }, 919 | { 4, 4 }, 920 | { 23, 10 }, 921 | { 0, 2 }, 922 | { 1, 2 }, 923 | { 3, 4 }, 924 | { 2, 3 }, 925 | { 0, 2 }, 926 | { 1, 2 }, 927 | { 5, 4 }, 928 | { 8, 5 }, 929 | { 0, 2 }, 930 | { 1, 2 }, 931 | { 9, 6 }, 932 | { 2, 3 }, 933 | { 0, 2 }, 934 | { 1, 2 }, 935 | { 4, 4 }, 936 | { 7, 5 }, 937 | { 0, 2 }, 938 | { 1, 2 }, 939 | { 3, 4 }, 940 | { 2, 3 }, 941 | { 0, 2 }, 942 | { 1, 2 }, 943 | { 5, 4 }, 944 | { 26, 10 }, 945 | { 0, 2 }, 946 | { 1, 2 }, 947 | { 6, 5 }, 948 | { 2, 3 }, 949 | { 0, 2 }, 950 | { 1, 2 }, 951 | { 4, 4 }, 952 | { 10, 6 }, 953 | { 0, 2 }, 954 | { 1, 2 }, 955 | { 3, 4 }, 956 | { 2, 3 }, 957 | { 0, 2 }, 958 | { 1, 2 }, 959 | { 5, 4 }, 960 | { 8, 5 }, 961 | { 0, 2 }, 962 | { 1, 2 }, 963 | { 12, 7 }, 964 | { 2, 3 }, 965 | { 0, 2 }, 966 | { 1, 2 }, 967 | { 4, 4 }, 968 | { 7, 5 }, 969 | { 0, 2 }, 970 | { 1, 2 }, 971 | { 3, 4 }, 972 | { 2, 3 }, 973 | { 0, 2 }, 974 | { 1, 2 }, 975 | { 5, 4 }, 976 | { 11, 6 }, 977 | { 0, 2 }, 978 | { 1, 2 }, 979 | { 6, 5 }, 980 | { 2, 3 }, 981 | { 0, 2 }, 982 | { 1, 2 }, 983 | { 4, 4 }, 984 | { 13, 7 }, 985 | { 0, 2 }, 986 | { 1, 2 }, 987 | { 3, 4 }, 988 | { 2, 3 }, 989 | { 0, 2 }, 990 | { 1, 2 }, 991 | { 5, 4 }, 992 | { 8, 5 }, 993 | { 0, 2 }, 994 | { 1, 2 }, 995 | { 9, 6 }, 996 | { 2, 3 }, 997 | { 0, 2 }, 998 | { 1, 2 }, 999 | { 4, 4 }, 1000 | { 7, 5 }, 1001 | { 0, 2 }, 1002 | { 1, 2 }, 1003 | { 3, 4 }, 1004 | { 2, 3 }, 1005 | { 0, 2 }, 1006 | { 1, 2 }, 1007 | { 5, 4 }, 1008 | { 21, 9 }, 1009 | { 0, 2 }, 1010 | { 1, 2 }, 1011 | { 6, 5 }, 1012 | { 2, 3 }, 1013 | { 0, 2 }, 1014 | { 1, 2 }, 1015 | { 4, 4 }, 1016 | { 10, 6 }, 1017 | { 0, 2 }, 1018 | { 1, 2 }, 1019 | { 3, 4 }, 1020 | { 2, 3 }, 1021 | { 0, 2 }, 1022 | { 1, 2 }, 1023 | { 5, 4 }, 1024 | { 8, 5 }, 1025 | { 0, 2 }, 1026 | { 1, 2 }, 1027 | { 15, 8 }, 1028 | { 2, 3 }, 1029 | { 0, 2 }, 1030 | { 1, 2 }, 1031 | { 4, 4 }, 1032 | { 7, 5 }, 1033 | { 0, 2 }, 1034 | { 1, 2 }, 1035 | { 3, 4 }, 1036 | { 2, 3 }, 1037 | { 0, 2 }, 1038 | { 1, 2 }, 1039 | { 5, 4 }, 1040 | { 11, 6 }, 1041 | { 0, 2 }, 1042 | { 1, 2 }, 1043 | { 6, 5 }, 1044 | { 2, 3 }, 1045 | { 0, 2 }, 1046 | { 1, 2 }, 1047 | { 4, 4 }, 1048 | { 29, 11 }, 1049 | { 0, 2 }, 1050 | { 1, 2 }, 1051 | { 3, 4 }, 1052 | { 2, 3 }, 1053 | { 0, 2 }, 1054 | { 1, 2 }, 1055 | { 5, 4 }, 1056 | { 8, 5 }, 1057 | { 0, 2 }, 1058 | { 1, 2 }, 1059 | { 9, 6 }, 1060 | { 2, 3 }, 1061 | { 0, 2 }, 1062 | { 1, 2 }, 1063 | { 4, 4 }, 1064 | { 7, 5 }, 1065 | { 0, 2 }, 1066 | { 1, 2 }, 1067 | { 3, 4 }, 1068 | { 2, 3 }, 1069 | { 0, 2 }, 1070 | { 1, 2 }, 1071 | { 5, 4 }, 1072 | { 17, 8 }, 1073 | { 0, 2 }, 1074 | { 1, 2 }, 1075 | { 6, 5 }, 1076 | { 2, 3 }, 1077 | { 0, 2 }, 1078 | { 1, 2 }, 1079 | { 4, 4 }, 1080 | { 10, 6 }, 1081 | { 0, 2 }, 1082 | { 1, 2 }, 1083 | { 3, 4 }, 1084 | { 2, 3 }, 1085 | { 0, 2 }, 1086 | { 1, 2 }, 1087 | { 5, 4 }, 1088 | { 8, 5 }, 1089 | { 0, 2 }, 1090 | { 1, 2 }, 1091 | { 12, 7 }, 1092 | { 2, 3 }, 1093 | { 0, 2 }, 1094 | { 1, 2 }, 1095 | { 4, 4 }, 1096 | { 7, 5 }, 1097 | { 0, 2 }, 1098 | { 1, 2 }, 1099 | { 3, 4 }, 1100 | { 2, 3 }, 1101 | { 0, 2 }, 1102 | { 1, 2 }, 1103 | { 5, 4 }, 1104 | { 11, 6 }, 1105 | { 0, 2 }, 1106 | { 1, 2 }, 1107 | { 6, 5 }, 1108 | { 2, 3 }, 1109 | { 0, 2 }, 1110 | { 1, 2 }, 1111 | { 4, 4 }, 1112 | { 13, 7 }, 1113 | { 0, 2 }, 1114 | { 1, 2 }, 1115 | { 3, 4 }, 1116 | { 2, 3 }, 1117 | { 0, 2 }, 1118 | { 1, 2 }, 1119 | { 5, 4 }, 1120 | { 8, 5 }, 1121 | { 0, 2 }, 1122 | { 1, 2 }, 1123 | { 9, 6 }, 1124 | { 2, 3 }, 1125 | { 0, 2 }, 1126 | { 1, 2 }, 1127 | { 4, 4 }, 1128 | { 7, 5 }, 1129 | { 0, 2 }, 1130 | { 1, 2 }, 1131 | { 3, 4 }, 1132 | { 2, 3 }, 1133 | { 0, 2 }, 1134 | { 1, 2 }, 1135 | { 5, 4 }, 1136 | { 16, 8 }, 1137 | { 0, 2 }, 1138 | { 1, 2 }, 1139 | { 6, 5 }, 1140 | { 2, 3 }, 1141 | { 0, 2 }, 1142 | { 1, 2 }, 1143 | { 4, 4 }, 1144 | { 10, 6 }, 1145 | { 0, 2 }, 1146 | { 1, 2 }, 1147 | { 3, 4 }, 1148 | { 2, 3 }, 1149 | { 0, 2 }, 1150 | { 1, 2 }, 1151 | { 5, 4 }, 1152 | { 8, 5 }, 1153 | { 0, 2 }, 1154 | { 1, 2 }, 1155 | { 14, 8 }, 1156 | { 2, 3 }, 1157 | { 0, 2 }, 1158 | { 1, 2 }, 1159 | { 4, 4 }, 1160 | { 7, 5 }, 1161 | { 0, 2 }, 1162 | { 1, 2 }, 1163 | { 3, 4 }, 1164 | { 2, 3 }, 1165 | { 0, 2 }, 1166 | { 1, 2 }, 1167 | { 5, 4 }, 1168 | { 11, 6 }, 1169 | { 0, 2 }, 1170 | { 1, 2 }, 1171 | { 6, 5 }, 1172 | { 2, 3 }, 1173 | { 0, 2 }, 1174 | { 1, 2 }, 1175 | { 4, 4 }, 1176 | { 18, 9 }, 1177 | { 0, 2 }, 1178 | { 1, 2 }, 1179 | { 3, 4 }, 1180 | { 2, 3 }, 1181 | { 0, 2 }, 1182 | { 1, 2 }, 1183 | { 5, 4 }, 1184 | { 8, 5 }, 1185 | { 0, 2 }, 1186 | { 1, 2 }, 1187 | { 9, 6 }, 1188 | { 2, 3 }, 1189 | { 0, 2 }, 1190 | { 1, 2 }, 1191 | { 4, 4 }, 1192 | { 7, 5 }, 1193 | { 0, 2 }, 1194 | { 1, 2 }, 1195 | { 3, 4 }, 1196 | { 2, 3 }, 1197 | { 0, 2 }, 1198 | { 1, 2 }, 1199 | { 5, 4 }, 1200 | { 25, 10 }, 1201 | { 0, 2 }, 1202 | { 1, 2 }, 1203 | { 6, 5 }, 1204 | { 2, 3 }, 1205 | { 0, 2 }, 1206 | { 1, 2 }, 1207 | { 4, 4 }, 1208 | { 10, 6 }, 1209 | { 0, 2 }, 1210 | { 1, 2 }, 1211 | { 3, 4 }, 1212 | { 2, 3 }, 1213 | { 0, 2 }, 1214 | { 1, 2 }, 1215 | { 5, 4 }, 1216 | { 8, 5 }, 1217 | { 0, 2 }, 1218 | { 1, 2 }, 1219 | { 12, 7 }, 1220 | { 2, 3 }, 1221 | { 0, 2 }, 1222 | { 1, 2 }, 1223 | { 4, 4 }, 1224 | { 7, 5 }, 1225 | { 0, 2 }, 1226 | { 1, 2 }, 1227 | { 3, 4 }, 1228 | { 2, 3 }, 1229 | { 0, 2 }, 1230 | { 1, 2 }, 1231 | { 5, 4 }, 1232 | { 11, 6 }, 1233 | { 0, 2 }, 1234 | { 1, 2 }, 1235 | { 6, 5 }, 1236 | { 2, 3 }, 1237 | { 0, 2 }, 1238 | { 1, 2 }, 1239 | { 4, 4 }, 1240 | { 13, 7 }, 1241 | { 0, 2 }, 1242 | { 1, 2 }, 1243 | { 3, 4 }, 1244 | { 2, 3 }, 1245 | { 0, 2 }, 1246 | { 1, 2 }, 1247 | { 5, 4 }, 1248 | { 8, 5 }, 1249 | { 0, 2 }, 1250 | { 1, 2 }, 1251 | { 9, 6 }, 1252 | { 2, 3 }, 1253 | { 0, 2 }, 1254 | { 1, 2 }, 1255 | { 4, 4 }, 1256 | { 7, 5 }, 1257 | { 0, 2 }, 1258 | { 1, 2 }, 1259 | { 3, 4 }, 1260 | { 2, 3 }, 1261 | { 0, 2 }, 1262 | { 1, 2 }, 1263 | { 5, 4 }, 1264 | { 20, 9 }, 1265 | { 0, 2 }, 1266 | { 1, 2 }, 1267 | { 6, 5 }, 1268 | { 2, 3 }, 1269 | { 0, 2 }, 1270 | { 1, 2 }, 1271 | { 4, 4 }, 1272 | { 10, 6 }, 1273 | { 0, 2 }, 1274 | { 1, 2 }, 1275 | { 3, 4 }, 1276 | { 2, 3 }, 1277 | { 0, 2 }, 1278 | { 1, 2 }, 1279 | { 5, 4 }, 1280 | { 8, 5 }, 1281 | { 0, 2 }, 1282 | { 1, 2 }, 1283 | { 15, 8 }, 1284 | { 2, 3 }, 1285 | { 0, 2 }, 1286 | { 1, 2 }, 1287 | { 4, 4 }, 1288 | { 7, 5 }, 1289 | { 0, 2 }, 1290 | { 1, 2 }, 1291 | { 3, 4 }, 1292 | { 2, 3 }, 1293 | { 0, 2 }, 1294 | { 1, 2 }, 1295 | { 5, 4 }, 1296 | { 11, 6 }, 1297 | { 0, 2 }, 1298 | { 1, 2 }, 1299 | { 6, 5 }, 1300 | { 2, 3 }, 1301 | { 0, 2 }, 1302 | { 1, 2 }, 1303 | { 4, 4 }, 1304 | { 19, 9 }, 1305 | { 0, 2 }, 1306 | { 1, 2 }, 1307 | { 3, 4 }, 1308 | { 2, 3 }, 1309 | { 0, 2 }, 1310 | { 1, 2 }, 1311 | { 5, 4 }, 1312 | { 8, 5 }, 1313 | { 0, 2 }, 1314 | { 1, 2 }, 1315 | { 9, 6 }, 1316 | { 2, 3 }, 1317 | { 0, 2 }, 1318 | { 1, 2 }, 1319 | { 4, 4 }, 1320 | { 7, 5 }, 1321 | { 0, 2 }, 1322 | { 1, 2 }, 1323 | { 3, 4 }, 1324 | { 2, 3 }, 1325 | { 0, 2 }, 1326 | { 1, 2 }, 1327 | { 5, 4 }, 1328 | { 17, 8 }, 1329 | { 0, 2 }, 1330 | { 1, 2 }, 1331 | { 6, 5 }, 1332 | { 2, 3 }, 1333 | { 0, 2 }, 1334 | { 1, 2 }, 1335 | { 4, 4 }, 1336 | { 10, 6 }, 1337 | { 0, 2 }, 1338 | { 1, 2 }, 1339 | { 3, 4 }, 1340 | { 2, 3 }, 1341 | { 0, 2 }, 1342 | { 1, 2 }, 1343 | { 5, 4 }, 1344 | { 8, 5 }, 1345 | { 0, 2 }, 1346 | { 1, 2 }, 1347 | { 12, 7 }, 1348 | { 2, 3 }, 1349 | { 0, 2 }, 1350 | { 1, 2 }, 1351 | { 4, 4 }, 1352 | { 7, 5 }, 1353 | { 0, 2 }, 1354 | { 1, 2 }, 1355 | { 3, 4 }, 1356 | { 2, 3 }, 1357 | { 0, 2 }, 1358 | { 1, 2 }, 1359 | { 5, 4 }, 1360 | { 11, 6 }, 1361 | { 0, 2 }, 1362 | { 1, 2 }, 1363 | { 6, 5 }, 1364 | { 2, 3 }, 1365 | { 0, 2 }, 1366 | { 1, 2 }, 1367 | { 4, 4 }, 1368 | { 13, 7 }, 1369 | { 0, 2 }, 1370 | { 1, 2 }, 1371 | { 3, 4 }, 1372 | { 2, 3 }, 1373 | { 0, 2 }, 1374 | { 1, 2 }, 1375 | { 5, 4 }, 1376 | { 8, 5 }, 1377 | { 0, 2 }, 1378 | { 1, 2 }, 1379 | { 9, 6 }, 1380 | { 2, 3 }, 1381 | { 0, 2 }, 1382 | { 1, 2 }, 1383 | { 4, 4 }, 1384 | { 7, 5 }, 1385 | { 0, 2 }, 1386 | { 1, 2 }, 1387 | { 3, 4 }, 1388 | { 2, 3 }, 1389 | { 0, 2 }, 1390 | { 1, 2 }, 1391 | { 5, 4 }, 1392 | { 16, 8 }, 1393 | { 0, 2 }, 1394 | { 1, 2 }, 1395 | { 6, 5 }, 1396 | { 2, 3 }, 1397 | { 0, 2 }, 1398 | { 1, 2 }, 1399 | { 4, 4 }, 1400 | { 10, 6 }, 1401 | { 0, 2 }, 1402 | { 1, 2 }, 1403 | { 3, 4 }, 1404 | { 2, 3 }, 1405 | { 0, 2 }, 1406 | { 1, 2 }, 1407 | { 5, 4 }, 1408 | { 8, 5 }, 1409 | { 0, 2 }, 1410 | { 1, 2 }, 1411 | { 14, 8 }, 1412 | { 2, 3 }, 1413 | { 0, 2 }, 1414 | { 1, 2 }, 1415 | { 4, 4 }, 1416 | { 7, 5 }, 1417 | { 0, 2 }, 1418 | { 1, 2 }, 1419 | { 3, 4 }, 1420 | { 2, 3 }, 1421 | { 0, 2 }, 1422 | { 1, 2 }, 1423 | { 5, 4 }, 1424 | { 11, 6 }, 1425 | { 0, 2 }, 1426 | { 1, 2 }, 1427 | { 6, 5 }, 1428 | { 2, 3 }, 1429 | { 0, 2 }, 1430 | { 1, 2 }, 1431 | { 4, 4 }, 1432 | { 22, 10 }, 1433 | { 0, 2 }, 1434 | { 1, 2 }, 1435 | { 3, 4 }, 1436 | { 2, 3 }, 1437 | { 0, 2 }, 1438 | { 1, 2 }, 1439 | { 5, 4 }, 1440 | { 8, 5 }, 1441 | { 0, 2 }, 1442 | { 1, 2 }, 1443 | { 9, 6 }, 1444 | { 2, 3 }, 1445 | { 0, 2 }, 1446 | { 1, 2 }, 1447 | { 4, 4 }, 1448 | { 7, 5 }, 1449 | { 0, 2 }, 1450 | { 1, 2 }, 1451 | { 3, 4 }, 1452 | { 2, 3 }, 1453 | { 0, 2 }, 1454 | { 1, 2 }, 1455 | { 5, 4 }, 1456 | { 27, 10 }, 1457 | { 0, 2 }, 1458 | { 1, 2 }, 1459 | { 6, 5 }, 1460 | { 2, 3 }, 1461 | { 0, 2 }, 1462 | { 1, 2 }, 1463 | { 4, 4 }, 1464 | { 10, 6 }, 1465 | { 0, 2 }, 1466 | { 1, 2 }, 1467 | { 3, 4 }, 1468 | { 2, 3 }, 1469 | { 0, 2 }, 1470 | { 1, 2 }, 1471 | { 5, 4 }, 1472 | { 8, 5 }, 1473 | { 0, 2 }, 1474 | { 1, 2 }, 1475 | { 12, 7 }, 1476 | { 2, 3 }, 1477 | { 0, 2 }, 1478 | { 1, 2 }, 1479 | { 4, 4 }, 1480 | { 7, 5 }, 1481 | { 0, 2 }, 1482 | { 1, 2 }, 1483 | { 3, 4 }, 1484 | { 2, 3 }, 1485 | { 0, 2 }, 1486 | { 1, 2 }, 1487 | { 5, 4 }, 1488 | { 11, 6 }, 1489 | { 0, 2 }, 1490 | { 1, 2 }, 1491 | { 6, 5 }, 1492 | { 2, 3 }, 1493 | { 0, 2 }, 1494 | { 1, 2 }, 1495 | { 4, 4 }, 1496 | { 13, 7 }, 1497 | { 0, 2 }, 1498 | { 1, 2 }, 1499 | { 3, 4 }, 1500 | { 2, 3 }, 1501 | { 0, 2 }, 1502 | { 1, 2 }, 1503 | { 5, 4 }, 1504 | { 8, 5 }, 1505 | { 0, 2 }, 1506 | { 1, 2 }, 1507 | { 9, 6 }, 1508 | { 2, 3 }, 1509 | { 0, 2 }, 1510 | { 1, 2 }, 1511 | { 4, 4 }, 1512 | { 7, 5 }, 1513 | { 0, 2 }, 1514 | { 1, 2 }, 1515 | { 3, 4 }, 1516 | { 2, 3 }, 1517 | { 0, 2 }, 1518 | { 1, 2 }, 1519 | { 5, 4 }, 1520 | { 21, 9 }, 1521 | { 0, 2 }, 1522 | { 1, 2 }, 1523 | { 6, 5 }, 1524 | { 2, 3 }, 1525 | { 0, 2 }, 1526 | { 1, 2 }, 1527 | { 4, 4 }, 1528 | { 10, 6 }, 1529 | { 0, 2 }, 1530 | { 1, 2 }, 1531 | { 3, 4 }, 1532 | { 2, 3 }, 1533 | { 0, 2 }, 1534 | { 1, 2 }, 1535 | { 5, 4 }, 1536 | { 8, 5 }, 1537 | { 0, 2 }, 1538 | { 1, 2 }, 1539 | { 15, 8 }, 1540 | { 2, 3 }, 1541 | { 0, 2 }, 1542 | { 1, 2 }, 1543 | { 4, 4 }, 1544 | { 7, 5 }, 1545 | { 0, 2 }, 1546 | { 1, 2 }, 1547 | { 3, 4 }, 1548 | { 2, 3 }, 1549 | { 0, 2 }, 1550 | { 1, 2 }, 1551 | { 5, 4 }, 1552 | { 11, 6 }, 1553 | { 0, 2 }, 1554 | { 1, 2 }, 1555 | { 6, 5 }, 1556 | { 2, 3 }, 1557 | { 0, 2 }, 1558 | { 1, 2 }, 1559 | { 4, 4 }, 1560 | { 24, 10 }, 1561 | { 0, 2 }, 1562 | { 1, 2 }, 1563 | { 3, 4 }, 1564 | { 2, 3 }, 1565 | { 0, 2 }, 1566 | { 1, 2 }, 1567 | { 5, 4 }, 1568 | { 8, 5 }, 1569 | { 0, 2 }, 1570 | { 1, 2 }, 1571 | { 9, 6 }, 1572 | { 2, 3 }, 1573 | { 0, 2 }, 1574 | { 1, 2 }, 1575 | { 4, 4 }, 1576 | { 7, 5 }, 1577 | { 0, 2 }, 1578 | { 1, 2 }, 1579 | { 3, 4 }, 1580 | { 2, 3 }, 1581 | { 0, 2 }, 1582 | { 1, 2 }, 1583 | { 5, 4 }, 1584 | { 17, 8 }, 1585 | { 0, 2 }, 1586 | { 1, 2 }, 1587 | { 6, 5 }, 1588 | { 2, 3 }, 1589 | { 0, 2 }, 1590 | { 1, 2 }, 1591 | { 4, 4 }, 1592 | { 10, 6 }, 1593 | { 0, 2 }, 1594 | { 1, 2 }, 1595 | { 3, 4 }, 1596 | { 2, 3 }, 1597 | { 0, 2 }, 1598 | { 1, 2 }, 1599 | { 5, 4 }, 1600 | { 8, 5 }, 1601 | { 0, 2 }, 1602 | { 1, 2 }, 1603 | { 12, 7 }, 1604 | { 2, 3 }, 1605 | { 0, 2 }, 1606 | { 1, 2 }, 1607 | { 4, 4 }, 1608 | { 7, 5 }, 1609 | { 0, 2 }, 1610 | { 1, 2 }, 1611 | { 3, 4 }, 1612 | { 2, 3 }, 1613 | { 0, 2 }, 1614 | { 1, 2 }, 1615 | { 5, 4 }, 1616 | { 11, 6 }, 1617 | { 0, 2 }, 1618 | { 1, 2 }, 1619 | { 6, 5 }, 1620 | { 2, 3 }, 1621 | { 0, 2 }, 1622 | { 1, 2 }, 1623 | { 4, 4 }, 1624 | { 13, 7 }, 1625 | { 0, 2 }, 1626 | { 1, 2 }, 1627 | { 3, 4 }, 1628 | { 2, 3 }, 1629 | { 0, 2 }, 1630 | { 1, 2 }, 1631 | { 5, 4 }, 1632 | { 8, 5 }, 1633 | { 0, 2 }, 1634 | { 1, 2 }, 1635 | { 9, 6 }, 1636 | { 2, 3 }, 1637 | { 0, 2 }, 1638 | { 1, 2 }, 1639 | { 4, 4 }, 1640 | { 7, 5 }, 1641 | { 0, 2 }, 1642 | { 1, 2 }, 1643 | { 3, 4 }, 1644 | { 2, 3 }, 1645 | { 0, 2 }, 1646 | { 1, 2 }, 1647 | { 5, 4 }, 1648 | { 16, 8 }, 1649 | { 0, 2 }, 1650 | { 1, 2 }, 1651 | { 6, 5 }, 1652 | { 2, 3 }, 1653 | { 0, 2 }, 1654 | { 1, 2 }, 1655 | { 4, 4 }, 1656 | { 10, 6 }, 1657 | { 0, 2 }, 1658 | { 1, 2 }, 1659 | { 3, 4 }, 1660 | { 2, 3 }, 1661 | { 0, 2 }, 1662 | { 1, 2 }, 1663 | { 5, 4 }, 1664 | { 8, 5 }, 1665 | { 0, 2 }, 1666 | { 1, 2 }, 1667 | { 14, 8 }, 1668 | { 2, 3 }, 1669 | { 0, 2 }, 1670 | { 1, 2 }, 1671 | { 4, 4 }, 1672 | { 7, 5 }, 1673 | { 0, 2 }, 1674 | { 1, 2 }, 1675 | { 3, 4 }, 1676 | { 2, 3 }, 1677 | { 0, 2 }, 1678 | { 1, 2 }, 1679 | { 5, 4 }, 1680 | { 11, 6 }, 1681 | { 0, 2 }, 1682 | { 1, 2 }, 1683 | { 6, 5 }, 1684 | { 2, 3 }, 1685 | { 0, 2 }, 1686 | { 1, 2 }, 1687 | { 4, 4 }, 1688 | { 18, 9 }, 1689 | { 0, 2 }, 1690 | { 1, 2 }, 1691 | { 3, 4 }, 1692 | { 2, 3 }, 1693 | { 0, 2 }, 1694 | { 1, 2 }, 1695 | { 5, 4 }, 1696 | { 8, 5 }, 1697 | { 0, 2 }, 1698 | { 1, 2 }, 1699 | { 9, 6 }, 1700 | { 2, 3 }, 1701 | { 0, 2 }, 1702 | { 1, 2 }, 1703 | { 4, 4 }, 1704 | { 7, 5 }, 1705 | { 0, 2 }, 1706 | { 1, 2 }, 1707 | { 3, 4 }, 1708 | { 2, 3 }, 1709 | { 0, 2 }, 1710 | { 1, 2 }, 1711 | { 5, 4 }, 1712 | { 30, 11 }, 1713 | { 0, 2 }, 1714 | { 1, 2 }, 1715 | { 6, 5 }, 1716 | { 2, 3 }, 1717 | { 0, 2 }, 1718 | { 1, 2 }, 1719 | { 4, 4 }, 1720 | { 10, 6 }, 1721 | { 0, 2 }, 1722 | { 1, 2 }, 1723 | { 3, 4 }, 1724 | { 2, 3 }, 1725 | { 0, 2 }, 1726 | { 1, 2 }, 1727 | { 5, 4 }, 1728 | { 8, 5 }, 1729 | { 0, 2 }, 1730 | { 1, 2 }, 1731 | { 12, 7 }, 1732 | { 2, 3 }, 1733 | { 0, 2 }, 1734 | { 1, 2 }, 1735 | { 4, 4 }, 1736 | { 7, 5 }, 1737 | { 0, 2 }, 1738 | { 1, 2 }, 1739 | { 3, 4 }, 1740 | { 2, 3 }, 1741 | { 0, 2 }, 1742 | { 1, 2 }, 1743 | { 5, 4 }, 1744 | { 11, 6 }, 1745 | { 0, 2 }, 1746 | { 1, 2 }, 1747 | { 6, 5 }, 1748 | { 2, 3 }, 1749 | { 0, 2 }, 1750 | { 1, 2 }, 1751 | { 4, 4 }, 1752 | { 13, 7 }, 1753 | { 0, 2 }, 1754 | { 1, 2 }, 1755 | { 3, 4 }, 1756 | { 2, 3 }, 1757 | { 0, 2 }, 1758 | { 1, 2 }, 1759 | { 5, 4 }, 1760 | { 8, 5 }, 1761 | { 0, 2 }, 1762 | { 1, 2 }, 1763 | { 9, 6 }, 1764 | { 2, 3 }, 1765 | { 0, 2 }, 1766 | { 1, 2 }, 1767 | { 4, 4 }, 1768 | { 7, 5 }, 1769 | { 0, 2 }, 1770 | { 1, 2 }, 1771 | { 3, 4 }, 1772 | { 2, 3 }, 1773 | { 0, 2 }, 1774 | { 1, 2 }, 1775 | { 5, 4 }, 1776 | { 20, 9 }, 1777 | { 0, 2 }, 1778 | { 1, 2 }, 1779 | { 6, 5 }, 1780 | { 2, 3 }, 1781 | { 0, 2 }, 1782 | { 1, 2 }, 1783 | { 4, 4 }, 1784 | { 10, 6 }, 1785 | { 0, 2 }, 1786 | { 1, 2 }, 1787 | { 3, 4 }, 1788 | { 2, 3 }, 1789 | { 0, 2 }, 1790 | { 1, 2 }, 1791 | { 5, 4 }, 1792 | { 8, 5 }, 1793 | { 0, 2 }, 1794 | { 1, 2 }, 1795 | { 15, 8 }, 1796 | { 2, 3 }, 1797 | { 0, 2 }, 1798 | { 1, 2 }, 1799 | { 4, 4 }, 1800 | { 7, 5 }, 1801 | { 0, 2 }, 1802 | { 1, 2 }, 1803 | { 3, 4 }, 1804 | { 2, 3 }, 1805 | { 0, 2 }, 1806 | { 1, 2 }, 1807 | { 5, 4 }, 1808 | { 11, 6 }, 1809 | { 0, 2 }, 1810 | { 1, 2 }, 1811 | { 6, 5 }, 1812 | { 2, 3 }, 1813 | { 0, 2 }, 1814 | { 1, 2 }, 1815 | { 4, 4 }, 1816 | { 19, 9 }, 1817 | { 0, 2 }, 1818 | { 1, 2 }, 1819 | { 3, 4 }, 1820 | { 2, 3 }, 1821 | { 0, 2 }, 1822 | { 1, 2 }, 1823 | { 5, 4 }, 1824 | { 8, 5 }, 1825 | { 0, 2 }, 1826 | { 1, 2 }, 1827 | { 9, 6 }, 1828 | { 2, 3 }, 1829 | { 0, 2 }, 1830 | { 1, 2 }, 1831 | { 4, 4 }, 1832 | { 7, 5 }, 1833 | { 0, 2 }, 1834 | { 1, 2 }, 1835 | { 3, 4 }, 1836 | { 2, 3 }, 1837 | { 0, 2 }, 1838 | { 1, 2 }, 1839 | { 5, 4 }, 1840 | { 17, 8 }, 1841 | { 0, 2 }, 1842 | { 1, 2 }, 1843 | { 6, 5 }, 1844 | { 2, 3 }, 1845 | { 0, 2 }, 1846 | { 1, 2 }, 1847 | { 4, 4 }, 1848 | { 10, 6 }, 1849 | { 0, 2 }, 1850 | { 1, 2 }, 1851 | { 3, 4 }, 1852 | { 2, 3 }, 1853 | { 0, 2 }, 1854 | { 1, 2 }, 1855 | { 5, 4 }, 1856 | { 8, 5 }, 1857 | { 0, 2 }, 1858 | { 1, 2 }, 1859 | { 12, 7 }, 1860 | { 2, 3 }, 1861 | { 0, 2 }, 1862 | { 1, 2 }, 1863 | { 4, 4 }, 1864 | { 7, 5 }, 1865 | { 0, 2 }, 1866 | { 1, 2 }, 1867 | { 3, 4 }, 1868 | { 2, 3 }, 1869 | { 0, 2 }, 1870 | { 1, 2 }, 1871 | { 5, 4 }, 1872 | { 11, 6 }, 1873 | { 0, 2 }, 1874 | { 1, 2 }, 1875 | { 6, 5 }, 1876 | { 2, 3 }, 1877 | { 0, 2 }, 1878 | { 1, 2 }, 1879 | { 4, 4 }, 1880 | { 13, 7 }, 1881 | { 0, 2 }, 1882 | { 1, 2 }, 1883 | { 3, 4 }, 1884 | { 2, 3 }, 1885 | { 0, 2 }, 1886 | { 1, 2 }, 1887 | { 5, 4 }, 1888 | { 8, 5 }, 1889 | { 0, 2 }, 1890 | { 1, 2 }, 1891 | { 9, 6 }, 1892 | { 2, 3 }, 1893 | { 0, 2 }, 1894 | { 1, 2 }, 1895 | { 4, 4 }, 1896 | { 7, 5 }, 1897 | { 0, 2 }, 1898 | { 1, 2 }, 1899 | { 3, 4 }, 1900 | { 2, 3 }, 1901 | { 0, 2 }, 1902 | { 1, 2 }, 1903 | { 5, 4 }, 1904 | { 16, 8 }, 1905 | { 0, 2 }, 1906 | { 1, 2 }, 1907 | { 6, 5 }, 1908 | { 2, 3 }, 1909 | { 0, 2 }, 1910 | { 1, 2 }, 1911 | { 4, 4 }, 1912 | { 10, 6 }, 1913 | { 0, 2 }, 1914 | { 1, 2 }, 1915 | { 3, 4 }, 1916 | { 2, 3 }, 1917 | { 0, 2 }, 1918 | { 1, 2 }, 1919 | { 5, 4 }, 1920 | { 8, 5 }, 1921 | { 0, 2 }, 1922 | { 1, 2 }, 1923 | { 14, 8 }, 1924 | { 2, 3 }, 1925 | { 0, 2 }, 1926 | { 1, 2 }, 1927 | { 4, 4 }, 1928 | { 7, 5 }, 1929 | { 0, 2 }, 1930 | { 1, 2 }, 1931 | { 3, 4 }, 1932 | { 2, 3 }, 1933 | { 0, 2 }, 1934 | { 1, 2 }, 1935 | { 5, 4 }, 1936 | { 11, 6 }, 1937 | { 0, 2 }, 1938 | { 1, 2 }, 1939 | { 6, 5 }, 1940 | { 2, 3 }, 1941 | { 0, 2 }, 1942 | { 1, 2 }, 1943 | { 4, 4 }, 1944 | { 23, 10 }, 1945 | { 0, 2 }, 1946 | { 1, 2 }, 1947 | { 3, 4 }, 1948 | { 2, 3 }, 1949 | { 0, 2 }, 1950 | { 1, 2 }, 1951 | { 5, 4 }, 1952 | { 8, 5 }, 1953 | { 0, 2 }, 1954 | { 1, 2 }, 1955 | { 9, 6 }, 1956 | { 2, 3 }, 1957 | { 0, 2 }, 1958 | { 1, 2 }, 1959 | { 4, 4 }, 1960 | { 7, 5 }, 1961 | { 0, 2 }, 1962 | { 1, 2 }, 1963 | { 3, 4 }, 1964 | { 2, 3 }, 1965 | { 0, 2 }, 1966 | { 1, 2 }, 1967 | { 5, 4 }, 1968 | { 26, 10 }, 1969 | { 0, 2 }, 1970 | { 1, 2 }, 1971 | { 6, 5 }, 1972 | { 2, 3 }, 1973 | { 0, 2 }, 1974 | { 1, 2 }, 1975 | { 4, 4 }, 1976 | { 10, 6 }, 1977 | { 0, 2 }, 1978 | { 1, 2 }, 1979 | { 3, 4 }, 1980 | { 2, 3 }, 1981 | { 0, 2 }, 1982 | { 1, 2 }, 1983 | { 5, 4 }, 1984 | { 8, 5 }, 1985 | { 0, 2 }, 1986 | { 1, 2 }, 1987 | { 12, 7 }, 1988 | { 2, 3 }, 1989 | { 0, 2 }, 1990 | { 1, 2 }, 1991 | { 4, 4 }, 1992 | { 7, 5 }, 1993 | { 0, 2 }, 1994 | { 1, 2 }, 1995 | { 3, 4 }, 1996 | { 2, 3 }, 1997 | { 0, 2 }, 1998 | { 1, 2 }, 1999 | { 5, 4 }, 2000 | { 11, 6 }, 2001 | { 0, 2 }, 2002 | { 1, 2 }, 2003 | { 6, 5 }, 2004 | { 2, 3 }, 2005 | { 0, 2 }, 2006 | { 1, 2 }, 2007 | { 4, 4 }, 2008 | { 13, 7 }, 2009 | { 0, 2 }, 2010 | { 1, 2 }, 2011 | { 3, 4 }, 2012 | { 2, 3 }, 2013 | { 0, 2 }, 2014 | { 1, 2 }, 2015 | { 5, 4 }, 2016 | { 8, 5 }, 2017 | { 0, 2 }, 2018 | { 1, 2 }, 2019 | { 9, 6 }, 2020 | { 2, 3 }, 2021 | { 0, 2 }, 2022 | { 1, 2 }, 2023 | { 4, 4 }, 2024 | { 7, 5 }, 2025 | { 0, 2 }, 2026 | { 1, 2 }, 2027 | { 3, 4 }, 2028 | { 2, 3 }, 2029 | { 0, 2 }, 2030 | { 1, 2 }, 2031 | { 5, 4 }, 2032 | { 21, 9 }, 2033 | { 0, 2 }, 2034 | { 1, 2 }, 2035 | { 6, 5 }, 2036 | { 2, 3 }, 2037 | { 0, 2 }, 2038 | { 1, 2 }, 2039 | { 4, 4 }, 2040 | { 10, 6 }, 2041 | { 0, 2 }, 2042 | { 1, 2 }, 2043 | { 3, 4 }, 2044 | { 2, 3 }, 2045 | { 0, 2 }, 2046 | { 1, 2 }, 2047 | { 5, 4 }, 2048 | { 8, 5 }, 2049 | { 0, 2 }, 2050 | { 1, 2 }, 2051 | { 15, 8 }, 2052 | { 2, 3 }, 2053 | { 0, 2 }, 2054 | { 1, 2 }, 2055 | { 4, 4 }, 2056 | { 7, 5 }, 2057 | { 0, 2 }, 2058 | { 1, 2 }, 2059 | { 3, 4 }, 2060 | { 2, 3 }, 2061 | { 0, 2 }, 2062 | { 1, 2 }, 2063 | { 5, 4 }, 2064 | { 11, 6 }, 2065 | { 0, 2 }, 2066 | { 1, 2 }, 2067 | { 6, 5 }, 2068 | { 2, 3 }, 2069 | { 0, 2 }, 2070 | { 1, 2 }, 2071 | { 4, 4 }, 2072 | { 28, 11 }, 2073 | { 0, 2 }, 2074 | { 1, 2 }, 2075 | { 3, 4 }, 2076 | { 2, 3 }, 2077 | { 0, 2 }, 2078 | { 1, 2 }, 2079 | { 5, 4 }, 2080 | { 8, 5 }, 2081 | { 0, 2 }, 2082 | { 1, 2 }, 2083 | { 9, 6 }, 2084 | { 2, 3 }, 2085 | { 0, 2 }, 2086 | { 1, 2 }, 2087 | { 4, 4 }, 2088 | { 7, 5 }, 2089 | { 0, 2 }, 2090 | { 1, 2 }, 2091 | { 3, 4 }, 2092 | { 2, 3 }, 2093 | { 0, 2 }, 2094 | { 1, 2 }, 2095 | { 5, 4 }, 2096 | { 17, 8 }, 2097 | { 0, 2 }, 2098 | { 1, 2 }, 2099 | { 6, 5 }, 2100 | { 2, 3 }, 2101 | { 0, 2 }, 2102 | { 1, 2 }, 2103 | { 4, 4 }, 2104 | { 10, 6 }, 2105 | { 0, 2 }, 2106 | { 1, 2 }, 2107 | { 3, 4 }, 2108 | { 2, 3 }, 2109 | { 0, 2 }, 2110 | { 1, 2 }, 2111 | { 5, 4 }, 2112 | { 8, 5 }, 2113 | { 0, 2 }, 2114 | { 1, 2 }, 2115 | { 12, 7 }, 2116 | { 2, 3 }, 2117 | { 0, 2 }, 2118 | { 1, 2 }, 2119 | { 4, 4 }, 2120 | { 7, 5 }, 2121 | { 0, 2 }, 2122 | { 1, 2 }, 2123 | { 3, 4 }, 2124 | { 2, 3 }, 2125 | { 0, 2 }, 2126 | { 1, 2 }, 2127 | { 5, 4 }, 2128 | { 11, 6 }, 2129 | { 0, 2 }, 2130 | { 1, 2 }, 2131 | { 6, 5 }, 2132 | { 2, 3 }, 2133 | { 0, 2 }, 2134 | { 1, 2 }, 2135 | { 4, 4 }, 2136 | { 13, 7 }, 2137 | { 0, 2 }, 2138 | { 1, 2 }, 2139 | { 3, 4 }, 2140 | { 2, 3 }, 2141 | { 0, 2 }, 2142 | { 1, 2 }, 2143 | { 5, 4 }, 2144 | { 8, 5 }, 2145 | { 0, 2 }, 2146 | { 1, 2 }, 2147 | { 9, 6 }, 2148 | { 2, 3 }, 2149 | { 0, 2 }, 2150 | { 1, 2 }, 2151 | { 4, 4 }, 2152 | { 7, 5 }, 2153 | { 0, 2 }, 2154 | { 1, 2 }, 2155 | { 3, 4 }, 2156 | { 2, 3 }, 2157 | { 0, 2 }, 2158 | { 1, 2 }, 2159 | { 5, 4 }, 2160 | { 16, 8 }, 2161 | { 0, 2 }, 2162 | { 1, 2 }, 2163 | { 6, 5 }, 2164 | { 2, 3 }, 2165 | { 0, 2 }, 2166 | { 1, 2 }, 2167 | { 4, 4 }, 2168 | { 10, 6 }, 2169 | { 0, 2 }, 2170 | { 1, 2 }, 2171 | { 3, 4 }, 2172 | { 2, 3 }, 2173 | { 0, 2 }, 2174 | { 1, 2 }, 2175 | { 5, 4 }, 2176 | { 8, 5 }, 2177 | { 0, 2 }, 2178 | { 1, 2 }, 2179 | { 14, 8 }, 2180 | { 2, 3 }, 2181 | { 0, 2 }, 2182 | { 1, 2 }, 2183 | { 4, 4 }, 2184 | { 7, 5 }, 2185 | { 0, 2 }, 2186 | { 1, 2 }, 2187 | { 3, 4 }, 2188 | { 2, 3 }, 2189 | { 0, 2 }, 2190 | { 1, 2 }, 2191 | { 5, 4 }, 2192 | { 11, 6 }, 2193 | { 0, 2 }, 2194 | { 1, 2 }, 2195 | { 6, 5 }, 2196 | { 2, 3 }, 2197 | { 0, 2 }, 2198 | { 1, 2 }, 2199 | { 4, 4 }, 2200 | { 18, 9 }, 2201 | { 0, 2 }, 2202 | { 1, 2 }, 2203 | { 3, 4 }, 2204 | { 2, 3 }, 2205 | { 0, 2 }, 2206 | { 1, 2 }, 2207 | { 5, 4 }, 2208 | { 8, 5 }, 2209 | { 0, 2 }, 2210 | { 1, 2 }, 2211 | { 9, 6 }, 2212 | { 2, 3 }, 2213 | { 0, 2 }, 2214 | { 1, 2 }, 2215 | { 4, 4 }, 2216 | { 7, 5 }, 2217 | { 0, 2 }, 2218 | { 1, 2 }, 2219 | { 3, 4 }, 2220 | { 2, 3 }, 2221 | { 0, 2 }, 2222 | { 1, 2 }, 2223 | { 5, 4 }, 2224 | { 25, 10 }, 2225 | { 0, 2 }, 2226 | { 1, 2 }, 2227 | { 6, 5 }, 2228 | { 2, 3 }, 2229 | { 0, 2 }, 2230 | { 1, 2 }, 2231 | { 4, 4 }, 2232 | { 10, 6 }, 2233 | { 0, 2 }, 2234 | { 1, 2 }, 2235 | { 3, 4 }, 2236 | { 2, 3 }, 2237 | { 0, 2 }, 2238 | { 1, 2 }, 2239 | { 5, 4 }, 2240 | { 8, 5 }, 2241 | { 0, 2 }, 2242 | { 1, 2 }, 2243 | { 12, 7 }, 2244 | { 2, 3 }, 2245 | { 0, 2 }, 2246 | { 1, 2 }, 2247 | { 4, 4 }, 2248 | { 7, 5 }, 2249 | { 0, 2 }, 2250 | { 1, 2 }, 2251 | { 3, 4 }, 2252 | { 2, 3 }, 2253 | { 0, 2 }, 2254 | { 1, 2 }, 2255 | { 5, 4 }, 2256 | { 11, 6 }, 2257 | { 0, 2 }, 2258 | { 1, 2 }, 2259 | { 6, 5 }, 2260 | { 2, 3 }, 2261 | { 0, 2 }, 2262 | { 1, 2 }, 2263 | { 4, 4 }, 2264 | { 13, 7 }, 2265 | { 0, 2 }, 2266 | { 1, 2 }, 2267 | { 3, 4 }, 2268 | { 2, 3 }, 2269 | { 0, 2 }, 2270 | { 1, 2 }, 2271 | { 5, 4 }, 2272 | { 8, 5 }, 2273 | { 0, 2 }, 2274 | { 1, 2 }, 2275 | { 9, 6 }, 2276 | { 2, 3 }, 2277 | { 0, 2 }, 2278 | { 1, 2 }, 2279 | { 4, 4 }, 2280 | { 7, 5 }, 2281 | { 0, 2 }, 2282 | { 1, 2 }, 2283 | { 3, 4 }, 2284 | { 2, 3 }, 2285 | { 0, 2 }, 2286 | { 1, 2 }, 2287 | { 5, 4 }, 2288 | { 20, 9 }, 2289 | { 0, 2 }, 2290 | { 1, 2 }, 2291 | { 6, 5 }, 2292 | { 2, 3 }, 2293 | { 0, 2 }, 2294 | { 1, 2 }, 2295 | { 4, 4 }, 2296 | { 10, 6 }, 2297 | { 0, 2 }, 2298 | { 1, 2 }, 2299 | { 3, 4 }, 2300 | { 2, 3 }, 2301 | { 0, 2 }, 2302 | { 1, 2 }, 2303 | { 5, 4 }, 2304 | { 8, 5 }, 2305 | { 0, 2 }, 2306 | { 1, 2 }, 2307 | { 15, 8 }, 2308 | { 2, 3 }, 2309 | { 0, 2 }, 2310 | { 1, 2 }, 2311 | { 4, 4 }, 2312 | { 7, 5 }, 2313 | { 0, 2 }, 2314 | { 1, 2 }, 2315 | { 3, 4 }, 2316 | { 2, 3 }, 2317 | { 0, 2 }, 2318 | { 1, 2 }, 2319 | { 5, 4 }, 2320 | { 11, 6 }, 2321 | { 0, 2 }, 2322 | { 1, 2 }, 2323 | { 6, 5 }, 2324 | { 2, 3 }, 2325 | { 0, 2 }, 2326 | { 1, 2 }, 2327 | { 4, 4 }, 2328 | { 19, 9 }, 2329 | { 0, 2 }, 2330 | { 1, 2 }, 2331 | { 3, 4 }, 2332 | { 2, 3 }, 2333 | { 0, 2 }, 2334 | { 1, 2 }, 2335 | { 5, 4 }, 2336 | { 8, 5 }, 2337 | { 0, 2 }, 2338 | { 1, 2 }, 2339 | { 9, 6 }, 2340 | { 2, 3 }, 2341 | { 0, 2 }, 2342 | { 1, 2 }, 2343 | { 4, 4 }, 2344 | { 7, 5 }, 2345 | { 0, 2 }, 2346 | { 1, 2 }, 2347 | { 3, 4 }, 2348 | { 2, 3 }, 2349 | { 0, 2 }, 2350 | { 1, 2 }, 2351 | { 5, 4 }, 2352 | { 17, 8 }, 2353 | { 0, 2 }, 2354 | { 1, 2 }, 2355 | { 6, 5 }, 2356 | { 2, 3 }, 2357 | { 0, 2 }, 2358 | { 1, 2 }, 2359 | { 4, 4 }, 2360 | { 10, 6 }, 2361 | { 0, 2 }, 2362 | { 1, 2 }, 2363 | { 3, 4 }, 2364 | { 2, 3 }, 2365 | { 0, 2 }, 2366 | { 1, 2 }, 2367 | { 5, 4 }, 2368 | { 8, 5 }, 2369 | { 0, 2 }, 2370 | { 1, 2 }, 2371 | { 12, 7 }, 2372 | { 2, 3 }, 2373 | { 0, 2 }, 2374 | { 1, 2 }, 2375 | { 4, 4 }, 2376 | { 7, 5 }, 2377 | { 0, 2 }, 2378 | { 1, 2 }, 2379 | { 3, 4 }, 2380 | { 2, 3 }, 2381 | { 0, 2 }, 2382 | { 1, 2 }, 2383 | { 5, 4 }, 2384 | { 11, 6 }, 2385 | { 0, 2 }, 2386 | { 1, 2 }, 2387 | { 6, 5 }, 2388 | { 2, 3 }, 2389 | { 0, 2 }, 2390 | { 1, 2 }, 2391 | { 4, 4 }, 2392 | { 13, 7 }, 2393 | { 0, 2 }, 2394 | { 1, 2 }, 2395 | { 3, 4 }, 2396 | { 2, 3 }, 2397 | { 0, 2 }, 2398 | { 1, 2 }, 2399 | { 5, 4 }, 2400 | { 8, 5 }, 2401 | { 0, 2 }, 2402 | { 1, 2 }, 2403 | { 9, 6 }, 2404 | { 2, 3 }, 2405 | { 0, 2 }, 2406 | { 1, 2 }, 2407 | { 4, 4 }, 2408 | { 7, 5 }, 2409 | { 0, 2 }, 2410 | { 1, 2 }, 2411 | { 3, 4 }, 2412 | { 2, 3 }, 2413 | { 0, 2 }, 2414 | { 1, 2 }, 2415 | { 5, 4 }, 2416 | { 16, 8 }, 2417 | { 0, 2 }, 2418 | { 1, 2 }, 2419 | { 6, 5 }, 2420 | { 2, 3 }, 2421 | { 0, 2 }, 2422 | { 1, 2 }, 2423 | { 4, 4 }, 2424 | { 10, 6 }, 2425 | { 0, 2 }, 2426 | { 1, 2 }, 2427 | { 3, 4 }, 2428 | { 2, 3 }, 2429 | { 0, 2 }, 2430 | { 1, 2 }, 2431 | { 5, 4 }, 2432 | { 8, 5 }, 2433 | { 0, 2 }, 2434 | { 1, 2 }, 2435 | { 14, 8 }, 2436 | { 2, 3 }, 2437 | { 0, 2 }, 2438 | { 1, 2 }, 2439 | { 4, 4 }, 2440 | { 7, 5 }, 2441 | { 0, 2 }, 2442 | { 1, 2 }, 2443 | { 3, 4 }, 2444 | { 2, 3 }, 2445 | { 0, 2 }, 2446 | { 1, 2 }, 2447 | { 5, 4 }, 2448 | { 11, 6 }, 2449 | { 0, 2 }, 2450 | { 1, 2 }, 2451 | { 6, 5 }, 2452 | { 2, 3 }, 2453 | { 0, 2 }, 2454 | { 1, 2 }, 2455 | { 4, 4 }, 2456 | { 22, 10 }, 2457 | { 0, 2 }, 2458 | { 1, 2 }, 2459 | { 3, 4 }, 2460 | { 2, 3 }, 2461 | { 0, 2 }, 2462 | { 1, 2 }, 2463 | { 5, 4 }, 2464 | { 8, 5 }, 2465 | { 0, 2 }, 2466 | { 1, 2 }, 2467 | { 9, 6 }, 2468 | { 2, 3 }, 2469 | { 0, 2 }, 2470 | { 1, 2 }, 2471 | { 4, 4 }, 2472 | { 7, 5 }, 2473 | { 0, 2 }, 2474 | { 1, 2 }, 2475 | { 3, 4 } 2476 | }; 2477 | -------------------------------------------------------------------------------- /indexbufferdecompression.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #include "indexbufferdecompression.h" 26 | #include "readbitstream.h" 27 | #include "indexcompressionconstants.h" 28 | #include "indexbuffercompressionformat.h" 29 | #include 30 | 31 | static const uint32_t EDGE_MAX_CODE_LENGTH = 11; 32 | static const uint32_t VERTEX_MAX_CODE_LENGTH = 8; 33 | static const uint32_t TRIANGLE_MAX_CODE_LENGTH = 7; 34 | 35 | #include "indexbufferdecodetables.h" 36 | 37 | // Decompress triangle codes using prefix coding based on static tables. 38 | template 39 | void DecompressTriangleCodesPrefix( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) 40 | { 41 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 42 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 43 | 44 | uint32_t edgesRead = 0; 45 | uint32_t verticesRead = 0; 46 | uint32_t newVertices = 0; 47 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 48 | 49 | // iterate through the triangles 50 | for ( Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 51 | { 52 | IndexBufferTriangleCodes code = static_cast< IndexBufferTriangleCodes >( input.Decode( TriangleDecoding, TRIANGLE_MAX_CODE_LENGTH ) ); 53 | 54 | switch ( code ) 55 | { 56 | case IB_EDGE_NEW: 57 | { 58 | uint32_t edgeFifoIndex = input.Decode( EdgeDecoding, EDGE_MAX_CODE_LENGTH ); 59 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 60 | 61 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 62 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 63 | 64 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = 65 | triangle[ 2 ] = static_cast< Ty >( newVertices ); 66 | 67 | ++newVertices; 68 | ++verticesRead; 69 | 70 | break; 71 | } 72 | 73 | case IB_EDGE_CACHED: 74 | { 75 | uint32_t edgeFifoIndex = input.Decode( EdgeDecoding, EDGE_MAX_CODE_LENGTH ); 76 | uint32_t vertexFifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 77 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 78 | 79 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 80 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 81 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 82 | 83 | break; 84 | } 85 | case IB_EDGE_FREE: 86 | { 87 | uint32_t edgeFifoIndex = input.Decode( EdgeDecoding, EDGE_MAX_CODE_LENGTH ); 88 | uint32_t relativeVertex = input.ReadVInt(); 89 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 90 | 91 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 92 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 93 | 94 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 95 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 96 | 97 | ++verticesRead; 98 | 99 | break; 100 | } 101 | case IB_NEW_NEW_NEW: 102 | { 103 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 104 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 105 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 106 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 107 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 108 | triangle[ 2 ] = static_cast< Ty >( newVertices + 2 ); 109 | 110 | newVertices += 3; 111 | verticesRead += 3; 112 | 113 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 114 | 115 | ++edgesRead; 116 | break; 117 | } 118 | case IB_NEW_NEW_CACHED: 119 | { 120 | uint32_t vertexFifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 121 | 122 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 123 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 124 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 125 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 126 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 127 | 128 | verticesRead += 2; 129 | newVertices += 2; 130 | 131 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 132 | 133 | ++edgesRead; 134 | break; 135 | } 136 | case IB_NEW_NEW_FREE: 137 | { 138 | uint32_t relativeVertex = input.ReadVInt(); 139 | 140 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 141 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 142 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 143 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 144 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 145 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 146 | 147 | newVertices += 2; 148 | verticesRead += 3; 149 | 150 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 151 | 152 | ++edgesRead; 153 | break; 154 | } 155 | case IB_NEW_CACHED_CACHED: 156 | { 157 | uint32_t vertex1FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 158 | uint32_t vertex2FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 159 | 160 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 161 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex2FifoIndex ) & VERTEX_FIFO_MASK ] ); 162 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 163 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 164 | 165 | ++verticesRead; 166 | ++newVertices; 167 | 168 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 169 | 170 | ++edgesRead; 171 | break; 172 | } 173 | case IB_NEW_CACHED_FREE: 174 | { 175 | uint32_t vertexFifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 176 | uint32_t relativeVertex = input.ReadVInt(); 177 | 178 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 179 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 180 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 181 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 182 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 183 | 184 | verticesRead += 2; 185 | ++newVertices; 186 | 187 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 188 | 189 | ++edgesRead; 190 | break; 191 | } 192 | case IB_NEW_FREE_CACHED: 193 | { 194 | uint32_t relativeVertex = input.ReadVInt(); 195 | uint32_t vertexFifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 196 | 197 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 198 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 199 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 200 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 201 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 202 | 203 | verticesRead += 2; 204 | ++newVertices; 205 | 206 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 207 | 208 | ++edgesRead; 209 | break; 210 | } 211 | case IB_NEW_FREE_FREE: 212 | { 213 | uint32_t relativeVertex1 = input.ReadVInt(); 214 | uint32_t relativeVertex2 = input.ReadVInt(); 215 | 216 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 217 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 218 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 219 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 220 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 221 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 222 | 223 | verticesRead += 3; 224 | ++newVertices; 225 | 226 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 227 | 228 | ++edgesRead; 229 | 230 | break; 231 | } 232 | case IB_CACHED_CACHED_CACHED: 233 | { 234 | uint32_t vertex0FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 235 | uint32_t vertex1FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 236 | uint32_t vertex2FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 237 | 238 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 239 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 240 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex2FifoIndex ) & VERTEX_FIFO_MASK ] ); 241 | 242 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 243 | 244 | ++edgesRead; 245 | break; 246 | } 247 | case IB_CACHED_CACHED_FREE: 248 | { 249 | uint32_t vertex0FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 250 | uint32_t vertex1FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 251 | uint32_t relativeVertex2 = input.ReadVInt(); 252 | 253 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 254 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 255 | 256 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 257 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 258 | 259 | ++verticesRead; 260 | 261 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 262 | 263 | ++edgesRead; 264 | 265 | break; 266 | } 267 | case IB_CACHED_FREE_FREE: 268 | { 269 | uint32_t vertex0FifoIndex = input.Decode( VertexDecoding, VERTEX_MAX_CODE_LENGTH ); 270 | uint32_t relativeVertex1 = input.ReadVInt(); 271 | uint32_t relativeVertex2 = input.ReadVInt(); 272 | 273 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 274 | 275 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 276 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 277 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 278 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 279 | 280 | verticesRead += 2; 281 | 282 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 283 | 284 | ++edgesRead; 285 | 286 | break; 287 | } 288 | case IB_FREE_FREE_FREE: 289 | { 290 | uint32_t relativeVertex0 = input.ReadVInt(); 291 | uint32_t relativeVertex1 = input.ReadVInt(); 292 | uint32_t relativeVertex2 = input.ReadVInt(); 293 | 294 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 295 | triangle[ 0 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex0 ); 296 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 297 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 298 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 299 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 300 | 301 | verticesRead += 3; 302 | 303 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 304 | 305 | ++edgesRead; 306 | 307 | break; 308 | } 309 | } 310 | 311 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 312 | 313 | ++edgesRead; 314 | 315 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 316 | 317 | ++edgesRead; 318 | } 319 | 320 | // Skip over padding at the end, put in so a short prefix code (1 bit) doesn't cause an overflow 321 | input.Read( LONGEST_PREFIX_CODE - 1 ); 322 | } 323 | 324 | // Decompression using triangle codes without entropy encoding (as opposed to individual vertex/edge codes). 325 | template 326 | void DecompressTriangleCodes1( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) 327 | { 328 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 329 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 330 | 331 | uint32_t edgesRead = 0; 332 | uint32_t verticesRead = 0; 333 | uint32_t newVertices = 0; 334 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 335 | 336 | // iterate through the triangles 337 | for ( Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 338 | { 339 | IndexBufferTriangleCodes code = static_cast< IndexBufferTriangleCodes >( input.Read( IB_TRIANGLE_CODE_BITS ) ); 340 | 341 | switch ( code ) 342 | { 343 | case IB_EDGE_NEW: 344 | { 345 | uint32_t edgeFifoIndex = input.Read( CACHED_EDGE_BITS ); 346 | 347 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 348 | 349 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 350 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 351 | 352 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = 353 | triangle[ 2 ] = static_cast< Ty >( newVertices ); 354 | 355 | ++newVertices; 356 | ++verticesRead; 357 | 358 | break; 359 | } 360 | 361 | case IB_EDGE_CACHED: 362 | { 363 | uint32_t edgeFifoIndex = input.Read( CACHED_EDGE_BITS ); 364 | uint32_t vertexFifoIndex = input.Read( CACHED_VERTEX_BITS ); 365 | 366 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 367 | 368 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 369 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 370 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 371 | 372 | break; 373 | } 374 | 375 | case IB_EDGE_FREE: 376 | { 377 | uint32_t edgeFifoIndex = input.Read( CACHED_EDGE_BITS ); 378 | uint32_t relativeVertex = input.ReadVInt(); 379 | 380 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - edgeFifoIndex ) & EDGE_FIFO_MASK ]; 381 | 382 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 383 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 384 | 385 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 386 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 387 | ++verticesRead; 388 | 389 | break; 390 | } 391 | 392 | case IB_NEW_NEW_NEW: 393 | { 394 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 395 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 396 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 397 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 398 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 399 | triangle[ 2 ] = static_cast< Ty >( newVertices + 2 ); 400 | 401 | newVertices += 3; 402 | verticesRead += 3; 403 | 404 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 405 | 406 | ++edgesRead; 407 | break; 408 | } 409 | 410 | case IB_NEW_NEW_CACHED: 411 | { 412 | uint32_t vertexFifoIndex = input.Read( CACHED_VERTEX_BITS ); 413 | 414 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 415 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 416 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 417 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 418 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 419 | 420 | verticesRead += 2; 421 | newVertices += 2; 422 | 423 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 424 | 425 | ++edgesRead; 426 | break; 427 | } 428 | 429 | case IB_NEW_NEW_FREE: 430 | { 431 | uint32_t relativeVertex = input.ReadVInt(); 432 | 433 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 434 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 435 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 436 | triangle[ 1 ] = static_cast< Ty >( newVertices + 1 ); 437 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 438 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 439 | 440 | newVertices += 2; 441 | verticesRead += 3; 442 | 443 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 444 | 445 | ++edgesRead; 446 | break; 447 | } 448 | 449 | case IB_NEW_CACHED_CACHED: 450 | { 451 | uint32_t vertex1FifoIndex = input.Read( CACHED_VERTEX_BITS ); 452 | uint32_t vertex2FifoIndex = input.Read( CACHED_VERTEX_BITS ); 453 | 454 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 455 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex2FifoIndex ) & VERTEX_FIFO_MASK ] ); 456 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 457 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 458 | 459 | ++verticesRead; 460 | ++newVertices; 461 | 462 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 463 | 464 | ++edgesRead; 465 | break; 466 | } 467 | 468 | case IB_NEW_CACHED_FREE: 469 | { 470 | uint32_t vertexFifoIndex = input.Read( CACHED_VERTEX_BITS ); 471 | uint32_t relativeVertex = input.ReadVInt(); 472 | 473 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 474 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 475 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 476 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 477 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 478 | 479 | verticesRead += 2; 480 | ++newVertices; 481 | 482 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 483 | 484 | ++edgesRead; 485 | break; 486 | } 487 | 488 | case IB_NEW_FREE_CACHED: 489 | { 490 | uint32_t relativeVertex = input.ReadVInt(); 491 | uint32_t vertexFifoIndex = input.Read( CACHED_VERTEX_BITS ); 492 | 493 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertexFifoIndex ) & VERTEX_FIFO_MASK ] ); 494 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 495 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 496 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 497 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex ); 498 | 499 | verticesRead += 2; 500 | ++newVertices; 501 | 502 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 503 | 504 | ++edgesRead; 505 | break; 506 | } 507 | 508 | case IB_NEW_FREE_FREE: 509 | { 510 | uint32_t relativeVertex1 = input.ReadVInt(); 511 | uint32_t relativeVertex2 = input.ReadVInt(); 512 | 513 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 514 | triangle[ 0 ] = static_cast< Ty >( newVertices ); 515 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 516 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 517 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 518 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 519 | 520 | verticesRead += 3; 521 | ++newVertices; 522 | 523 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 524 | 525 | ++edgesRead; 526 | 527 | break; 528 | } 529 | 530 | case IB_CACHED_CACHED_CACHED: 531 | { 532 | uint32_t vertex0FifoIndex = input.Read( CACHED_VERTEX_BITS ); 533 | uint32_t vertex1FifoIndex = input.Read( CACHED_VERTEX_BITS ); 534 | uint32_t vertex2FifoIndex = input.Read( CACHED_VERTEX_BITS ); 535 | 536 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 537 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 538 | triangle[ 2 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex2FifoIndex ) & VERTEX_FIFO_MASK ] ); 539 | 540 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 541 | 542 | ++edgesRead; 543 | break; 544 | } 545 | 546 | case IB_CACHED_CACHED_FREE: 547 | { 548 | uint32_t vertex0FifoIndex = input.Read( CACHED_VERTEX_BITS ); 549 | uint32_t vertex1FifoIndex = input.Read( CACHED_VERTEX_BITS ); 550 | uint32_t relativeVertex2 = input.ReadVInt(); 551 | 552 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 553 | triangle[ 1 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex1FifoIndex ) & VERTEX_FIFO_MASK ] ); 554 | 555 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 556 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 557 | 558 | ++verticesRead; 559 | 560 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 561 | 562 | ++edgesRead; 563 | 564 | break; 565 | } 566 | 567 | case IB_CACHED_FREE_FREE: 568 | { 569 | uint32_t vertex0FifoIndex = input.Read( CACHED_VERTEX_BITS ); 570 | uint32_t relativeVertex1 = input.ReadVInt(); 571 | uint32_t relativeVertex2 = input.ReadVInt(); 572 | 573 | triangle[ 0 ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - vertex0FifoIndex ) & VERTEX_FIFO_MASK ] ); 574 | 575 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 576 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 577 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 578 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 579 | 580 | verticesRead += 2; 581 | 582 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 583 | 584 | ++edgesRead; 585 | 586 | break; 587 | } 588 | 589 | case IB_FREE_FREE_FREE: 590 | { 591 | uint32_t relativeVertex0 = input.ReadVInt(); 592 | uint32_t relativeVertex1 = input.ReadVInt(); 593 | uint32_t relativeVertex2 = input.ReadVInt(); 594 | 595 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 596 | triangle[ 0 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex0 ); 597 | vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = 598 | triangle[ 1 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex1 ); 599 | vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = 600 | triangle[ 2 ] = static_cast< Ty >( ( newVertices - 1 ) - relativeVertex2 ); 601 | 602 | verticesRead += 3; 603 | 604 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 605 | 606 | ++edgesRead; 607 | 608 | break; 609 | } 610 | 611 | case IB_EDGE_0_NEW: 612 | { 613 | const Edge& edge = edgeFifo[ ( edgesRead - 1 ) & EDGE_FIFO_MASK ]; 614 | 615 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 616 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 617 | 618 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = 619 | triangle[ 2 ] = static_cast< Ty >( newVertices ); 620 | 621 | ++newVertices; 622 | ++verticesRead; 623 | break; 624 | } 625 | 626 | case IB_EDGE_1_NEW: 627 | { 628 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - 1 ) & EDGE_FIFO_MASK ]; 629 | 630 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 631 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 632 | 633 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = 634 | triangle[ 2 ] = static_cast< Ty >( newVertices ); 635 | 636 | ++newVertices; 637 | ++verticesRead; 638 | break; 639 | } 640 | } 641 | 642 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 643 | 644 | ++edgesRead; 645 | 646 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 647 | 648 | ++edgesRead; 649 | } 650 | } 651 | 652 | // Decompress using per indice (vertex/edge) codes, no entropy encoding. 653 | template 654 | void DecompressIndiceCodes1( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) 655 | { 656 | Edge edgeFifo[ EDGE_FIFO_SIZE ]; 657 | uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; 658 | 659 | uint32_t edgesRead = 0; 660 | uint32_t verticesRead = 0; 661 | uint32_t newVertices = 0; 662 | const Ty* triangleEnd = triangles + ( triangleCount * 3 ); 663 | 664 | // iterate through the triangles 665 | for ( Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) 666 | { 667 | int readVertex = 0; 668 | bool skipFirstEdge = false; 669 | 670 | while ( readVertex < 3 ) 671 | { 672 | IndexBufferCodes code = static_cast< IndexBufferCodes >( input.Read( IB_VERTEX_CODE_BITS ) ); 673 | 674 | switch ( code ) 675 | { 676 | case IB_NEW_VERTEX: 677 | 678 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 679 | triangle[ readVertex ] = static_cast< Ty >( newVertices ); 680 | 681 | ++readVertex; 682 | ++verticesRead; 683 | ++newVertices; 684 | 685 | break; 686 | 687 | case IB_CACHED_EDGE: 688 | { 689 | assert( readVertex == 0 ); 690 | 691 | uint32_t fifoIndex = input.Read( CACHED_EDGE_BITS ); 692 | const Edge& edge = edgeFifo[ ( ( edgesRead - 1 ) - fifoIndex ) & EDGE_FIFO_MASK ]; 693 | 694 | triangle[ 0 ] = static_cast< Ty >( edge.second ); 695 | triangle[ 1 ] = static_cast< Ty >( edge.first ); 696 | 697 | readVertex += 2; 698 | skipFirstEdge = true; 699 | 700 | break; 701 | } 702 | 703 | case IB_CACHED_VERTEX: 704 | { 705 | uint32_t fifoIndex = input.Read( CACHED_VERTEX_BITS ); 706 | 707 | triangle[ readVertex ] = static_cast< Ty >( vertexFifo[ ( ( verticesRead - 1 ) - fifoIndex ) & VERTEX_FIFO_MASK ] ); 708 | 709 | ++readVertex; 710 | 711 | break; 712 | } 713 | 714 | case IB_FREE_VERTEX: 715 | { 716 | uint32_t relativeVertex = input.ReadVInt(); 717 | uint32_t vertex = ( newVertices - 1 ) - relativeVertex; 718 | 719 | vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = 720 | triangle[ readVertex ] = static_cast< Ty >( vertex ); 721 | 722 | ++verticesRead; 723 | ++readVertex; 724 | break; 725 | } 726 | 727 | } 728 | } 729 | 730 | if ( !skipFirstEdge ) 731 | { 732 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); 733 | 734 | ++edgesRead; 735 | } 736 | else // first 2 verts were an edge case, so insert them into the vertex fifo. 737 | { 738 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = triangle[ 0 ]; 739 | 740 | ++verticesRead; 741 | 742 | vertexFifo[ verticesRead & EDGE_FIFO_MASK ] = triangle[ 1 ]; 743 | 744 | ++verticesRead; 745 | } 746 | 747 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); 748 | 749 | ++edgesRead; 750 | 751 | edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); 752 | 753 | ++edgesRead; 754 | } 755 | } 756 | 757 | // Type Generalized indice decompression, detects format from stream. 758 | template < typename Ty > 759 | void DecompressIndexBuffer( Ty* triangles, uint32_t triangleCount, ReadBitstream& input ) 760 | { 761 | IndexBufferCompressionFormat format = static_cast< IndexBufferCompressionFormat >( input.ReadVInt() ); 762 | 763 | switch ( format ) 764 | { 765 | case IBCF_PER_INDICE_1: 766 | 767 | DecompressIndiceCodes1( triangles, triangleCount, input ); 768 | break; 769 | 770 | case IBCF_PER_TRIANGLE_1: 771 | 772 | DecompressTriangleCodes1( triangles, triangleCount, input ); 773 | break; 774 | 775 | case IBCF_PER_TRIANGLE_PREFIX_ENTROPY: 776 | 777 | DecompressTriangleCodesPrefix( triangles, triangleCount, input ); 778 | break; 779 | 780 | default: // IBCF_AUTO: 781 | break; 782 | } 783 | } 784 | 785 | // 32 bit indice decompression 786 | void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input ) 787 | { 788 | DecompressIndexBuffer( triangles, triangleCount, input ); 789 | } 790 | 791 | // 16 bit indice decompression 792 | void DecompressIndexBuffer( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input ) 793 | { 794 | DecompressIndexBuffer( triangles, triangleCount, input ); 795 | } 796 | -------------------------------------------------------------------------------- /indexbufferdecompression.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef INDEX_BUFFER_DECOMPRESSION_H__ 26 | #define INDEX_BUFFER_DECOMPRESSION_H__ 27 | #pragma once 28 | 29 | #include 30 | #include "readbitstream.h" 31 | 32 | // Compress an index buffer, writing the results out to a bitstream and providing a vertex remapping (which will be in pre-transform cache optimised 33 | // order. 34 | // Parameters: 35 | // [out] triangles - Triangle list index buffer (3 indices to vertices per triangle), output from the decompression - 16bit indices 36 | // [in] triangle count - The number of triangles to decompress. 37 | // [in] input - The bit stream that the compressed data will be read from. 38 | void DecompressIndexBuffer( uint16_t* triangles, uint32_t triangleCount, ReadBitstream& input ); 39 | 40 | // Same as above but 32 bit indices. 41 | void DecompressIndexBuffer( uint32_t* triangles, uint32_t triangleCount, ReadBitstream& input ); 42 | 43 | #endif // -- INDEX_BUFFER_DECOMPRESSION_H__ 44 | -------------------------------------------------------------------------------- /indexcompressionconstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef INDEX_COMPRESSION_CONSTANTS_H__ 26 | #define INDEX_COMPRESSION_CONSTANTS_H__ 27 | #pragma once 28 | 29 | #include 30 | 31 | #ifdef _MSC_VER 32 | 33 | #define ICC_INLINE __forceinline 34 | 35 | #else 36 | 37 | #define ICC_INLINE inline 38 | 39 | #endif 40 | 41 | // Constant fifo and code sizes. 42 | const uint32_t VERTEX_FIFO_SIZE = 32; 43 | const uint32_t VERTEX_FIFO_MASK = VERTEX_FIFO_SIZE - 1; 44 | const uint32_t EDGE_FIFO_SIZE = 32; 45 | const uint32_t EDGE_FIFO_MASK = EDGE_FIFO_SIZE - 1; 46 | const uint32_t CACHED_EDGE_BITS = 5; 47 | const uint32_t CACHED_VERTEX_BITS = 5; 48 | 49 | const uint32_t IB_VERTEX_CODE_BITS = 2; 50 | 51 | const uint32_t IB_TRIANGLE_CODE_BITS = 4; 52 | 53 | // The longest prefix code length in bits for the prefix coded version. 54 | const uint32_t LONGEST_PREFIX_CODE = 11; 55 | 56 | // Edge in the edge fifo. 57 | struct Edge 58 | { 59 | void set( uint32_t f, uint32_t s ) 60 | { 61 | first = f; 62 | second = s; 63 | } 64 | 65 | uint32_t first; 66 | uint32_t second; 67 | }; 68 | 69 | // These are the vertex/edge codes for CompressIndexBuffer 70 | enum IndexBufferCodes 71 | { 72 | // Represents a yet un-seen vertex. 73 | IB_NEW_VERTEX = 0, 74 | 75 | // Represents 2 vertices on an edge in the edge fifo, which will be used as the first 2 vertices of the 76 | // triangle. 77 | IB_CACHED_EDGE = 1, 78 | 79 | // Represents a vertex that has been seen recently and is still in the vertex fifo. 80 | IB_CACHED_VERTEX = 2, 81 | 82 | // Represents a vertex that has been seen 83 | IB_FREE_VERTEX = 3 84 | }; 85 | 86 | // These are the triangle codes for CompressIndexBuffer2 87 | enum IndexBufferTriangleCodes 88 | { 89 | IB_EDGE_NEW = 0, 90 | IB_EDGE_CACHED = 1, 91 | IB_EDGE_FREE = 2, 92 | IB_NEW_NEW_NEW = 3, 93 | IB_NEW_NEW_CACHED = 4, 94 | IB_NEW_NEW_FREE = 5, 95 | IB_NEW_CACHED_CACHED = 6, 96 | IB_NEW_CACHED_FREE= 7, 97 | IB_NEW_FREE_CACHED = 8, 98 | IB_NEW_FREE_FREE = 9, 99 | IB_CACHED_CACHED_CACHED = 10, 100 | IB_CACHED_CACHED_FREE = 11, 101 | IB_CACHED_FREE_FREE = 12, 102 | IB_FREE_FREE_FREE = 13, 103 | 104 | // Note these two codes aren't used for prefix coding 105 | IB_EDGE_0_NEW = 14, 106 | IB_EDGE_1_NEW = 15 107 | }; 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /readbitstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef READ_BIT_STREAM_H__ 26 | #define READ_BIT_STREAM_H__ 27 | #pragma once 28 | 29 | #include 30 | #include 31 | 32 | #ifdef _MSC_VER 33 | 34 | #define RBS_INLINE __forceinline 35 | 36 | #else 37 | 38 | #define RBS_INLINE inline 39 | 40 | #endif 41 | 42 | // Detect if our processor is x86/x64 (supports unaligned reads and is little endian) 43 | // Note that other processors could be added 44 | #if __X86_64__ || \ 45 | _M_X64 || \ 46 | _M_AMD64 || \ 47 | defined(__x86_64__) || \ 48 | __386__ || \ 49 | _M_I386 || \ 50 | (defined(__DMC__) && defined(_M_IX86)) || \ 51 | (defined(_MSC_VER) && _M_IX86) || \ 52 | defined(__i386__) 53 | 54 | #define RBS_LITTLE_ENDIAN_UNALIGNED 55 | 56 | #endif 57 | 58 | 59 | // Used for representing an entry in the decoding table for prefix coding. 60 | struct PrefixCodeTableEntry 61 | { 62 | uint8_t original; 63 | uint8_t codeLength; 64 | }; 65 | 66 | // Very simple reader bitstream, note it does not do any overflow checking, etc. 67 | class ReadBitstream 68 | { 69 | public: 70 | 71 | // Construct the bitstream with a fixed byte buffer (which should be padded out to multiples of 8 bytes, as we read in 8 byte chunks). 72 | ReadBitstream( const uint8_t* buffer, size_t bufferSize ); 73 | 74 | ~ReadBitstream() {} 75 | 76 | // Read a number of bits 77 | uint32_t Read( uint32_t bitcount ); 78 | 79 | // Get the buffer size of this in bytes 80 | size_t Size() const { return m_bufferSize; } 81 | 82 | // Read a variable encoded int (use MSB of each byte to signal another byte 83 | uint32_t ReadVInt(); 84 | 85 | // Decode prefix code using table (least significant bits lookup). 86 | // Note, maximum code length should be 32 or less (practically much lower, as you need a table to match). 87 | // Also note, this uses 4 byte reads/only partially refills the bit-buffer. 88 | uint32_t Decode( const PrefixCodeTableEntry* table, const uint32_t maximumCodeLength ); 89 | 90 | private: 91 | 92 | uint64_t m_bitBuffer; 93 | 94 | const uint8_t* m_buffer; 95 | const uint8_t* m_cursor; 96 | 97 | size_t m_bufferSize; 98 | uint32_t m_bitsLeft; 99 | 100 | }; 101 | 102 | 103 | RBS_INLINE uint32_t ReadBitstream::Decode( const PrefixCodeTableEntry* table, uint32_t maximumCodeSize ) 104 | { 105 | if ( m_bitsLeft < maximumCodeSize ) 106 | { 107 | #if defined( RBS_LITTLE_ENDIAN_UNALIGNED ) 108 | 109 | // We're on x86/x64, so we're little endian and can do an un-aligned read. 110 | uint64_t intermediateBitBuffer = *(const uint32_t*)m_cursor; 111 | 112 | #else 113 | 114 | // other processor architecture, unknown endian/unaligned read support 115 | uint64_t intermediateBitBuffer = m_cursor[ 0 ]; 116 | 117 | intermediateBitBuffer |= static_cast< uint64_t >( m_cursor[ 1 ] ) << 8; 118 | intermediateBitBuffer |= static_cast< uint64_t >( m_cursor[ 2 ] ) << 16; 119 | intermediateBitBuffer |= static_cast< uint64_t >( m_cursor[ 3 ] ) << 24; 120 | 121 | #endif 122 | 123 | m_bitBuffer |= intermediateBitBuffer << m_bitsLeft; 124 | 125 | m_bitsLeft += 32; 126 | m_cursor += 4; 127 | } 128 | 129 | // mask should be constant collasped due to maximumCodeSize being fixed and this being inlined. 130 | const uint64_t mask = ( uint64_t( 1 ) << maximumCodeSize ) - 1; 131 | const PrefixCodeTableEntry& codeEntry = table[ m_bitBuffer & mask ]; 132 | const uint32_t codeLength = codeEntry.codeLength; 133 | 134 | m_bitBuffer >>= codeLength; 135 | m_bitsLeft -= codeLength; 136 | 137 | return codeEntry.original; 138 | } 139 | 140 | 141 | inline ReadBitstream::ReadBitstream( const uint8_t* buffer, size_t bufferSize ) 142 | { 143 | m_cursor = 144 | m_buffer = buffer; 145 | m_bufferSize = bufferSize; 146 | 147 | if ( bufferSize >= 8 ) 148 | { 149 | m_bitBuffer = m_cursor[ 0 ]; 150 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 1 ] ) << 8; 151 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 2 ] ) << 16; 152 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 3 ] ) << 24; 153 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 4 ] ) << 32; 154 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 5 ] ) << 40; 155 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 6 ] ) << 48; 156 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 7 ] ) << 56; 157 | 158 | m_cursor += 8; 159 | m_bitsLeft = 64; 160 | } 161 | else 162 | { 163 | m_bitsLeft = 0; 164 | } 165 | } 166 | 167 | 168 | RBS_INLINE uint32_t ReadBitstream::Read( uint32_t bitCount ) 169 | { 170 | uint64_t mask = ( uint64_t( 1 ) << bitCount ) - 1; 171 | uint32_t result = static_cast< uint32_t >( m_bitBuffer & mask ); 172 | 173 | m_bitBuffer >>= bitCount; 174 | 175 | if ( m_bitsLeft < bitCount ) 176 | { 177 | #if defined( RBS_LITTLE_ENDIAN_UNALIGNED ) 178 | 179 | // We're on x86/x64, so we're little endian and can do an un-aligned read. 180 | m_bitBuffer = *(const uint64_t*)m_cursor; 181 | 182 | #else 183 | 184 | // other processor architecture, unknown endian/unaligned read support 185 | m_bitBuffer = m_cursor[ 0 ]; 186 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 1 ] ) << 8; 187 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 2 ] ) << 16; 188 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 3 ] ) << 24; 189 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 4 ] ) << 32; 190 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 5 ] ) << 40; 191 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 6 ] ) << 48; 192 | m_bitBuffer |= static_cast< uint64_t >( m_cursor[ 7 ] ) << 56; 193 | 194 | #endif 195 | 196 | m_cursor += 8; 197 | 198 | uint32_t leftOverBits = bitCount - m_bitsLeft; 199 | 200 | result |= static_cast< uint32_t >( m_bitBuffer << m_bitsLeft ) & mask; 201 | m_bitBuffer >>= leftOverBits; 202 | m_bitsLeft = 64 - leftOverBits; 203 | } 204 | else 205 | { 206 | m_bitsLeft -= bitCount; 207 | } 208 | 209 | return result; 210 | } 211 | 212 | 213 | RBS_INLINE uint32_t ReadBitstream::ReadVInt() 214 | { 215 | uint32_t bitsToShift = 0; 216 | uint32_t result = 0; 217 | uint32_t readByte; 218 | 219 | do 220 | { 221 | 222 | readByte = Read( 8 ); 223 | result |= ( readByte & 0x7F ) << bitsToShift; 224 | bitsToShift += 7; 225 | 226 | } 227 | while ( readByte & 0x80 ); 228 | 229 | return result; 230 | } 231 | 232 | #endif // -- READ_BIT_STREAM_H__ 233 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Vertex Cache Optimised Index Buffer Compression 2 | 3 | This is a small proof of concept for compressing and decompressing index buffer triangle lists. It's designed to maintain the order of the triangle list and perform best with a triangle list that has been vertex cache post-transform optimised (a pre-transform cache optimisation is done as part of the compression). 4 | 5 | It's also designed to be relatively lightweight, with a decompression throughput in the tens of millions of triangles per core. It does not achieve state of the art levels of compression levels (which can be less than a bit per triangle, as well as providing good chances for vertex prediction), but it does maintain ordering of triangles and support arbitrary topologies. 6 | 7 | There are some cases where the vertices within a triangle are re-ordered, but the general winding direction is maintained. 8 | 9 | ## How does it work? 10 | 11 | The inspiration was a mix of Fabian Giesen's [Simple loss-less index buffer compression](http://fgiesen.wordpress.com/2013/12/14/simple-lossless-index-buffer-compression/) and 12 | the higher compression algorithms that make use of shared edges and re-order triangles. The idea was that there is probably a middle ground between them. 13 | 14 | The basic goals were: 15 | 16 | * Maintain the ordering of triangles, exploiting vertex cache optimal ordering. 17 | 18 | * Exploit recent triangle connectivity. 19 | 20 | * Make it fast, especially for decompression, without the need to maintain large extra data structures, like winged edge. 21 | 22 | * Make it simple enough to be easily understandable. 23 | 24 | The vertex cache optimisation means that there will be quite a few vertices and edges shared between the next triangle in the list and the previous. We exploit this by maintaining two relatively small fixed size FIFOs, an edge FIFO and a vertex FIFO (not unlike the vertex cache itself, except we store recent indices). 25 | 26 | The compression relies on 4 codes: 27 | 28 | 1. A _new vertex_ code, for vertices that have not yet been seen. 29 | 30 | 2. A _cached edge_ code, for edges that have been seen recently. This code is followed by a relative index back into the edge FIFO. 31 | 32 | 3. A _cached vertex_ code, for vertices that have been seen recently. This code is followed by a relative index back into the vertex FIFO. 33 | 34 | 4. A _free vertex_ code, for vertices that have been seen, but not recently. This code is followed by a variable length integer encoding of the index relative to the most recent new vertex. 35 | 36 | Triangles can either consist of two codes, a cached edge followed by one of the vertex codes, or of 3 of the vertex codes. The most common codes in an optimised mesh are generally the cached edge and new vertex codes. 37 | 38 | Cached edges are always the first code in any triangle they appear in and may correspond to any edge in the original triangle (we check all the edges against the FIFO). This means that an individual triangle may have its vertices specified in a different order (but in the same winding direction) than the original uncompressed one. 39 | 40 | New vertex codes work because vertices are re-ordered to the order in which they appear in the mesh, meaning whenever we encounter a new vertex, we can just read and an internal counter to get 41 | the current index, incrementing it afterwards. This has the benefit of also meaning vertices are in pre-transform cache optimised order. 42 | 43 | ## Does it actually work? 44 | 45 | That's a better question! While my thoughts were that in theory it would average around 11-12bits a triangle, the Stanford Armadillo mesh (optimised with Tom Forsyth's vertex cache optimisation algorithm), with 345944 triangles, compresses the index buffer down to 563122 bytes, which is more like 13 and the Stanford Bunny is 12.85bits or so. This is not anywhere near the state of the art in terms of compression (which get down to less than a bit), but that isn't the goal. 46 | 47 | Performance wise, with the code posted here, the Armadillo compresses in 18.5 milliseconds and decompresses in 6.6 milliseconds on average on my system. The Stanford bunny is more like 1.4 milliseconds to decompress, relatively. 48 | 49 | ## Update! 50 | 51 | I've added a second more efficient (in terms of both speed and size) compression algorithm (CompressIndexBuffer2 and DecompressIndexBuffer2), as well as some changes upstream from Branimir Karadžić, who made some compiler compatibility fixes and added 16bit indice support. This uses a code per triangle instead of multiple codes for different cases. 52 | 53 | For details of the original algorithm, please see this [blog post](http://conorstokes.github.io/graphics/2014/09/28/vertex-cache-optimised-index-buffer-compression/). For details of the second algorithm, please see this [blog post](http://conorstokes.github.io/graphics/2014/09/28/vertex-cache-optimised-index-buffer-compression/). 54 | 55 | ## Update 2! 56 | 57 | There were previously some bug fixes for 64bit mode, but I have now added another compression option that adds prefix/huffman code based entropy encoding, as well as some bitstream I/O optimisations. 58 | -------------------------------------------------------------------------------- /writebitstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014-2015, Conor Stokes 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | #ifndef WRITE_BIT_STREAM_H__ 26 | #define WRITE_BIT_STREAM_H__ 27 | #pragma once 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #ifdef _MSC_VER 34 | #define WBS_INLINE __forceinline 35 | #else 36 | #define WBS_INLINE inline 37 | #endif 38 | 39 | // Used for prefix coding tables. 40 | struct PrefixCode 41 | { 42 | uint32_t code; 43 | uint32_t bitLength; 44 | }; 45 | 46 | // Very simple bitstream for writing that will grow to accommodate written bits. 47 | class WriteBitstream 48 | { 49 | public: 50 | 51 | // Construct the bit stream with an initial buffer capacity - should be a multiple of 8 and > 0 52 | WriteBitstream( size_t initialBufferCapacity = 16 ) 53 | { 54 | m_bufferCursor = 55 | m_buffer = new uint8_t[ initialBufferCapacity ]; 56 | m_bufferEnd = m_buffer + initialBufferCapacity; 57 | m_size = 0; 58 | m_bitsLeft = 64; 59 | m_bitBuffer = 0; 60 | } 61 | 62 | ~WriteBitstream() 63 | { 64 | delete[] m_buffer; 65 | } 66 | 67 | // Size in bits. 68 | size_t Size() const { return m_size; } 69 | 70 | // Write a number of bits to the stream. 71 | void Write( uint32_t value, uint32_t bitCount ); 72 | 73 | // Write a V int to the stream. 74 | void WriteVInt( uint32_t value ); 75 | 76 | // Get the size in bytes 77 | size_t ByteSize() const { return ( m_size + 7 ) >> 3; } 78 | 79 | // Finish writing by flushing the buffer. 80 | void Finish(); 81 | 82 | // Get the raw data for this buffer. 83 | const uint8_t* RawData() const { return m_buffer; } 84 | 85 | // Write a prefix code from the coding table to the stream. 86 | template 87 | void WritePrefixCode( Ty input, const PrefixCode* codes ); 88 | 89 | private: 90 | 91 | // If we need to grow the buffer. 92 | void GrowBuffer(); 93 | 94 | // Not copyable 95 | WriteBitstream( const WriteBitstream& ); 96 | 97 | // Not assignable 98 | WriteBitstream& operator=( const WriteBitstream& ); 99 | 100 | uint64_t m_bitBuffer; 101 | size_t m_size; 102 | uint8_t* m_buffer; 103 | uint8_t* m_bufferCursor; 104 | uint8_t* m_bufferEnd; 105 | uint32_t m_bitsLeft; 106 | }; 107 | 108 | 109 | WBS_INLINE void WriteBitstream::Write( uint32_t value, uint32_t bitCount ) 110 | { 111 | m_bitBuffer |= ( static_cast( value ) << ( 64 - m_bitsLeft ) ) & ( m_bitsLeft == 0 ? 0 : 0xFFFFFFFFFFFFFFFF ); 112 | 113 | if ( bitCount > m_bitsLeft ) 114 | { 115 | if ( m_bufferCursor > m_bufferEnd - 7 ) 116 | { 117 | GrowBuffer(); 118 | } 119 | 120 | m_bufferCursor[ 0 ] = m_bitBuffer & 0xFF; 121 | m_bufferCursor[ 1 ] = ( m_bitBuffer >> 8 ) & 0xFF; 122 | m_bufferCursor[ 2 ] = ( m_bitBuffer >> 16 ) & 0xFF; 123 | m_bufferCursor[ 3 ] = ( m_bitBuffer >> 24 ) & 0xFF; 124 | m_bufferCursor[ 4 ] = ( m_bitBuffer >> 32 ) & 0xFF; 125 | m_bufferCursor[ 5 ] = ( m_bitBuffer >> 40 ) & 0xFF; 126 | m_bufferCursor[ 6 ] = ( m_bitBuffer >> 48 ) & 0xFF; 127 | m_bufferCursor[ 7 ] = ( m_bitBuffer >> 56 ) & 0xFF; 128 | 129 | m_bufferCursor += 8; 130 | 131 | m_bitBuffer = value >> ( m_bitsLeft ); 132 | m_bitsLeft = 64 - ( bitCount - m_bitsLeft ); 133 | } 134 | else 135 | { 136 | m_bitsLeft -= bitCount; 137 | } 138 | 139 | m_size += bitCount; 140 | } 141 | 142 | 143 | WBS_INLINE void WriteBitstream::WriteVInt( uint32_t value ) 144 | { 145 | do 146 | { 147 | uint32_t lower7 = value & 0x7F; 148 | 149 | value >>= 7; 150 | 151 | Write( lower7 | ( value > 0 ? 0x80 : 0 ), 8 ); 152 | 153 | } while ( value > 0 ); 154 | } 155 | 156 | 157 | inline void WriteBitstream::Finish() 158 | { 159 | if ( m_bufferCursor > m_bufferEnd - 8 ) 160 | { 161 | GrowBuffer(); 162 | } 163 | 164 | m_bufferCursor[ 0 ] = m_bitBuffer & 0xFF; 165 | m_bufferCursor[ 1 ] = ( m_bitBuffer >> 8 ) & 0xFF; 166 | m_bufferCursor[ 2 ] = ( m_bitBuffer >> 16 ) & 0xFF; 167 | m_bufferCursor[ 3 ] = ( m_bitBuffer >> 24 ) & 0xFF; 168 | m_bufferCursor[ 4 ] = ( m_bitBuffer >> 32 ) & 0xFF; 169 | m_bufferCursor[ 5 ] = ( m_bitBuffer >> 40 ) & 0xFF; 170 | m_bufferCursor[ 6 ] = ( m_bitBuffer >> 48 ) & 0xFF; 171 | m_bufferCursor[ 7 ] = ( m_bitBuffer >> 56 ) & 0xFF; 172 | 173 | m_bufferCursor += 8; 174 | } 175 | 176 | 177 | WBS_INLINE void WriteBitstream::GrowBuffer() 178 | { 179 | size_t bufferSize = m_bufferEnd - m_buffer; 180 | size_t newBufferSize = bufferSize * 2; 181 | size_t bufferPosition = m_bufferCursor - m_buffer; 182 | uint8_t* newBuffer = new uint8_t[ newBufferSize ]; 183 | 184 | ::memcpy( reinterpret_cast( newBuffer ), reinterpret_cast( m_buffer ), bufferSize ); 185 | 186 | delete[] m_buffer; 187 | 188 | m_buffer = newBuffer; 189 | m_bufferCursor = m_buffer + bufferPosition; 190 | m_bufferEnd = m_buffer + newBufferSize; 191 | } 192 | 193 | 194 | template 195 | WBS_INLINE void WriteBitstream::WritePrefixCode( Ty input, const PrefixCode* codes ) 196 | { 197 | const PrefixCode& code = codes[ input ]; 198 | 199 | Write( code.code, code.bitLength ); 200 | } 201 | 202 | 203 | #endif // -- WRITE_BIT_STREAM_H__ 204 | --------------------------------------------------------------------------------