Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Using Quaternions Efficiently in Real-time Applications

, 10 Nov 2010 CPOL
Various methods for using quaternions in ways that maximize performance
// QuatDemoCode.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "conio.h"

#include "SlowGameEntity.h"
#include "FastGameEntity.h"

#include "Node.h"
#include "SlowCacheObject.h"
#include "FastCacheObject.h"


template< class T >
void updateAllEntitysAI( std::vector<T> &entities )
{
    std::vector<T>::iterator cur = entities.begin();
    std::vector<T>::iterator end = entities.end();
    for(; cur != end; cur++ )
        (*cur).updateAI();
}

void testSlowGameEntities( std::vector<SlowGameEntity> &slowGameEntities )
{
    updateAllEntitysAI<SlowGameEntity>( slowGameEntities );
}
void testFastGameEntities( std::vector<FastGameEntity> &fastGameEntities )
{
    updateAllEntitysAI<FastGameEntity>( fastGameEntities );
}

template< class T >
void calcAllEntitysOrientation( std::vector<T> &entities )
{
    std::vector<T>::iterator cur = entities.begin();
    std::vector<T>::iterator end = entities.end();
    for(; cur != end; cur++ )
        (*cur).calculateOrientation( 1.0f );
}
void testSlowGameEntitysCalcOri( std::vector<SlowGameEntity> &slowGameEntities )
{
    calcAllEntitysOrientation<SlowGameEntity>( slowGameEntities );
}
void testFastGameEntitysCalcOri( std::vector<FastGameEntity> &fastGameEntities )
{
    calcAllEntitysOrientation<FastGameEntity>( fastGameEntities );
}

typedef FastCacheObject::Transforms TransformsType;
typedef Node< FastCacheObject > FastCacheNode;

void updateWorldTransforms( FastCacheNode **parent, TransformsType **transforms, unsigned int size )
{
    for (unsigned int j=0; j<size; j++)
    {
        unsigned int innerSize = (*parent)->getNumObjects();
        const D3DXQUATERNION *parentTransform = &((*parent)->getTransforms()->worldTransform_);
        TransformsType *trans = (*transforms);

        j += innerSize;
        for( unsigned int k=0; k<innerSize; k++, trans++ )
        {
            D3DXQuaternionMultiply( &trans->worldTransform_,
                                    &trans->localTransform_,
                                    parentTransform 
                                  );
        }

        transforms++;
        parent++;
    }
}
void testFastCacheObject( Node< FastCacheObject > **parent, TransformsType **transforms, unsigned int size )
{
    for (int i=0; i<1000000; i++)
        updateWorldTransforms( parent, transforms, size );
}

void testSlowCacheObject( Node< SlowCacheObject > *slowCacheRoot )
{
    for (int i=0; i<1000000; i++)
        slowCacheRoot->updateWorldTransform( 0 );
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<SlowGameEntity> slowGameEntities;
    std::vector<FastGameEntity> fastGameEntities;

    unsigned int num = 100000;
    SlowGameEntity slowGameEntity;
    FastGameEntity fastGameEntity;
    for (unsigned int i=0; i<num; i++)
    {
        slowGameEntities.push_back( slowGameEntity );
        fastGameEntities.push_back( fastGameEntity );
    }

    //TEST 1 compare AI functions
    testSlowGameEntities( slowGameEntities );
    testFastGameEntities( fastGameEntities );

    //TEST 2 compare vertex transformations
    (*slowGameEntities.begin()).transformManyVertices( 1000000 );
    (*fastGameEntities.begin()).transformManyVertices( 1000000 );

    //TEST 3 compare orientation updates
    testSlowGameEntitysCalcOri( slowGameEntities );
    testFastGameEntitysCalcOri( fastGameEntities );


    //TEST 4 compare cache objects

    //build a tree of FastCacheObjects//////////////////////////////////////////
    //create 3 sets of arrays- one for each level of the tree
    //root level array - just one node
    TransformsType *rootTransforms = new TransformsType;
    //second level array - 2 nodes
    TransformsType *level2_Transforms = new TransformsType[2];
    //third level array - 8 nodes
    TransformsType *level3_Transforms = new TransformsType[8];

    //make the root
    FastCacheNode *fastCacheRoot = new FastCacheNode();
    fastCacheRoot->setTransforms( rootTransforms );
    //add 2 children to the root ( as Nodes )
    FastCacheNode *childA2 = fastCacheRoot->addChild< FastCacheNode >();
    FastCacheNode *childB2 = fastCacheRoot->addChild< FastCacheNode >();
    childA2->setTransforms( &level2_Transforms[0] );
    childB2->setTransforms( &level2_Transforms[1] );
    //add 4 children to each root child ( as Objects )
    for(int i=0; i<4; i++)
    {
        FastCacheObject *leafA = childA2->addChild< FastCacheObject >();
        FastCacheObject *leafB = childB2->addChild< FastCacheObject >();

        leafA->setTransforms( &level3_Transforms[i] );
        leafB->setTransforms( &level3_Transforms[i+4] );
    }

    //put top 3 nodes into a contiguous array of arrays
    FastCacheNode *nodeArray[] = { fastCacheRoot, childA2, childB2 };
    //put 3 transforms arrays into a contiguous array of arrays
    TransformsType *transArray[] = { level2_Transforms, &level3_Transforms[0], &level3_Transforms[4] };
    //updateWorldTransforms( nodeArray, transArray, 11 );
    testFastCacheObject( nodeArray, transArray, 11 );

    delete fastCacheRoot;
    delete [] rootTransforms;
    delete [] level2_Transforms;
    delete [] level3_Transforms;




    //build a tree of SlowCacheObjects//////////////////////////////////////////
    typedef Node< SlowCacheObject > SlowCacheNode;
    //make the root
    SlowCacheNode *slowCacheRoot = new SlowCacheNode;
    //add 2 children to the root ( as Nodes )
    SlowCacheNode *childA = slowCacheRoot->addChild< SlowCacheNode >();
    SlowCacheNode *childB = slowCacheRoot->addChild< SlowCacheNode >();
    //add 4 children to each root child ( as Objects )
    for(int i=0; i<4; i++)
    {
        childA->addChild< SlowCacheObject >();
        childB->addChild< SlowCacheObject >();
    }
    //slowCacheRoot->updateWorldTransform( 0 );
    testSlowCacheObject( slowCacheRoot );

    delete slowCacheRoot;


    printf(" press q to quit\n" );
    while(1)
    {
        if ( _getch() == 'q' )
            break;
    }

    return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

gtdelarosa
Software Developer Gameloft
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 10 Nov 2010
Article Copyright 2010 by gtdelarosa
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid