dinsdag 8 oktober 2019

Snellere atan2

float Globals::ApproxAtan2(float y, float x)
{
    const float n1 = 0.97239411f;
    const float n2 = -0.19194795f;
    float result = 0.0f;
    if (x != 0.0f)
    {
        const union { float flVal; Uint32 nVal; } tYSign = { y };
        const union { float flVal; Uint32 nVal; } tXSign = { x };
        if (fabsf(x) >= fabsf(y))
        {
            union { float flVal; Uint32 nVal; } tOffset = { PI_FLOAT };
            // Add or subtract PI based on y's sign.
            tOffset.nVal |= tYSign.nVal & 0x80000000u;
            // No offset if x is positive, so multiby 0 or based on x's sign.
            tOffset.nVal *= tXSign.nVal >> 31;
            result = tOffset.flVal;
            const float z = y / x;
            result += (n1 + n2 * z * z) * z;
        }
        else // Use atan(y/x) = pi/2 - atan(x/y) if |y/x| > 1.
        {
            union { float flVal; Uint32 nVal; } tOffset = { PI_2_FLOAT };
            // Add or subtract PI/2 based on y's sign.
            tOffset.nVal |= tYSign.nVal & 0x80000000u;
            result = tOffset.flVal;
            const float z = x / y;
            result -= (n1 + n2 * z * z) * z;
        }
    }
    else if (y > 0.0f)
    {
        result = PI_2_FLOAT;
    }
    else if (y < 0.0f)
    {
        result = -PI_2_FLOAT;
    }
    return result;
}

Geen opmerkingen:

Een reactie posten