Esempio n. 1
0
//生成一个绕任意轴旋转的矩阵(弧度制)
void Matrix44Rotate( matrix44& mat44, float ax, float ay, float az, float angle )
{
	Matrix44Identity( mat44 );

	float sinx = sin( angle );
	float cosx = cos( angle );
	float cosx2 = 1.0f - cosx;

	float len = sqrt( ax * ax + ay * ay + az * az );

	float x = ax / len;
	float y = ay / len;
	float z = az / len;

	mat44._v1._x = x*x * cosx2 + cosx;
	mat44._v1._y = x*y * cosx2 + z * sinx;
	mat44._v1._z = x*z * cosx2 - y * sinx;

	mat44._v2._x = x*y * cosx2 - z * sinx;
	mat44._v2._y = y*y * cosx2 + cosx;
	mat44._v2._z = y*z * cosx2 + x * sinx;

	mat44._v3._x = x*z * cosx2 + y * sinx;
	mat44._v3._y = y*z * cosx2 - x * sinx;
	mat44._v3._z = z*z * cosx2 + cosx;

}
Esempio n. 2
0
//生成一个缩放矩阵
void Matrix44Scale( matrix44& mat44, float xScale, float yScale, float zScale )
{
	Matrix44Identity( mat44 );

	mat44._v1._x = xScale;
	mat44._v2._y = yScale;
	mat44._v3._z = zScale;

}
Esempio n. 3
0
//生成一个平移矩阵
void Matrix44Translate( matrix44& mat44, float x, float y, float z )
{
	Matrix44Identity( mat44 );

	mat44._v4._x = x;
	mat44._v4._y = y;
	mat44._v4._z = z;

}
Esempio n. 4
0
//生成一个绕Z轴旋转矩阵(弧度制)
void Matrix44RotateZ( matrix44& mat44, float angle )
{
	Matrix44Identity( mat44 );

	float sinx= sin( angle );
	float cosx= cos( angle );

	mat44._v1._x = cosx;
	mat44._v1._y = sinx;
	mat44._v2._x = -sinx;
	mat44._v2._y = cosx;

}
Esempio n. 5
0
//生成一个沿指定轴缩放的矩阵
void Matrix44ScaleAxis( matrix44& mat44, const vertex3& axis, float scale )
{
	Matrix44Identity( mat44 );

	float kone = scale - 1;
	float xy = axis._x * axis._y;
	float xz = axis._x * axis._z;
	float yz = axis._y * axis._z;

	mat44._v1 = Vertex4( 1 + kone * axis._x*axis._x, kone * xy, kone * xz, 0 );
	mat44._v2 = Vertex4( mat44._v1._y, 1 + kone * axis._y*axis._y, kone * yz, 0 );
	mat44._v3 = Vertex4( mat44._v1._z, mat44._v2._z, 1 + kone * axis._z*axis._z, 0 );

}
Esempio n. 6
0
//-----------------------------------------------------------------------------
// Проверка столкновений Sphere-Mesh
//-----------------------------------------------------------------------------
bool vw_SphereMeshCollision(VECTOR3D Object1Location, eObjectBlock *Object1DrawObjectList, float Object1RotationMatrix[9],
							float Object2Radius, VECTOR3D Object2Location, VECTOR3D Object2PrevLocation,
							VECTOR3D *CollisionLocation)
{
	// если не передали геометрию - делать тут нечего
	if (Object1DrawObjectList == 0) return false;


	// делаем матрицу перемещения точек, для геометрии
	float TransMat[16];
	TransMat[0] = Object1RotationMatrix[0];
	TransMat[1] = Object1RotationMatrix[1];
	TransMat[2] = Object1RotationMatrix[2];
	TransMat[3] = 0.0f;
	TransMat[4] = Object1RotationMatrix[3];
	TransMat[5] = Object1RotationMatrix[4];
	TransMat[6] = Object1RotationMatrix[5];
	TransMat[7] = 0.0f;
	TransMat[8] = Object1RotationMatrix[6];
	TransMat[9] = Object1RotationMatrix[7];
	TransMat[10] = Object1RotationMatrix[8];
	TransMat[11] = 0.0f;
	TransMat[12] = Object1Location.x;
	TransMat[13] = Object1Location.y;
	TransMat[14] = Object1Location.z;
	TransMat[15] = 1.0f;


	// находим точку локального положения объекта в моделе
	VECTOR3D LocalLocation(Object1DrawObjectList->Location);
	Matrix33CalcPoint(&LocalLocation, Object1RotationMatrix);


	// если нужно - создаем матрицу, иначе - копируем ее
	if (Object1DrawObjectList->Rotation.x != 0.0f ||
		Object1DrawObjectList->Rotation.y != 0.0f ||
		Object1DrawObjectList->Rotation.z != 0.0f)
	{
		float TransMatTMP[16];
		Matrix44Identity(TransMatTMP);
		Matrix44CreateRotate(TransMatTMP, Object1DrawObjectList->Rotation);
		Matrix44Translate(TransMatTMP, LocalLocation);
		// и умножаем на основную матрицу, со сведениями по всему объекту
		Matrix44Mult(TransMat, TransMatTMP);
	}
	else
	{
		Matrix44Translate(TransMat, LocalLocation);
	}



	// проверяем все треугольники объекта
	for (int i=0; i<Object1DrawObjectList->VertexCount; i+=3)
	{
		// находим 3 точки треугольника (с учетом индекс буфера)

		int j2;
		if (Object1DrawObjectList->IndexBuffer != 0)
			j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i]*Object1DrawObjectList->VertexStride;
		else
			j2 = (Object1DrawObjectList->RangeStart+i)*Object1DrawObjectList->VertexStride;

		// находим точки триугольника
		VECTOR3D Point1;
		Point1.x = Object1DrawObjectList->VertexBuffer[j2];
		Point1.y = Object1DrawObjectList->VertexBuffer[j2+1];
		Point1.z = Object1DrawObjectList->VertexBuffer[j2+2];
		Matrix44CalcPoint(&Point1, TransMat);

		if (Object1DrawObjectList->IndexBuffer != 0)
			j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i+1]*Object1DrawObjectList->VertexStride;
		else
			j2 = (Object1DrawObjectList->RangeStart+i+1)*Object1DrawObjectList->VertexStride;

		VECTOR3D Point2;
		Point2.x = Object1DrawObjectList->VertexBuffer[j2];
		Point2.y = Object1DrawObjectList->VertexBuffer[j2+1];
		Point2.z = Object1DrawObjectList->VertexBuffer[j2+2];
		Matrix44CalcPoint(&Point2, TransMat);

		if (Object1DrawObjectList->IndexBuffer != 0)
			j2 = Object1DrawObjectList->IndexBuffer[Object1DrawObjectList->RangeStart+i+2]*Object1DrawObjectList->VertexStride;
		else
			j2 = (Object1DrawObjectList->RangeStart+i+2)*Object1DrawObjectList->VertexStride;

		VECTOR3D Point3;
		Point3.x = Object1DrawObjectList->VertexBuffer[j2];
		Point3.y = Object1DrawObjectList->VertexBuffer[j2+1];
		Point3.z = Object1DrawObjectList->VertexBuffer[j2+2];
		Matrix44CalcPoint(&Point3, TransMat);



		// находим 2 вектора, образующих плоскость
		VECTOR3D PlaneVector1 = Point2 - Point1;
		VECTOR3D PlaneVector2 = Point3 - Point1;

		// находим нормаль плоскости
		VECTOR3D NormalVector = PlaneVector1;
		NormalVector.Multiply(PlaneVector2);
		NormalVector.Normalize();



	// проверка, сферы
	//	- в сфере или нет?, т.е. расстояние от плоскости до центра сферы
	//	- по нормале находим точку на плоскости
	//	- точка принадлежит треугольнику?


		// находим расстояние от точки до плоскости
		float Distance = (Object2Location - Point1)*NormalVector;

		// если точка дальше радиуса - нам тут делать нечего, берем следующую точку
		if (fabsf(Distance) <= Object2Radius)
		{
			// находим реальную точку пересечения с плоскостью
			VECTOR3D IntercPoint = Object2Location - (NormalVector^Distance);

			// передаем точку и флаг успешной коллизии
			if (vw_PointInTriangle(IntercPoint, Point1, Point2, Point3))
			{
				*CollisionLocation = IntercPoint;
				return true;
			}
		}




	// проверка, сферы
	// если от точек до текущего положения расстояние меньше

		float Object2Radius2 = Object2Radius*Object2Radius;

		// находим расстояние
		VECTOR3D DistancePoint1 = Object2Location - Point1;
		float Distance2Point1 = DistancePoint1.x*DistancePoint1.x + DistancePoint1.y*DistancePoint1.y + DistancePoint1.z*DistancePoint1.z;
		if (Distance2Point1 <= Object2Radius2)
		{
			*CollisionLocation = Point1;
			return true;
		}

		// находим расстояние
		VECTOR3D DistancePoint2 = Object2Location - Point2;
		float Distance2Point2 = DistancePoint2.x*DistancePoint2.x + DistancePoint2.y*DistancePoint2.y + DistancePoint2.z*DistancePoint2.z;
		if (Distance2Point2 <= Object2Radius2)
		{
			*CollisionLocation = Point2;
			return true;
		}

		// находим расстояние
		VECTOR3D DistancePoint3 = Object2Location - Point3;
		float Distance2Point3 = DistancePoint3.x*DistancePoint3.x + DistancePoint3.y*DistancePoint3.y + DistancePoint3.z*DistancePoint3.z;
		if (Distance2Point3 <= Object2Radius2)
		{
			*CollisionLocation = Point3;
			return true;
		}



	// проверка луч, старое положение - новое положение объекта
	//	- пересекает плоскость (обе точки с одной стороны? знак, или ноль)
	//	- точка пересечения плоскости
	//	- принадлежит треугольнику?


		// проверка, если это фронт-часть, нормально... иначе - берем следующую
		VECTOR3D vDir1 = Point1 - Object2PrevLocation;
		float d1 = vDir1*NormalVector;
		if (d1>0.001f) continue;

		// находим расстояние от плоскости до точки
		float originDistance = NormalVector*Point1;

		// пересечение прямой с плоскостью
		VECTOR3D vLineDir = Object2Location - Object2PrevLocation;
		// может и не нужно этого делать... т.к. все и так хорошо работает в нашем случае
		//vLineDir.Normalize();

		float Numerator = - (NormalVector.x * Object2PrevLocation.x +		// Use the plane equation with the normal and the line
				   NormalVector.y * Object2PrevLocation.y +
				   NormalVector.z * Object2PrevLocation.z - originDistance);

		float Denominator = NormalVector*vLineDir;
		if( Denominator == 0.0) continue;

		float dist = Numerator / Denominator;

		// зная расстояние, находим точку пересечения с плоскостью
		VECTOR3D IntercPoint = Object2PrevLocation + (vLineDir ^ dist);


		// проверяем, на отрезке или нет (до этого работали с прямой/лучем)
		if ((Object2PrevLocation-IntercPoint)*(Object2Location-IntercPoint) >= 0.0f) continue;

		// передаем точку и флаг успешной коллизии
		if (vw_PointInTriangle(IntercPoint, Point1, Point2, Point3))
		{
			*CollisionLocation = IntercPoint;
			return true;
		}
	}


	return false;
}
Esempio n. 7
0
void gamerRenderInitAllObjects( tAnimModel const* pAnimModel,
                                tAnimSequence* pAnimSequence,
                                tAnimHierarchy const* pAnimHierarchy )
{
    const float fStartingPosRadius = 5.0f;
    
    Matrix44Identity( &gIdentityMat );
    
    siNumRenderObjects = 1;
    
    saRenderObjects = sGameRenderObjectFactory.alloc( siNumRenderObjects );
    saAnimModelInstances = sAnimModelInstanceFactory.alloc( siNumRenderObjects );
    saObjectInfo = sVectorFactory.alloc( siNumRenderObjects * 3 );
    saAnimHierarchies = sAnimHierarchyFactory.alloc( siNumRenderObjects );
    
    memset( saObjectInfo, 0, sizeof( tVector4 ) * siNumRenderObjects * 3 );
    
    float fAnglePart = ( 2.0f * 3.14159f ) / (float)siNumRenderObjects;
    
    int iCount = 0;
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        // animation model instance
        tAnimModelInstance* pAnimModelInstance = &saAnimModelInstances[i];
        animModelInstanceInit( pAnimModelInstance );
        animModelInstanceSet( pAnimModelInstance, pAnimModel );
        animModelInstanceSetupGL( pAnimModelInstance );
        
        tGameRenderObject* pRenderObject = &saRenderObjects[i];
        pRenderObject->miType = RENDEROBJECT_ANIMMODEL;
        
        pRenderObject->mpAnimModelInstance = &saAnimModelInstances[i];
        
        // position, heading and speed
        pRenderObject->mpPosition = &saObjectInfo[iCount++];
        pRenderObject->mpSize = &saObjectInfo[iCount++];
        pRenderObject->mpHeading = &saObjectInfo[iCount++];
        pRenderObject->mfSpeed = 0.0f;
    
        pRenderObject->mpPosition->fW = 1.0f;
        pRenderObject->mpSize->fW = 1.0f;
        pRenderObject->mpHeading->fW = 1.0f;
        
        // heading
        tVector4 xVec = { 1.0f, 0.0f, 0.0f, 1.0f };
        tMatrix44 rotMatY;
        Matrix44RotateY( &rotMatY, fAnglePart * (float)i );
        Matrix44Transform( pRenderObject->mpHeading, &xVec, &rotMatY );
        Vector4Normalize( pRenderObject->mpHeading, pRenderObject->mpHeading );
        
        // position
        pRenderObject->mpPosition->fX = pRenderObject->mpHeading->fX * fStartingPosRadius - 15.0f;
        pRenderObject->mpPosition->fZ = pRenderObject->mpHeading->fZ * fStartingPosRadius;
        
        pRenderObject->mfAnimMult = 0.5f + (float)( rand() % 500 ) * 0.001f;
        
        pRenderObject->mfSpeed = pRenderObject->mfAnimMult;
        pRenderObject->mfSpeed *= 0.01f;
        
        pRenderObject->mpSize->fX = 1.5f;
        pRenderObject->mpSize->fY = 1.5f;
        pRenderObject->mpSize->fZ = 1.5f;
        
        // duplicate of the hierarchy for storing skin matrices
        animHierarchyCopy( &saAnimHierarchies[i],
                           pAnimHierarchy,
                           &gJointFactory,
                           &gMatrixFactory );
        
        // use this hierarchy for this model instance
        pAnimModelInstance->mpAnimHierarchy = &saAnimHierarchies[i];
        pAnimModelInstance->mpAnimModel = pAnimModel;
        
        pAnimModelInstance->maRotations = (tVector4 *)malloc( sizeof( tVector4 ) );
        pAnimModelInstance->maPositions = (tVector4 *)malloc( sizeof( tVector4 ) );
        pAnimModelInstance->maScalings = (tVector4 *)malloc( sizeof( tVector4 ) );
        pAnimModelInstance->maRotatePivot = (tVector4 *)malloc( sizeof( tVector4 ) );
        pAnimModelInstance->maScalePivot = (tVector4 *)malloc( sizeof( tVector4 ) );
        
        //memcpy( pAnimModelInstance->maRotatePivot, &pAnimModel->mCenter, sizeof( tVector4 ) );
        //memcpy( pAnimModelInstance->maScalePivot, &pAnimModel->mCenter, sizeof( tVector4 ) );
        
        memset( pAnimModelInstance->maRotatePivot, 0, sizeof( tVector4 ) );
        memset( pAnimModelInstance->maScalePivot, 0, sizeof( tVector4 ) );
        
        pAnimModelInstance->miNumXForms = 1;
    }

    spAnimSequence = pAnimSequence;
}
Esempio n. 8
0
void gamerRenderUpdateAllObjects( float fTime )
{
    double fElapsed4 = 0.0f;
    double fElapsed6 = 0.0f;
    
    double fElapsed7 = 0.0f;
    double fElapsed8 = 0.0f;
    double fElapsed9 = 0.0f;
    double fElapsed10 = 0.0f;
    
    double fStart, fEnd;
    
    double fPartStart, fPartEnd;
    
    int iNumJoints = saAnimHierarchies[0].miNumJoints;
    
    /*tVector4* aPositions = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
    tVector4* aScalings = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
    tQuaternion* aRotations = (tQuaternion *)malloc( sizeof( tQuaternion ) * iNumJoints );
    tVector4* aRotationVecs = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
    tMatrix44* aAnimMatrices = (tMatrix44 *)malloc( sizeof( tMatrix44 ) * iNumJoints );
    */
    
    // allocate for all the objects and their joints
    tVector4** aaPositions = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects );
    tVector4** aaScalings = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects );
    tQuaternion** aaRotations = (tQuaternion **)malloc( sizeof( tQuaternion* ) * siNumRenderObjects );
    tVector4** aaRotationVecs = (tVector4 **)malloc( sizeof( tVector4* ) * siNumRenderObjects );
    tMatrix44** aaAnimMatrices = (tMatrix44 **)malloc( sizeof( tMatrix44* ) * siNumRenderObjects );
    
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        aaPositions[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
        aaScalings[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
        aaRotations[i] = (tQuaternion *)malloc( sizeof( tQuaternion ) * iNumJoints );
        aaRotationVecs[i] = (tVector4 *)malloc( sizeof( tVector4 ) * iNumJoints );
        aaAnimMatrices[i] = (tMatrix44 *)malloc( sizeof( tMatrix44 ) * iNumJoints );
    
        for( int j = 0; j < iNumJoints; j++ )
        {
            Matrix44Identity( &aaAnimMatrices[i][j] );
        }
    }
    
    /*for( int i = 0; i < iNumJoints; i++ )
    {
        Matrix44Identity( &aAnimMatrices[i] );
    }*/
    
    fPartStart = getTime();
    
#if 0
    // update anim model instances' transform
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        fStart = getTime();
        
        //animSequencePlay( spAnimSequence, aPositions, aScalings, aRotations, aRotationVecs, aAnimMatrices, sfTime );
        
        tGameRenderObject* pGameRenderObject = &saRenderObjects[i];
        tAnimModelInstance* pAnimModelInstance = pGameRenderObject->mpAnimModelInstance;
        
        // y rotation angle
        float fAngle = atan2f( pGameRenderObject->mpHeading->fZ, pGameRenderObject->mpHeading->fX ) - 3.14159f * 0.5f;
        pAnimModelInstance->mRotation.fY = fAngle;
        
        // update position
        tVector4 dPos;
        Vector4MultScalar( &dPos, pGameRenderObject->mpHeading, pGameRenderObject->mfSpeed );
        
        tVector4* pPos = pGameRenderObject->mpPosition;
        tVector4 newPos;
        Vector4Add( &newPos, pPos, &dPos );
        
        memcpy( pGameRenderObject->mpPosition, &newPos, sizeof( tVector4 ) );
        
        memcpy( &pAnimModelInstance->mPosition, &newPos, sizeof( tVector4 ) );
        memcpy( &pAnimModelInstance->mScaling, pGameRenderObject->mpSize, sizeof( tVector4 ) );
    
        fEnd = getTime();
        fElapsed0 += ( fEnd - fStart );
    }
