int C_BspNode::ClassifyPolygon(C_Plane* plane , poly* polygon) { int front = 0, back = 0; for(int i = 0; i < polygon->nVertices; i++) { int whereIs = ClassifyVertex(plane , &(polygon->pVertices[i])); if(whereIs == FRONT) { front++; } else if(whereIs == BACK) { back++; } } if(front && !back) { return FRONT; } else if(!front && back) { return BACK; } else if(!front && !back) { return COINCIDENT; } else { return INTERSECTS; } }
void CompressTriangleCodes1( const Ty* triangles, uint32_t triangleCount, uint32_t* vertexRemap, uint32_t vertexCount, WriteBitstream& output ) { Edge edgeFifo[ EDGE_FIFO_SIZE ]; uint32_t vertexFifo[ VERTEX_FIFO_SIZE ]; uint32_t edgesRead = 0; uint32_t verticesRead = 0; uint32_t newVertices = 0; const Ty* triangleEnd = triangles + ( triangleCount * 3 ); assert( vertexCount < 0xFFFFFFFF ); uint32_t* vertexRemapEnd = vertexRemap + vertexCount; // clear the vertex remapping to "not found" value of 0xFFFFFFFF - dirty, but low overhead. for ( uint32_t* remappedVertex = vertexRemap; remappedVertex < vertexRemapEnd; ++remappedVertex ) { *remappedVertex = VERTEX_NOT_MAPPED; } // iterate through the triangles for ( const Ty* triangle = triangles; triangle < triangleEnd; triangle += 3 ) { int32_t lowestEdgeCursor = edgesRead >= EDGE_FIFO_SIZE ? edgesRead - EDGE_FIFO_SIZE : 0; int32_t edgeCursor = edgesRead - 1; bool foundEdge = false; int32_t spareVertex = 0; // check to make sure that there are no degenerate triangles. assert( triangle[ 0 ] != triangle[ 1 ] && triangle[ 1 ] != triangle[ 2 ] && triangle[ 2 ] != triangle[ 0 ] ); // Probe back through the edge fifo to see if one of the triangle edges is in the FIFO for ( ; edgeCursor >= lowestEdgeCursor; --edgeCursor ) { const Edge& edge = edgeFifo[ edgeCursor & EDGE_FIFO_MASK ]; // check all the edges in order and save the free vertex. if ( edge.second == triangle[ 0 ] && edge.first == triangle[ 1 ] ) { foundEdge = true; spareVertex = 2; break; } else if ( edge.second == triangle[ 1 ] && edge.first == triangle[ 2 ] ) { foundEdge = true; spareVertex = 0; break; } else if ( edge.second == triangle[ 2 ] && edge.first == triangle[ 0 ] ) { foundEdge = true; spareVertex = 1; break; } } // we found an edge so write it out, so classify a vertex and then write out the correct code. if ( foundEdge ) { uint32_t cachedVertex; uint32_t spareVertexIndice = triangle[ spareVertex ]; VertexClassification freeVertexClass = ClassifyVertex( spareVertexIndice, vertexRemap, vertexFifo, verticesRead, cachedVertex ); uint32_t relativeEdge = ( edgesRead - 1 ) - edgeCursor; switch ( freeVertexClass ) { case NEW_VERTEX: switch ( relativeEdge ) { case 0: output.Write( IB_EDGE_0_NEW, IB_TRIANGLE_CODE_BITS ); break; case 1: output.Write( IB_EDGE_1_NEW, IB_TRIANGLE_CODE_BITS ); break; default: output.Write( IB_EDGE_NEW, IB_TRIANGLE_CODE_BITS ); output.Write( relativeEdge, CACHED_EDGE_BITS ); break; } vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; vertexRemap[ spareVertexIndice ] = newVertices; ++verticesRead; ++newVertices; break; case CACHED_VERTEX: output.Write( IB_EDGE_CACHED, IB_TRIANGLE_CODE_BITS ); output.Write( relativeEdge, CACHED_EDGE_BITS ); output.Write( cachedVertex, CACHED_VERTEX_BITS ); break; case FREE_VERTEX: output.Write( IB_EDGE_FREE, IB_TRIANGLE_CODE_BITS ); output.Write( relativeEdge, CACHED_EDGE_BITS ); vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = spareVertexIndice; ++verticesRead; output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ spareVertexIndice ] ); break; } // Populate the edge fifo with the the remaining edges // Note - the winding order is important as we'll need to re-produce this on decompression. // The edges are put in as if the found edge is the first edge in the triangle (which it will be when we // reconstruct). switch ( spareVertex ) { case 0: edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); ++edgesRead; edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); ++edgesRead; break; case 1: edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 0 ], triangle[ 1 ] ); ++edgesRead; edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); ++edgesRead; break; case 2: edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 1 ], triangle[ 2 ] ); ++edgesRead; edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( triangle[ 2 ], triangle[ 0 ] ); ++edgesRead; break; } } else { VertexClassification classifications[ 3 ]; uint32_t cachedVertexIndices[ 3 ]; // classify each vertex as new, cached or free, potentially extracting a cached indice. classifications[ 0 ] = ClassifyVertex( triangle[ 0 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 0 ] ); classifications[ 1 ] = ClassifyVertex( triangle[ 1 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 1 ] ); classifications[ 2 ] = ClassifyVertex( triangle[ 2 ], vertexRemap, vertexFifo, verticesRead, cachedVertexIndices[ 2 ] ); // use the classifications to lookup the matching compression code and potentially rotate the order of the vertices. const VertexCompressionCase& compressionCase = CompressionCase[ classifications[ 0 ] ][ classifications[ 1 ] ][ classifications[ 2 ] ]; // rotate the order of the vertices based on the compression classification. uint32_t reorderedTriangle[ 3 ]; reorderedTriangle[ 0 ] = triangle[ compressionCase.vertexOrder[ 0 ] ]; reorderedTriangle[ 1 ] = triangle[ compressionCase.vertexOrder[ 1 ] ]; reorderedTriangle[ 2 ] = triangle[ compressionCase.vertexOrder[ 2 ] ]; output.Write( compressionCase.code, IB_TRIANGLE_CODE_BITS ); switch ( compressionCase.code ) { case IB_NEW_NEW_NEW: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = triangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = triangle[ 1 ]; vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = triangle[ 2 ]; vertexRemap[ triangle[ 0 ] ] = newVertices; vertexRemap[ triangle[ 1 ] ] = newVertices + 1; vertexRemap[ triangle[ 2 ] ] = newVertices + 2; verticesRead += 3; newVertices += 3; break; } case IB_NEW_NEW_CACHED: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; verticesRead += 2; newVertices += 2; break; } case IB_NEW_NEW_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; vertexRemap[ reorderedTriangle[ 1 ] ] = newVertices + 1; verticesRead += 3; newVertices += 2; break; } case IB_NEW_CACHED_CACHED: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; verticesRead += 1; newVertices += 1; break; } case IB_NEW_CACHED_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; verticesRead += 2; newVertices += 1; break; } case IB_NEW_FREE_CACHED: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; verticesRead += 2; newVertices += 1; break; } case IB_NEW_FREE_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); vertexRemap[ reorderedTriangle[ 0 ] ] = newVertices; verticesRead += 3; newVertices += 1; break; } case IB_CACHED_CACHED_CACHED: { output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 2 ] ], CACHED_VERTEX_BITS ); break; } case IB_CACHED_CACHED_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 1 ] ], CACHED_VERTEX_BITS ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); verticesRead += 1; break; } case IB_CACHED_FREE_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.Write( cachedVertexIndices[ compressionCase.vertexOrder[ 0 ] ], CACHED_VERTEX_BITS ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); verticesRead += 2; break; } case IB_FREE_FREE_FREE: { vertexFifo[ verticesRead & VERTEX_FIFO_MASK ] = reorderedTriangle[ 0 ]; vertexFifo[ ( verticesRead + 1 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 1 ]; vertexFifo[ ( verticesRead + 2 ) & VERTEX_FIFO_MASK ] = reorderedTriangle[ 2 ]; output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 0 ] ] ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 1 ] ] ); output.WriteVInt( ( newVertices - 1 ) - vertexRemap[ reorderedTriangle[ 2 ] ] ); verticesRead += 3; break; } } // populate the edge fifo with the 3 most recent edges edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 0 ], reorderedTriangle[ 1 ] ); ++edgesRead; edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 1 ], reorderedTriangle[ 2 ] ); ++edgesRead; edgeFifo[ edgesRead & EDGE_FIFO_MASK ].set( reorderedTriangle[ 2 ], reorderedTriangle[ 0 ] ); ++edgesRead; } } }