void CHWTessellator::QuadGenerateConnectivity()

in d3d/archive/images/d3d11/tessellator.cpp [791:961]


void CHWTessellator::QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors )
{
    // Generate primitives for all the concentric rings, one side at a time for each ring
    static const int startRing = 1;
    int numPointRowsToCenter[QUAD_AXES] = {((processedTessFactors.numPointsForInsideTessFactor[U]+1) >> 1),
                                            ((processedTessFactors.numPointsForInsideTessFactor[V]+1) >> 1)}; // +1 is so even tess includes the center point
    int numRings = min(numPointRowsToCenter[U],numPointRowsToCenter[V]);
    int degeneratePointRing[QUAD_AXES] = { // Even partitioning causes degenerate row of points,
                                           // which results in exceptions to the point ordering conventions 
                                           // when travelling around the rings counterclockwise.
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ? numPointRowsToCenter[V] - 1 : -1,
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U]) ? numPointRowsToCenter[U] - 1 : -1 };

    const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[QUAD_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Ueq1],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq1]};
    TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0],
                                                        processedTessFactors.outsideTessFactorParity[Veq0],
                                                        processedTessFactors.outsideTessFactorParity[Ueq1],
                                                        processedTessFactors.outsideTessFactorParity[Veq1]};
    int numPointsForOutsideEdge[QUAD_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0],
                                              processedTessFactors.numPointsForOutsideEdge[Veq0],
                                              processedTessFactors.numPointsForOutsideEdge[Ueq1],
                                              processedTessFactors.numPointsForOutsideEdge[Veq1]};

    int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset;
    int outsideEdgePointBaseOffset = 0;
    int edge;
    for(int ring = startRing; ring < numRings; ring++)
    {
        int numPointsForInsideEdge[QUAD_AXES] = {processedTessFactors.numPointsForInsideTessFactor[U] - 2*ring,
                                                 processedTessFactors.numPointsForInsideTessFactor[V] - 2*ring};

        int edge0InsidePointBaseOffset = insideEdgePointBaseOffset;
        int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset;

        for(edge = 0; edge < QUAD_EDGES; edge++ )
        {
            int parity = (edge+1)&0x1;

            int numTriangles = numPointsForInsideEdge[parity] + numPointsForOutsideEdge[edge] - 2;
            int insideBaseOffset;
            int outsideBaseOffset;
            if( edge == 3 ) // We need to patch the indexing so Stitch() can think it sees
                            // 2 sequentially increasing rows of points, even though we have wrapped around
                            // to the end of the inner and outer ring's points, so the last point is really
                            // the first point for the ring.  
                            // We make it so that when Stitch() calls AddIndex(), that function
                            // will do any necessary index adjustment.
            {
                if( ring == degeneratePointRing[parity] )
                {
                    m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset + 1;
                    m_IndexPatchContext2.cornerCaseBadValue = outsideEdgePointBaseOffset + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext2.cornerCaseReplacementValue = edge0OutsidePointBaseOffset;
                    m_IndexPatchContext2.indexInversionEndPoint = (m_IndexPatchContext2.baseIndexToInvert << 1) - 1;
                    insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                    outsideBaseOffset = outsideEdgePointBaseOffset;
                    SetUsingPatchedIndices2(true);
                }
                else
                {
                    m_IndexPatchContext.insidePointIndexDeltaToRealValue    = insideEdgePointBaseOffset;
                    m_IndexPatchContext.insidePointIndexBadValue            = numPointsForInsideEdge[parity] - 1;
                    m_IndexPatchContext.insidePointIndexReplacementValue    = edge0InsidePointBaseOffset;
                    m_IndexPatchContext.outsidePointIndexPatchBase          = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range
                    m_IndexPatchContext.outsidePointIndexDeltaToRealValue   = outsideEdgePointBaseOffset 
                                                                                - m_IndexPatchContext.outsidePointIndexPatchBase;
                    m_IndexPatchContext.outsidePointIndexBadValue           = m_IndexPatchContext.outsidePointIndexPatchBase
                                                                                + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext.outsidePointIndexReplacementValue   = edge0OutsidePointBaseOffset;

                    insideBaseOffset = 0;
                    outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase;
                    SetUsingPatchedIndices(true);
                }
            }
            else if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset;
                m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
                m_IndexPatchContext2.cornerCaseReplacementValue = -1; // unused
                m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert << 1;
                insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                outsideBaseOffset = outsideEdgePointBaseOffset;
                SetUsingPatchedIndices2(true);
            }
            else
            {
                insideBaseOffset = insideEdgePointBaseOffset;
                outsideBaseOffset = outsideEdgePointBaseOffset;
            }
            if( ring == startRing )
            {
                StitchTransition(/*baseIndexOffset: */m_NumIndices, 
                               insideBaseOffset,processedTessFactors.insideTessFactorCtx[parity].numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity[parity],
                               outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]);
            }
            else
            {
                StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED,
                              /*baseIndexOffset: */m_NumIndices,
                              numPointsForInsideEdge[parity],
                              insideBaseOffset,outsideBaseOffset);
            }
            SetUsingPatchedIndices(false);
            SetUsingPatchedIndices2(false);
            m_NumIndices += numTriangles*3;
            outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1;
            if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                insideEdgePointBaseOffset -= numPointsForInsideEdge[parity] - 1;
            }
            else
            {
                insideEdgePointBaseOffset += numPointsForInsideEdge[parity] - 1;
            }
            numPointsForOutsideEdge[edge] = numPointsForInsideEdge[parity];
        }
        if( startRing == ring )
        {
            for(edge = 0; edge < QUAD_EDGES; edge++ )
            {
                outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx[edge&1];
                outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity[edge&1];
            }
        }
    }

    // Triangulate center - a row of quads if odd
    // This triangulation may be producing diagonals that are asymmetric about 
    // the center of the patch in this region.  
    if( (processedTessFactors.numPointsForInsideTessFactor[U] > processedTessFactors.numPointsForInsideTessFactor[V]) && 
        (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[V] ) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[U]>>1) - (processedTessFactors.numPointsForInsideTessFactor[V]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 2;
        m_IndexPatchContext2.cornerCaseBadValue = m_IndexPatchContext2.baseIndexToInvert;
        m_IndexPatchContext2.cornerCaseReplacementValue = outsideEdgePointBaseOffset;
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
        StitchRegular(/*bTrapezoid*/false,DIAGONALS_INSIDE_TO_OUTSIDE,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset+1);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
    else if((processedTessFactors.numPointsForInsideTessFactor[V] >= processedTessFactors.numPointsForInsideTessFactor[U]) && 
            (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[U]) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[V]>>1) - (processedTessFactors.numPointsForInsideTessFactor[U]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 1;
        m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
		DIAGONALS diag = (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ?  
							DIAGONALS_INSIDE_TO_OUTSIDE : DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE;
        StitchRegular(/*bTrapezoid*/false,diag,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
}