#endif // #if 0
    
    fPartEnd = getTime();
    fElapsed7 = fPartEnd - fPartEnd;
    fPartStart = fPartEnd;
    
    tVector4** paPositions = aaPositions;
    tVector4** paScalings = aaScalings;
    tVector4** paRotationVecs = aaRotationVecs;
    tQuaternion** paRotations = aaRotations;
    tMatrix44** paAnimMatrices = aaAnimMatrices;
    
    // update joint in hierarchy matrices
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        tJob job;
        tJointJobData jobData;
        jobData.mpSequence = spAnimSequence;
        jobData.mpHierarchy = &saAnimHierarchies[0];
        jobData.maPositions = *paPositions; //aPositions;
        jobData.maScalings = *paScalings; //aScalings;
        jobData.maRotations = *paRotations; //aRotations;
        jobData.maRotationVecs = *paRotationVecs; //aRotationVecs;
        jobData.mfTime = fTime * saRenderObjects[i].mfAnimMult;
        jobData.maAnimMatrices = *paAnimMatrices; //aAnimMatrices;
        
        jobData.mpResultAnimHiearchy = &saAnimHierarchies[i];
        
        job.mpfnFunc = updateJointValuesAndMatrices;
        job.miDataSize = sizeof( tJointJobData );
        job.mpData = &jobData;
        
        jobManagerAddJob( gpJobManager, &job );
        
        ++paPositions;
        ++paScalings;
        ++paRotations;
        ++paRotationVecs;
        ++paAnimMatrices;
        
    }   // for i = 0 to num render objects
    
    jobManagerWait( gpJobManager );
    
    
    // update all the joint's matrices
    /*for( int i = 0; i < siNumRenderObjects; i++ )
    {
        fStart = getTime();
        animSequenceUpdateJointAnimValues( spAnimSequence,
                                          &saAnimHierarchies[0],
                                          aaPositions[i],
                                          aaScalings[i],
                                          aaRotations[i],
                                          aaRotationVecs[i],
                                          fTime * saRenderObjects[i].mfAnimMult );
        
        jobManagerWait( gpJobManager );
        
        fEnd = getTime();
        fElapsed1 += ( fEnd - fStart );
        fStart = fEnd;
        
        animSequenceUpdateAnimMatrices( spAnimSequence,
                                       &saAnimHierarchies[0],
                                       aaPositions[i],
                                       aaScalings[i],
                                       aaRotations[i],
                                       aaRotationVecs[i],
                                       aaAnimMatrices[i] );
        
        jobManagerWait( gpJobManager );
        
        fElapsed2 += ( fEnd - fStart );
        fStart = fEnd;
        
        updateJointMatrices( &saAnimHierarchies[i], aaAnimMatrices[i] );
        jobManagerWait( gpJobManager );
        
        fElapsed3 += ( fEnd - fStart );
        fStart = fEnd;
    }
    
    jobManagerWait( gpJobManager );
    */
    
    fPartEnd = getTime();
    fElapsed8 = fPartEnd - fPartStart;
    
    // update the xform of the total model
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        animModelInstanceUpdateXForm( &saAnimModelInstances[i] );
    }
    
    // transform position and normal
    fPartStart = getTime();
    
    fStart = getTime();
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        animModelInstanceUpdate( &saAnimModelInstances[i] );
    }
    
    jobManagerWait( gpJobManager );
    
    fEnd = getTime();
    fElapsed4 += ( fEnd - fStart );
    fStart = fEnd;
    
    fPartEnd = getTime();
    fElapsed9 = fPartEnd - fPartStart;
    
    WTFASSERT2( fPartEnd >= fPartStart, "WTF" );
    
    fStart = getTime();
    
    // TODO: OPTIMIZE COPY VB DATA
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        animModelInstanceCopyVBData( &saAnimModelInstances[i] );
    }
    
    fEnd = getTime();
    fElapsed6 = fEnd - fStart;
    
    fPartEnd = getTime();
    fElapsed10 = fPartEnd - fPartStart;
    fPartStart = fPartEnd;
    
