Example #1
0
//-------------------------------------------------------------------------------
// @ Slerp()
//-------------------------------------------------------------------------------
// Spherical linearly interpolate two quaternions
// This will always take the shorter path between them
//-------------------------------------------------------------------------------
void 
Slerp( IvQuat& result, const IvQuat& start, const IvQuat& end, float t )
{
    // get cosine of "angle" between quaternions
    float cosTheta = start.Dot( end );
    float startInterp, endInterp;

    // if "angle" between quaternions is less than 90 degrees
    if ( cosTheta >= kEpsilon )
    {
        // if angle is greater than zero
        if ( (1.0f - cosTheta) > kEpsilon )
        {
            // use standard slerp
            float theta = acosf( cosTheta );
            float recipSinTheta = 1.0f/IvSin( theta );

            startInterp = IvSin( (1.0f - t)*theta )*recipSinTheta;
            endInterp = IvSin( t*theta )*recipSinTheta;
        }
        // angle is close to zero
        else
        {
            // use linear interpolation
            startInterp = 1.0f - t;
            endInterp = t;
        }
    }
    // otherwise, take the shorter route
    else
    {
        // if angle is less than 180 degrees
        if ( (1.0f + cosTheta) > kEpsilon )
        {
            // use slerp w/negation of start quaternion
            float theta = acosf( -cosTheta );
            float recipSinTheta = 1.0f/IvSin( theta );

            startInterp = IvSin( (t-1.0f)*theta )*recipSinTheta;
            endInterp = IvSin( t*theta )*recipSinTheta;
        }
        // angle is close to 180 degrees
        else
        {
            // use lerp w/negation of start quaternion
            startInterp = t - 1.0f;
            endInterp = t;
        }
    }
    
    result = startInterp*start + endInterp*end;

}   // End of Slerp()
Example #2
0
//-------------------------------------------------------------------------------
// @ Player::CreateCylinder()
//-------------------------------------------------------------------------------
// Create vertex arrays for a cylinder centered around the origin
//-------------------------------------------------------------------------------
void 
Player::CreateCylinder()                                    
{
    // Creates a grid of points, shaped into a cylinder.  In order to avoid a
    // texturing anomaly, we cannot simply share the vertical seam edge vertices
    // They must be duplicated; one copy must have a U-coord of 0.0, the other a
    // U-coord of 1.0f
    const unsigned int steps = 32;
    mCylinderVerts = IvRenderer::mRenderer->GetResourceManager()->CreateVertexBuffer(
        kTCPFormat, (steps + 1) * steps, nullptr, kDefaultUsage);

    IvTCPVertex* tempVerts0 = (IvTCPVertex*)(mCylinderVerts->BeginLoadData());

    // temporary pointers that can be stepped along the arrays
    const float phiIncrement = kPI / (steps - 1);
    const float thetaIncrement = kTwoPI / steps;
    unsigned int i,j;

    // A double loop, walking around and down the cylinder
    for (j = 0; j <= steps; j++)
    {
        float theta = thetaIncrement * j;
        float u = j / (float)steps;

        float sinTheta, cosTheta;
        IvSinCos(theta, sinTheta, cosTheta);

        for (i = 0; i < steps; i++)
        {
            float phi = -kHalfPI + phiIncrement * i;
            float v = i / (float)(steps - 1);

            if (i == 0)
            {
                tempVerts0->position = IvVector3(0.0f, 0.0f, -mRadius);
            }
            else if (i == (steps - 1))
            {
                tempVerts0->position = IvVector3(0.0f, 0.0f, mRadius);
            }
            else
            {
                tempVerts0->position = IvVector3(mRadius * cosTheta, mRadius * sinTheta, mRadius * IvSin(phi));
            }

            tempVerts0->texturecoord = IvVector2(u, v);

            tempVerts0->color.mAlpha = 
            tempVerts0->color.mRed = 
            tempVerts0->color.mGreen = 
            tempVerts0->color.mBlue = 255; 

            tempVerts0++;
        }
    }

    mCylinderVerts->EndLoadData();

    // Create index arrays - just a 32x31-quad mesh of triangles
    // Each of the 32 strips has 31 * 2 triangles plus two dummy indices
    // This means that there are 31 * 2 + 2 + 2 (two extra to start the
    // strip, and two extra to end the previous strip) indices in each
    // strip, although we can avoid two indices in the first strip, as
    // there is no previous strip to be ended in that case.  Thus,
    // 64 + 66 * 31 indices for the entire cylinder
    unsigned int cylinderIndexCount = steps * 2 + (steps - 1) * (steps * 2 + 2);

    mCylinderIndices = IvRenderer::mRenderer->GetResourceManager()->CreateIndexBuffer(
        cylinderIndexCount, nullptr, kDefaultUsage);

    UInt32* tempIndices = (UInt32*)mCylinderIndices->BeginLoadData();

    for (j = 0; j < steps; j++)
    {
        UInt32 baseIndex0 = steps * j;
        UInt32 baseIndex1 = steps * (j + 1);

        // restart the strip by doubling the last and next indices
        if (j != 0)
        {
            *(tempIndices++) = tempIndices[-1];
            *(tempIndices++) = baseIndex0;
        }

        unsigned int i;
        for (i = 0; i < steps; i++)
        {
            *(tempIndices++) = baseIndex0;
            *(tempIndices++) = baseIndex1;

            baseIndex0++;
            baseIndex1++;
        }
    }

    mCylinderIndices->EndLoadData();

}   // End of Player::CreateCylinder()