void CHWTessellator::TriGeneratePoints()

in d3d/archive/images/d3d11/tessellator.cpp [1192:1285]


void CHWTessellator::TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors )
{
    // Generate exterior ring edge points, clockwise starting from point V (VW, the U==0 edge)
    int pointOffset = 0;
    int edge;
    for(edge = 0; edge < TRI_EDGES; edge++ )
    {
        int parity = edge&0x1;
        int startPoint = 0;
        int endPoint = processedTessFactors.numPointsForOutsideEdge[edge] - 1;
        for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end, since next edge starts with it.
        {
            FXP fxpParam;
            int q = (parity) ? p : endPoint - p; // whether to reverse point order given we are defining V or U (W implicit):
                                                 // edge0, VW, has V decreasing, so reverse 1D points below
                                                 // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                 // edge2, UV, has U decreasing, so reverse 1D points below
            SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]);
            PlacePointIn1D(processedTessFactors.outsideTessFactorCtx[edge],q,fxpParam);
            if( edge == 0 )
            {
                DefinePoint(/*U*/0,
                            /*V*/fxpParam,
                            /*pointStorageOffset*/pointOffset);
            }
            else
            {
                DefinePoint(/*U*/fxpParam,
                            /*V*/(edge == 2) ? FXP_ONE - fxpParam : 0,
                            /*pointStorageOffset*/pointOffset);
            }
        }
    }

    // Generate interior ring points, clockwise spiralling in
    SetTessellationParity(processedTessFactors.insideTessFactorParity);
    static const int startRing = 1;
    int numRings = (processedTessFactors.numPointsForInsideTessFactor >> 1);
    for(int ring = startRing; ring < numRings; ring++)
    {
        int startPoint = ring;
        int endPoint = processedTessFactors.numPointsForInsideTessFactor - 1 - startPoint;

        for(edge = 0; edge < TRI_EDGES; edge++ )
        {
            int parity = edge&0x1;
            int perpendicularAxisPoint = startPoint;
            FXP fxpPerpParam;
            PlacePointIn1D(processedTessFactors.insideTessFactorCtx,perpendicularAxisPoint,fxpPerpParam);
            fxpPerpParam *= FXP_TWO_THIRDS; // Map location to the right size in barycentric space.
                                         // I (amarp) can draw a picture to explain.
                                         // We know this fixed point math won't over/underflow
            fxpPerpParam = (fxpPerpParam+FXP_ONE_HALF/*round*/)>>FXP_FRACTION_BITS; // get back to n.16
            for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end: next edge starts with it. 
            {
                FXP fxpParam;
                int q = (parity) ? p : endPoint - (p - startPoint); // whether to reverse point given we are defining V or U (W implicit):
                                                         // edge0, VW, has V decreasing, so reverse 1D points below
                                                         // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                         // edge2, UV, has U decreasing, so reverse 1D points below
                PlacePointIn1D(processedTessFactors.insideTessFactorCtx,q,fxpParam);
                // edge0 VW, has perpendicular parameter U constant
                // edge1 WU, has perpendicular parameter V constant
                // edge2 UV, has perpendicular parameter W constant 
                const unsigned int deriv = 2; // reciprocal is the rate of change of edge-parallel parameters as they are pushed into the triangle
                switch(edge)
                {
                case 0:
                    DefinePoint(/*U*/fxpPerpParam,
                                /*V*/fxpParam - (fxpPerpParam+1/*round*/)/deriv, // we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 1:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/fxpPerpParam,
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 2:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/FXP_ONE - (fxpParam - (fxpPerpParam+1/*round*/)/deriv) - fxpPerpParam,// we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                }
            }
        }
    }
    if( !Odd() )
    {
        // Last point is the point at the center.
        DefinePoint(/*U*/FXP_ONE_THIRD,
                    /*V*/FXP_ONE_THIRD,
                    /*pointStorageOffset*/pointOffset);
    }
}