It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.

By Miguel Gomez
Gamasutra
July 2, 1999

Letters to the Editor:
Write a letter
View all letters


Features

The BASIS type

Contents

Introduction

The Vector type

The MATRIX type

The BASIS type

The COORDINATE FRAME type

The RIGID_BODY STATE type

Bibliography

There are two good ways and one bad way to store three-dimensional orientation. Storing it as a quaternion uses only four scalars and makes interpolating between orientations efficient. Storing orientation as an orthonormal basis (three mutually orthogonal unit vectors in the form of a 3x3 matrix) uses nine scalars and is less convenient for interpolating orientation; however, it is much more efficient for transforming vectors to and from a local coordinate frame. Because of collision detection this seems to be what the orientation is most frequently used for, so I prefer using an orthonormal basis (see Listing 3). The conversion from a basis to a quaternion is not terribly expensive and can be done if interpolation is necessary.

Why define a BASIS type when you can simply use a 3x3 matrix? There are operations on bases that you wouldn’t do on matrices, such as rotation, and there are matrix operations (such as addition) that don’t make sense on bases. The distinct type makes the code a little cleaner, as well as safeguarding against unwanted operations.

To transform a vector v in body space to world space, we multiply the x, y and z components of v by their corresponding axes and add all the resulting vectors together:

VECTOR v_world = v.x * X_body + v.y * Y_body + v.z * Z_body;

To transform a vector v in world space back to body space, we dot the vector with each body axis:

v_body.x = v.dot( X_body );

v_body.y = v.dot( Y_body );

v_body.z = v.dot( Z_body );

Listing 3.

// An orthonormal basis with respect to a parent

//

class BASIS

{

public:

MATRIX R;

public:

BASIS()

{}

BASIS(

const VECTOR& v0,

const VECTOR& v1,

const VECTOR& v2

)

: R( v0, v1, v2 )

{}

BASIS( const MATRIX& m )

: R( m )

{}

const VECTOR& operator [] ( long i ) const { return R.C[i]; }

const VECTOR& x() const { return R.C[0]; }

const VECTOR& y() const { return R.C[1]; }

const VECTOR& z() const { return R.C[2]; }

const MATRIX& basis() const { return R; }

void basis( const VECTOR& v0, const VECTOR& v1, const VECTOR& v2 )

{

this->R[0] = v0;

this->R[1] = v1;

this->R[2] = v2;

}

// Right-Handed Rotations

void rotateAboutX( const SCALAR& a )

{

if( 0 != a )//don’t rotate by 0

{

VECTOR b1 = this->Y()*cos(a) + this->Z()*sin(a);

VECTOR b2 = -this->Y()*sin(a) + this->Z()*cos(a);

//set basis

this->M[1] = b1;

this->M[2] = b2;

//x is unchanged

}

}

void rotateAboutY( const SCALAR& a )

{

if( 0 != a )//don’t rotate by 0

{

VECTOR b2 = this->Z()*cos(a) + this->X()*sin(a); //rotate z

VECTOR b0 = -this->Z()*sin(a) + this->X()*cos(a); //rotate x

//set basis

this->M[2] = b2;

this->M[0] = b0;

//y is unchanged

}

}

void rotateAboutZ( const SCALAR& a )

{

if( 0 != a )//don’t rotate by 0

{

//don’t over-write basis before calculation is done

VECTOR b0 = this->X()*cos(a) + this->Y()*sin(a); //rotate x

VECTOR b1 = -this->X()*sin(a) + this->Y()*cos(a); //rotate y

//set basis

this->M[0] = b0;

this->M[1] = b1;

//z is unchanged

}

}

//rotate the basis about the unit axis u by theta (radians)

void rotate( const SCALAR& theta, const VECTOR& u );

//rotate, length of da is theta, unit direction of da is u

void rotate( const VECTOR& da );

 

// Transformations

const VECTOR transformVectorToLocal( const VECTOR& v ) const

{

return VECTOR( R.C[0].dot(v), R.C[1].dot(v), R.C[2].dot(v) );

}

const POINT transformVectorToParent( const VECTOR& v ) const

{

return R.C[0] * v.x + R.C[1] * v.y + R.C[2] * v.z;

}

};


The COORDINATE FRAME type


join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2003 CMP Media LLC

privacy policy
| terms of service