Click here to Skip to main content
12,634,296 members (26,748 online)
Click here to Skip to main content

Stats

18.1K views
54 downloads
27 bookmarked
Posted

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

You may also be interested in...

Pro
Pro
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161208.2 | Last Updated 10 Nov 2010
Article Copyright 2010 by gtdelarosa
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid