void CHLSLTessellator::QuadHLSLProcessTessFactors()

in d3d/archive/images/d3d11/tessellator.cpp [2179:2412]


void CHLSLTessellator::QuadHLSLProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1, 
                                               float insideTessFactorScaleU, float insideTessFactorScaleV )
{
    if( !(tessFactor_Ueq0 > 0) ||// NaN will pass
        !(tessFactor_Veq0 > 0) || 
        !(tessFactor_Ueq1 > 0) ||
        !(tessFactor_Veq1 > 0) )
    {
        m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0;
        m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0;
        m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1;
        m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1;
        m_LastUnRoundedComputedTessFactors[4] = 0;
        m_LastUnRoundedComputedTessFactors[5] = 0;
        m_LastComputedTessFactors[0] = 
        m_LastComputedTessFactors[1] = 
        m_LastComputedTessFactors[2] = 
        m_LastComputedTessFactors[3] = 
        m_LastComputedTessFactors[4] = 
        m_LastComputedTessFactors[5] = 0;
        return;
    }

    CleanupFloatTessFactor(tessFactor_Ueq0);// clamp to [1.0f..INF], NaN->1.0f
    CleanupFloatTessFactor(tessFactor_Veq0); 
    CleanupFloatTessFactor(tessFactor_Ueq1);
    CleanupFloatTessFactor(tessFactor_Veq1);

    // Save off tessFactors so they can be returned to app
    m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0;
    m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0;
    m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1;
    m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1;

    // Process outside tessFactors
    float outsideTessFactor[QUAD_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Ueq1, tessFactor_Veq1};
    int edge, axis;
    TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES], outsideTessFactorParity[QUAD_EDGES];
    if( Pow2Partitioning() || IntegerPartitioning() )
    {
        for( edge = 0; edge < QUAD_EDGES; edge++ )
        {
            RoundUpTessFactor(outsideTessFactor[edge]);
            ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode
            int edgeEven = isEven(outsideTessFactor[edge]);
            outsideTessFactorParity[edge] = edgeEven ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
        }
    }
    else
    {
        SetTessellationParity(m_originalParity); // ClampTessFactor needs it
        for( edge = 0; edge < QUAD_EDGES; edge++ )
        {
            ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode
            outsideTessFactorParity[edge] = m_originalParity;
        }
    }
    
    // Compute inside TessFactors
    float insideTessFactor[QUAD_AXES];
    if( m_quadInsideTessFactorReductionAxis == D3D11_TESSELLATOR_QUAD_REDUCTION_1_AXIS )
    {
        switch( m_insideTessFactorReduction )
        {
        case D3D11_TESSELLATOR_REDUCTION_MIN:
            insideTessFactor[U] = fmin(fmin(tessFactor_Veq0,tessFactor_Veq1),fmin(tessFactor_Ueq0,tessFactor_Ueq1));
            break;
        case D3D11_TESSELLATOR_REDUCTION_MAX:
            insideTessFactor[U] = fmax(fmax(tessFactor_Veq0,tessFactor_Veq1),fmax(tessFactor_Ueq0,tessFactor_Ueq1));
            break;
        case D3D11_TESSELLATOR_REDUCTION_AVERAGE:
            insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4;
            break;
        }
        // Scale inside tessFactor based on user scale factor.

        ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0
        insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU;

        // Compute inside parity
        if( Pow2Partitioning() || IntegerPartitioning() )
        {
            ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
            RoundUpTessFactor(insideTessFactor[U]);
            insideTessFactorParity[U] = 
            insideTessFactorParity[V] = 
                (isEven(insideTessFactor[U]) || (FLOAT_ONE == insideTessFactor[U]) )
                ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
        }
        else
        {
            ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
            // no parity changes for fractional tessellation - just use what the user requested
            insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity;
        }

        // To prevent snapping on edges, the "picture frame" comes
        // in using avg or max (and ignore inside TessFactor scaling) until it is at least 3.
        if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) &&
            (insideTessFactor[U] < FLOAT_THREE) )
        {
            if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
            {
                insideTessFactor[U] = fmin(FLOAT_THREE,fmax(fmax(tessFactor_Veq0,tessFactor_Veq1),fmax(tessFactor_Ueq0,tessFactor_Ueq1)));
            }
            else
            {
                insideTessFactor[U] = fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4);
            }
            ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
            if( IntegerPartitioning())
            {
                RoundUpTessFactor(insideTessFactor[U]);
                insideTessFactorParity[U] = 
                insideTessFactorParity[V] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
            }
        }
        insideTessFactor[V] = insideTessFactor[U];
    }
    else
    {
        switch( m_insideTessFactorReduction )
        {
        case D3D11_TESSELLATOR_REDUCTION_MIN:
            insideTessFactor[U] = fmin(tessFactor_Veq0,tessFactor_Veq1);
            insideTessFactor[V] = fmin(tessFactor_Ueq0,tessFactor_Ueq1);
            break;
        case D3D11_TESSELLATOR_REDUCTION_MAX:
            insideTessFactor[U] = fmax(tessFactor_Veq0,tessFactor_Veq1);
            insideTessFactor[V] = fmax(tessFactor_Ueq0,tessFactor_Ueq1);
            break;
        case D3D11_TESSELLATOR_REDUCTION_AVERAGE:
            insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1) / 2;
            insideTessFactor[V] = (tessFactor_Ueq0 + tessFactor_Ueq1) / 2;
            break;
        }
        // Scale inside tessFactors based on user scale factor.

        ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0
        ClampFloatTessFactorScale(insideTessFactorScaleV);
        insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU;
        insideTessFactor[V] = insideTessFactor[V]*insideTessFactorScaleV;

        // Compute inside parity
        if( Pow2Partitioning() || IntegerPartitioning() )
        {
            for( axis = 0; axis < QUAD_AXES; axis++ )
            {
                ClampTessFactor(insideTessFactor[axis]); // clamp reduction + scale result that is based on unbounded user input
                m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app
                RoundUpTessFactor(insideTessFactor[axis]);
                insideTessFactorParity[axis] = 
                    (isEven(insideTessFactor[axis]) || (FLOAT_ONE == insideTessFactor[axis]) )
                    ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
            }
        }
        else
        {
            ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
            ClampTessFactor(insideTessFactor[V]); // clamp reduction + scale result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
            m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app
             // no parity changes for fractional tessellation - just use what the user requested
            insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity;
        }

        // To prevent snapping on edges, the "picture frame" comes
        // in using avg or max (and ignore inside TessFactor scaling) until it is at least 3.
        if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) &&
            (insideTessFactor[U] < FLOAT_THREE) )
        {
            if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
            {
                insideTessFactor[U] = fmin(FLOAT_THREE,fmax(tessFactor_Veq0,tessFactor_Veq1));
            }
            else
            {
                insideTessFactor[U] = fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1) / 2);
            }
            ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
            if( IntegerPartitioning())
            {
                RoundUpTessFactor(insideTessFactor[U]);
                insideTessFactorParity[U] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
            }
        }

        if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[V]) &&
            (insideTessFactor[V] < FLOAT_THREE) )
        {
            if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
            {
                insideTessFactor[V] = fmin(FLOAT_THREE,fmax(tessFactor_Ueq0,tessFactor_Ueq1));
            }
            else
            {
                insideTessFactor[V] = fmin(FLOAT_THREE,(tessFactor_Ueq0 + tessFactor_Ueq1) / 2);
            }
            ClampTessFactor(insideTessFactor[V]);// clamp reduction result that is based on unbounded user input
            m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app
            if( IntegerPartitioning())
            {
                RoundUpTessFactor(insideTessFactor[V]);
                insideTessFactorParity[V] = isEven(insideTessFactor[V]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
            }
        }

        for( axis = 0; axis < QUAD_AXES; axis++ )
        {
            if( TESSELLATOR_PARITY_ODD == insideTessFactorParity[axis] )
            {
                // Ensure the first ring ("picture frame") interpolates in on all sides
                // as much as the side with the minimum TessFactor.  Prevents snapping to edge. 
                if( (insideTessFactor[axis] < FLOAT_THREE) && (insideTessFactor[axis] < insideTessFactor[(axis+1)&0x1]))
                {
                    insideTessFactor[axis] = fmin(insideTessFactor[(axis+1)&0x1],FLOAT_THREE);
                    m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app
                }
            }
        }
    }

    // Save off TessFactors so they can be returned to app
    m_LastComputedTessFactors[0] = outsideTessFactor[Ueq0];
    m_LastComputedTessFactors[1] = outsideTessFactor[Veq0];
    m_LastComputedTessFactors[2] = outsideTessFactor[Ueq1];
    m_LastComputedTessFactors[3] = outsideTessFactor[Veq1];
    m_LastComputedTessFactors[4] = insideTessFactor[U];
    m_LastComputedTessFactors[5] = insideTessFactor[V];
}