#if 0
    OUTPUT( "********************\n" );
    OUTPUT( "elapsed 0 = %.4f\n", fElapsed0 );
    OUTPUT( "elapsed 1 = %.4f\n", fElapsed1 );
    OUTPUT( "elapsed 2 = %.4f\n", fElapsed2 );
    OUTPUT( "elapsed 3 = %.4f\n", fElapsed3 );
    OUTPUT( "elapsed 4 = %.4f\n", fElapsed4 );
    OUTPUT( "elapsed 5 = %.4f\n", fElapsed5 );
    OUTPUT( "elapsed 6 = %.4f\n", fElapsed6 );
    OUTPUT( "elapsed 7 = %.4f\n", fElapsed7 );
    OUTPUT( "elapsed 8 = %.4f\n", fElapsed8 );
    OUTPUT( "elapsed 9 = %.4f\n", fElapsed9 );
    OUTPUT( "elapsed 10 = %.4f\n", fElapsed10 );
    OUTPUT( "total elapsed = %.4f\n", fTotalElapsed );
    OUTPUT( "********************\n" );
#endif // #if 0
    
    /*free( aPositions );
    free( aScalings );
    free( aRotations );
    free( aRotationVecs );
    free( aAnimMatrices );*/
    
    for( int i = 0; i < siNumRenderObjects; i++ )
    {
        free( aaPositions[i] );
        free( aaScalings[i] );
        free( aaRotations[i] );
        free( aaRotationVecs[i] );
        free( aaAnimMatrices[i] );
    }
    
    free( aaPositions );
    free( aaScalings );
    free( aaRotations );
    free( aaRotationVecs );
    free( aaAnimMatrices );
}