in d3d/archive/images/d3d11/tessellator.cpp [1899:2072]
void CHWTessellator::StitchTransition(int baseIndexOffset,
int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints,
TESSELLATOR_PARITY insideEdgeTessFactorParity,
int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints,
TESSELLATOR_PARITY outsideTessFactorParity
)
{
#ifdef ALLOW_XBOX_360_COMPARISON
// Tables to assist in the stitching of 2 rows of points having arbitrary TessFactors.
// The stitching order is governed by Ruler Function vertex split ordering (see external documentation).
//
// The contents of the finalPointPositionTable are where vertex i [0..32] ends up on the half-edge
// at the max tessellation amount given ruler-function split order.
// Recall the other half of an edge is mirrored, so we only need to deal with one half.
// This table is used to decide when to advance a point on the interior or exterior.
// It supports odd TessFactor up to 65 and even TessFactor up to 64.
static const int _finalPointPositionTable[33] =
{ 0, 32, 16, 8, 17, 4, 18, 9, 19, 2, 20, 10, 21, 5, 22, 11, 23,
1, 24, 12, 25, 6, 26, 13, 27, 3, 28, 14, 29, 7, 30, 15, 31 };
// The loopStart and loopEnd tables below just provide optimal loop bounds for the
// stitching algorithm further below, for any given halfTssFactor.
// There is probably a better way to encode this...
// loopStart[halfTessFactor] encodes the FIRST entry other that [0] in finalPointPositionTable[] above which is
// less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop.
static const int _loopStart[33] =
{1,1,17,9,9,5,5,5,5,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
// loopStart[halfTessFactor] encodes the LAST entry in finalPointPositionTable[] above which is
// less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop.
static const int _loopEnd[33] =
{0,0,17,17,25,25,25,25,29,29,29,29,29,29,29,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,32};
const int* finalPointPositionTable;
const int* loopStart;
const int* loopEnd;
if( m_bXBox360Mode )
{
// The XBox360 vertex introduction order is always from the center of the edge.
// So the final positions of points on the half-edge are this trivial table.
static const int XBOXfinalPointPositionTable[33] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 };
// loopStart and loopEnd (meaning described above) also become trivial for XBox360 splitting.
static const int XBOXloopStart[33] =
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
static const int XBOXloopEnd[33] =
{0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
finalPointPositionTable = XBOXfinalPointPositionTable;
loopStart = XBOXloopStart;
loopEnd = XBOXloopEnd;
}
else
{
finalPointPositionTable = _finalPointPositionTable;
loopStart = _loopStart;
loopEnd =_loopEnd;
}
#else
// Tables to assist in the stitching of 2 rows of points having arbitrary TessFactors.
// The stitching order is governed by Ruler Function vertex split ordering (see external documentation).
//
// The contents of the finalPointPositionTable are where vertex i [0..33] ends up on the half-edge
// at the max tessellation amount given ruler-function split order.
// Recall the other half of an edge is mirrored, so we only need to deal with one half.
// This table is used to decide when to advance a point on the interior or exterior.
// It supports odd TessFactor up to 65 and even TessFactor up to 64.
static const int finalPointPositionTable[33] =
{ 0, 32, 16, 8, 17, 4, 18, 9, 19, 2, 20, 10, 21, 5, 22, 11, 23,
1, 24, 12, 25, 6, 26, 13, 27, 3, 28, 14, 29, 7, 30, 15, 31 };
// The loopStart and loopEnd tables below just provide optimal loop bounds for the
// stitching algorithm further below, for any given halfTssFactor.
// There is probably a better way to encode this...
// loopStart[halfTessFactor] encodes the FIRST entry in finalPointPositionTable[] above which is
// less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop.
static const int loopStart[33] =
{1,1,17,9,9,5,5,5,5,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
// loopStart[halfTessFactor] encodes the LAST entry in finalPointPositionTable[] above which is
// less than halfTessFactor. Exceptions are entry 0 and 1, which are set up to skip the loop.
static const int loopEnd[33] =
{0,0,17,17,25,25,25,25,29,29,29,29,29,29,29,29,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,32};
#endif
if( TESSELLATOR_PARITY_ODD == insideEdgeTessFactorParity )
{
insideNumHalfTessFactorPoints -= 1;
}
if( TESSELLATOR_PARITY_ODD == outsideTessFactorParity )
{
outsideNumHalfTessFactorPoints -= 1;
}
// Walk first half
int outsidePoint = outsideEdgePointBaseOffset;
int insidePoint = insideEdgePointBaseOffset;
// iStart,iEnd are a small optimization so the loop below doesn't have to go from 0 up to 31
int iStart = min(loopStart[insideNumHalfTessFactorPoints],loopStart[outsideNumHalfTessFactorPoints]);
int iEnd = max(loopEnd[insideNumHalfTessFactorPoints],loopEnd[outsideNumHalfTessFactorPoints]);
if( finalPointPositionTable[0] < outsideNumHalfTessFactorPoints ) // since we dont' start the loop at 0 below, we need a special case.
{
// Advance outside
DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset);
baseIndexOffset += 3; outsidePoint++;
}
for(int i = iStart; i <= iEnd; i++)
{
if( /*(i>0) && <-- not needed since iStart is never 0*/(finalPointPositionTable[i] < insideNumHalfTessFactorPoints))
{
// Advance inside
DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset);
baseIndexOffset += 3; insidePoint++;
}
if((finalPointPositionTable[i] < outsideNumHalfTessFactorPoints))
{
// Advance outside
DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset);
baseIndexOffset += 3; outsidePoint++;
}
}
if( (insideEdgeTessFactorParity != outsideTessFactorParity) || (insideEdgeTessFactorParity == TESSELLATOR_PARITY_ODD))
{
if( insideEdgeTessFactorParity == outsideTessFactorParity )
{
// Quad in the middle
DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset);
baseIndexOffset += 3;
DefineClockwiseTriangle(insidePoint+1,outsidePoint,outsidePoint+1,baseIndexOffset);
baseIndexOffset += 3;
insidePoint++;
outsidePoint++;
}
else if( TESSELLATOR_PARITY_EVEN == insideEdgeTessFactorParity )
{
// Triangle pointing inside
DefineClockwiseTriangle(insidePoint,outsidePoint,outsidePoint+1,baseIndexOffset);
baseIndexOffset += 3;
outsidePoint++;
}
else
{
// Triangle pointing outside
DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset);
baseIndexOffset += 3;
insidePoint++;
}
}
// Walk second half.
for(int i = iEnd; i >= iStart; i--)
{
if((finalPointPositionTable[i] < outsideNumHalfTessFactorPoints))
{
// Advance outside
DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset);
baseIndexOffset += 3; outsidePoint++;
}
if( /*(i>0) && <-- not needed since iStart is never 0*/ (finalPointPositionTable[i] < insideNumHalfTessFactorPoints))
{
// Advance inside
DefineClockwiseTriangle(insidePoint,outsidePoint,insidePoint+1,baseIndexOffset);
baseIndexOffset += 3; insidePoint++;
}
}
// Below case is not needed if we didn't optimize loop above and made it run from 31 down to 0.
if((finalPointPositionTable[0] < outsideNumHalfTessFactorPoints))
{
DefineClockwiseTriangle(outsidePoint,outsidePoint+1,insidePoint,baseIndexOffset);
baseIndexOffset += 3; outsidePoint++;
}
}