Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Generic Math Template Library FAQ

Welcome to the GMTL frequently asked questions list.

General Questions about GMTL

Why do you use templated code?

There are several benefits to using the templated code approach. First, it allows us to easily support multiple versions of very similar data types. For instance, there are many different types of matrices, varying in both size and data type. We could have 4x4 floating point, 3x3 double precision, 2x2 floating point, etcetera. These are very different matrices, but in general they all support the same kinds of operations. With templated code, we can write a single function in many cases that will handle all possible variations of a GMTL object.

Templated code also makes GMTL very easy to extend. Although GMTL provides many data types to begin with, it allows a lot of flexibility for developers to customize their own code. For instance, GMTL provides several commonly-used vector types such as 2, 3, and 4-dimensional floating point vectors. But maybe you're a physicist doing research in the 6th dimension, and you need a 6-D vector. GMTL's templated code allows you to create a vector of arbitrary dimensionality. And the vector's math operations are written in such a way that they will work for vectors of any size, eliminating the need for the physicist to rewrite all of the vector math.

It also allows us to provide a unified interface to GMTL objects. This is why many of the functions in GMTL have the same name, but can work on a wide variety of data types. Developers using GMTL have much less to remember than if we had a separate function name for each possible combination of data types. Instead, functions that conceptually do a similar function have many versions overloaded with different data type combinations.

What's with these namespaces?

All of GMTL's functions and data types are defined within the 'gmtl' namespace.

In C++, you can reference something in a namespace by prepending it to the thing you want to reference. For instance, when creating any GMTL object, you need to prepend "gmtl::" to its name. The following code shows the instantiation of several different objects.

  gmtl::Matrix44f myMatrix;
  gmtl::Vec3f myVector;
  gmtl::Quatf myQuaternion;

Similarly, GMTL's function calls also need to have this namespace:

  gmtl::identity( myMatrix );
  gmtl::normalize( myVector );

Developers can also specify that they are using a particular namespace in their code, aleviating the need to specify the namespace for each object.

  using namespace gmtl
  {
      Matrix44f myMatrix;
      Vec3f myVector;
      normalize( myVector );
  };

Additionally, GMTL's C math functions are further encapsulated by a namespace called "Math". To reference these functions, you must prepend "gmtl::Math::" to the function names.

  float cosine = gmtl::Math::cos( 3.14 );
  float minimum = gmtl::Math::Min( 3.0, 1.4, -43.2 );

Why would I want to use GMTL's C math abstraction rather than the regular C math library?

GMTL has abstracted the C math libraries to ensure cross-platform compatibility. If you write an application using GMTL's math functions, you do not have to make any changes when building on different platforms.

The math abstraction is also designed to be type safe. It will work for different mathematical data types such as float and double without having different function syntax for each data type. For instance, on some platforms, the math library is designed solely for double-precision floating point numbers and separate functions are provided for regular float numbers, with an 'f' appended to each function name. On such platforms, you have math functions like 'floor' & 'floorf' as well as 'cos' and 'cosf'.

In GMTL, there is only one function name to remember for each type of operation, regardless of the data type. So you could pass either a double or a float to GMTL's 'cos' function to get the cosine value.

What is an AABox?

This is an axially-aligned bounding box. Think of it as a box in 3D space with its each of its sides parallel to one of the coordinate axes. Such a box can be described using only 2 points, the minimum and maximum. AABoxes can be useful in object collision detection.

What is an AxisAngle?

This is a rotational data type, defined by an arbitrary axis vector in space and an amount of rotation.

What is a Coord?

This is a coordinate frame, defined by a position and a rotation value.

What is an EulerAngle?

This is a data type that represents a rotational value. It consists of three values, each representing a rotation about one of the coordinate axes X, Y, and Z. Note that Euler angle representations are often more intuitive to use, but suffer from the problem of Gimble lock.

What is a LineSeg?

This is a line segment of finite length. It consists of 2 endpoints in space. Internally to GMTL, a LineSeg is defined by an endpoint in space and a vector that shows where the other endpoint is relative to the first point.

What is a Matrix?

This is a data type commonly used in graphical applications. It simply contains rows and columns of data, with any number of rows and columns. 4x4 matrices can represent any transformation in 3D space, containing (but not limited to) translational, rotational, skew, and scaling information.

What is a Plane?

A plane is a flat surface in 3D space with no boundaries. It is defined by a point in 3D space and a surface normal vector.

What is a Point?

Points represent a position in space, with one data value per dimension of that space.

What is a Quat?

This is a quaternion, which is represents a rotation in 3D space. Quaternions can be used for rotational interpolation along the surface of a sphere. They are represented at a 4-element normalized vector.

What is a Ray?

A ray is a line in space that has an origin point extends to infinity in some direction. In GMTL, a ray is represented by a Point object denoting its origin and a vector showing the direction it is pointing.

What is a Sphere?

This is a 3D dimensional round object such that every point on the outer boundary of the object is the same distance away from the centerpoint. A sphere can be described by a centerpoint position and a radius.

What is a Tri?

This is a triangle, defined by three points in space. The counterclockwise ordering of the points determines the direction of the triangle's surface normal (using a right-handed coordinate system).

What is a Vec?

This is a vector that represents a direction in space, with one data value per dimension of the space.

What is the difference between a point and a vector?

Points represent positions in space, while vectors represent a direction. Even though they may seem to represent the same data, it is generally discouraged to use them interchangably. Differences occur when operations are performed on them. For instance, if you transform a point using a matrix, the full transformation will be applied to the point (translation, rotation, skew, and scale). But when a vector is transformed by a matrix, only the rotational transform is applied to it.

Why doesn't my vector move?

If you are transforming a vector using a matrix, only the matrix's rotational information will be applied. Hence, you may be expecting the vector's endpoint to change but it will not. You most likely want to use a Point object instead of a Vec.

What is the difference between AxisAngle, EulerAngle and Quat?

An axis angle consists of a vector designating the axis to rotate about, and the rotation amount to use. An Euler angle object consists of 3 rotation amounts, one for each coordinate axis X, Y, and Z. Euler angles are often the most intuitive rotation type, but suffer from the Gimble lock problem. A quaternion has 4 values that can be translated into an axis and a rotation amount, but are stored in a normalized form that maintain the mathematical properties of quaternions, including the ability of spherical interpolation.

How is data represented in a matrix?

GMTL matrices have their data stored in a 2-dimension natrix array in column major order. This means that you can access the data using the following syntax:

  gmtl::Matrix44f myMat;
  int row, column = 2;
  float data = myMat[column][row];

This representation is the same for many graphics API's, including OpenGL, DirectX, Performer, and OpenSG - each of which uses matrix data in a column major ordering.

What are the general concepts behind GMTL?

This question is best answered by our "Light Overview of GMTL" in the online documentation of GMTL. It is located at the following webpage: http://ggt.sourceforge.net/html/main.html

What's with all the 'make' and 'set' functions?

In general, think of the make function as creating a new object based on an existing object, or extracting some part (or all) of an existing object. By comparison, use the set function to copy some part of one object to another existing object.

You use the 'make' function to generate new objects based on existing objects that may not even be the same type. For instance, we can create a quaternion rotation from an existing Euler angle rotation. Once made, the quaternion will perform the exact same rotation as the Euler angle.

  gmtl::EulerAngleXYZf myEuler;
  gmtl::Quatf myQuat = gmtl::make<gmtl::Quatf>( myEuler );

Note that you have to specify a templated argument that says what kind of object you want to be made.

Although you can usually make one object from any other type of object, there are some fundamental limitations. For instance, you can't make a quaternion (purely rotational information) from a vector (purely translational information), with the exception of using the makePure function (see below for details). Similarly, if you have a matrix containing both translational and rotational information, you can only make a vector based on the translational data.

In the following example, we make a new axis angle object that has the same rotational data as our existing matrix. Regardless of whatever translation and scaling data our matrix contains, only the rotation is represented in the new axis angle.

  gmtl::Matrix44f myMat;
  gmtl::AxisAnglef myAA = gmtl::make<gmtl::AxisAnglef>( myMat );

The 'set' function, however, modifies an existing object with data from another object. For instance, if you already have a quaternion and you want to change its rotation data to match an Euler angle, the 'set' function is appropriate. Note that the first argument is ALWAYS the object that you want to change, and the second argument is ALWAYS the object that you want to use as the data source. The source data will not be changed.

  gmtl::EulerAngleXYZf myEuler;
  gmtl::Quatf myQuat;

  gmtl::set( myQuat, myEuler );

What are the makeTrans, makeRot, setTrans, setScale, etc. functions?

These are altered versions of the 'make' and 'set' functions that specifically target certain types of data, such as rotational, translational, or scaling information.

Data types such as coordinate frame objects and matrices can have a combination of different types of transformations. For instance, a particular matrix could describe a translation and a rotation. But perhaps you only want to know the translation of it. In this case, the makeTrans function can be useful.

  gmtl::Matrix44f myFullMat;
  gmtl::Matrix44f myTransMat;

  myTransMat = gmtl::makeTrans<gmtl::Matrix44f>( myFullMat );

Now 'myTransMat' represents the translational aspect of 'myFullMat'. If we had simply used the 'make' function instead of 'makeTrans', then myTransMat would be a complete copy of myFullMat.

As with the 'set' function, other functions like 'setTrans' or 'setRot' copy a feature from one object to another, with the objects not necessarily being the same type. The following example shows how to set the translation of a matrix from a coordinate frame object:

  gmtl::Matrix44f myMat;
  gmtl::CoordVec3EulerAngleXYZf myCoord;

  gmtl::setTrans( myMat, myCoord );

Note that whatever rotational data the matrix had is maintained even after using the setTrans function, which will only modify its translational aspect.

There are many altered 'make' and 'set' extensions beyond what we have discussed, but they all work in the same manner. Some commonly-used ones are makeTrans, setTrans, makeRot, setRot, makeScale, and setScale. Here are a few others that you might use:

The makeDirCos function creates a matrix or quaternion rotation using direction cosines.

  gmtl::Vec3f xDestAxis, yDestAxis, zDestAxis;
  gmtl::Vec3f xSrcAxis, ySrcAxis, zSrcAxis;

  gmtl::Matrix44f myMat = gmtl::makeDirCos<gmtl::Matrix44f>( xDestAxis, yDestAxis, zDestAxis, xSrcAxis, ySrcAxis, zSrcAxis );

The makePure function allows you to start with a vector and create a quaternion with that vector as its rotation axis, but without any twist value.

  gmtl::Vec3f myVec;
  gmtl::Quatf myQuat = gmtl::makePure<gmtl::Quatf>( myVec );

You can use the makeVec function to extract the axis of rotation from a quaternion object.

  gmtl::Quatf myQuat;
  gmtl::Vec3f myVec = gmtl::makeVec<gmtl::Vec3f>( myQuat );

The makeNormal function allows you to create a normalized object from a source object. Usually this will deal with vectors.

  gmtl::Vec3f srcVec;
  gmtl::Vec3f normVec = gmtl::makeNormal<gmtl::Vec3f>( srcVec );

The makeXRot, makeYRot, makeZRot functions can be used to extract rotational data about particular axes.

  gmtl::Matrix44f myMat;
  float xrot = gmtl::makeXRot( myMat );

Why do we need all the extensions on the end of data types?

This refers to the fact that you can use our provided type definitions to create specific versions of an object. For instance, there are many types of matrices, with varying numbers of rows and columns, as well as the kind of data contained therein. You can't simply make a Matrix, you must specify what kind:

  gmtl::Matrix myMatrix;      //This will not work
  gmtl::Matrix44f myMatrix;   //This is correct

The reason we have these extensions (shown here by "44f" appended to the Matrix data type) is purely for simplicity. You can always create objects using templated arguments, but the extended versions of the data types are provided for convenience. As an example, we can create the 4x4 floating point matrix shown previously:

  gmtl::Matrix44f myMatrix;
  gmtl::Matrix<float, 4, 4> myMatrix;

These two instantiations of myMatrix are equivalent, but you can see how the first version can be much easier to read and write. If you want to get more serious about simplifying your code, you can create your own type definitions.

  typedef gmtl::Matrix<float, 4, 4> Mat;
  typedef gmtl::Vec<float, 3> Vector;

These type definitions make the following pairs of object instantiations equivalent:

  gmtl::Matrix<float, 4, 4> myMatrix;
  Mat myMatrix;

  gmtl::Vec<float, 3> myVec;
  Vector myVec;

Spatial Objects

What is a spatial object?

A spatial object is something that has some sort of geometric meaning, rather than being purely mathematical. Spatial objects can be visualized in some way, such that you could draw them on a piece of paper or render them using 3-D graphics. They occupy some portion of an n-dimensional space, typically 2-D or 3-D.

Spatial objects are typically used for generating boundaries or performing collision detection. They can be extremely useful in graphical applications. We can perform special operations on spatial objects, such as testing whether certain objects intersect with each other or whether one volumetric object (such as a sphere) contains another spatial object.

What kinds of spatial objects does GMTL support?

Points, vectors, line segments, rays, planes, spheres, axially-aligned boxes, and triangles.

What objects in GMTL are not considered spatial?

Matrices, quaternions, axis angles, Euler angles, and coordinate frames.

How Do I ...?

Vectors

How do I rotate a vector?

In most cases you can simply use the * operator with your vector and one of the rotaional data types.

  gmtl::Vec3f myVec;
  gmtl::AxisAngle myAA;
  gmtl::Quaternion myQuat;
  gmtl::Matrix44f myMat;
  gmtl::EulerAngleXYZf myEuler;
 
  myVec = myVec * myAA;
  myVec = myVec * myQuat;
  myVec = myVec * myMat;
  myVec = myVec * myEuler;

How do I find the cross product of 2 vectors?

We can use the cross function, which returns another vector.

  gmtl::Vec3f vecA, vecB, crossVec;
  crossVec = gmtl::cross( vecA, vecB );

How do I find the dot product of 2 vectors?

Use the dot function, which returns a number (depending on the type of data in the vectors).

  gmtl::Vec3d vecA, vecB;
  double x = gmtl::dot( vecA, vecB );

How do I check if a vector is normalized?

Use the isNormalized function, which returns a boolean value.

  gmtl::Vec3f myVec;
  if ( gmtl::isNormalized( myVec ) )
  {
     cout << "Vector is normalized" << endl;
  }

How do I normalize a vector?

Use the normalize function. After this, the length of the vector will be 1, unless the original length was 0, in which case normalization is not possible.

  gmtl::Vec3f myVec;
  gmtl::normalize( myVec );

How do I check if 2 vectors are equal?

Use the == operator, just as you would when testing the equality of simple data types like `int'.

  gmtl::Vec3f vecA, vecB;
  if ( vecA == vecB )
  {
     cout << "Vectors are equal" << endl;
  }

How do I find the length of a vector?

Use the length function. The numeric type returned depends on the data type of the vector.

  gmtl::Vec3f myVec;
  float length = gmtl::length( myVec );

Another potential function to use is lengthSquared. This function is provided as a convenience because GMTL users frequently need this value rather than merely the length.

  float lengthSq = gmtl::lengthSquared( myVec );

How do I invert a vector?

Use A scalar multiplication by -1. This will cause the vector to be pointing in the exact opposite direction and keep the same length.

  gmtl::Vec3f myVec;
  myVec *= -1;

How do I interpolate between 2 vectors?

Use the lerp function. This will perform a linearly-interpolated vector based on 2 original vectors and an interpolation weight between 0 and 1.

  gmtl::Vec3f resultVec, vecA. vecB;
  float weight = 0.333;

  gmtl::lerp( resultVec, weight, vecA, vecB );

After this function, resultVec now contains a vector that is one third of the way from vecA to vecB. This resulting vector is closer to vecA.

How do I multiply a vector by a scalar value?

Simply use the * or *= operator.

  gmtl::Vec3f myVec, anotherVec;
  float myScalar = 3.5;

  myVec *= myScalar;
  anotherVec = myVec * myScalar;

How do I add, subtract, divide and multiply vectors?

Generally, you can use any of the standard mathematical operators ('+', '-', '*', '/') to perform math functions on vectors.

  gmtl::Vec3f vecA, vecB, vecC;

  vecA = vecB * vecC;
  vecA = vecB / vecC;
  vecA += vecB;
  vecA = vecB + vecC;
  vecA -= vecC;
  vecA = vecB - vecC;

etc.

Matrices

How do I multiply matrices?

The simplest way to multiply one matrix by another is to use the * operator.

  gmtl::Matrix44f A, B, C;
  A = B * C;

Note that when multiplying matrices, the ordering matters. The following line of code could make matrix A have a different result:

  A = C * B;

Alternatively, you can use the preMult and postMult functions.

This preMult call is the same as "A = B * A;"

  gmtl::preMult( A, B ); 

This postMult call is the same as "A = A * B;"

  gmtl::postMult( A, B );

The *= operator also acts as a postMult function.

  A *= B;

How do I create a matrix?

You can create a new matrix simply by instantiating it. You can use one of the GMTL-provided type definitions. The first matrix is a 4x4 matrix of floating point numbers. The second is a 2x3 matrix of double precision floating point numbers.

  gmtl::Matrix44f myMat;
  gmtl::Matrix23d otherMat;

You can also create matrices of arbitrary size and data type using the templated constructor. The templated arguments are (in order) the data type, the number of rows, and the number of columns. For example, the following creates a 4x6 matrix of floating point numbers.

  gmtl::Matrix< float, 4, 6 > newMatrix;

You can also create a matrix from any of the other transformation data types. See below for examples.

How do I create a matrix from a vector?

Using the makeTrans function, you can create a purely translational matrix from a vector.

  gmtl::Vec3f myVec;
  gmtl::Matrix44f myMat = gmtl::makeTrans< gmtl::Matrix44f >( myVec );

How do I create a matrix from a point?

Using the make function, you can create a purely translational matrix from a point.

  gmtl::Point3f myPoint;
  gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myPoint );

How do I create a matrix from a quaterion?

Using the make function, you can create a purely rotational matrix from a quaternion object.

  gmtl::Quatf myQuat;
  gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myQuat );

How do I create a matrix from an Euler angle?

Using the make function, you can create a purely rotational matrix from an EulerAngle object.

  gmtl::EulerAngleXYZf myEulerAngle;
  gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myEulerAngle );

How do I create a matrix from an axis angle?

Using the make function, you can create a purely rotational matrix from an AxisAngle object.

  gmtl::AxisAnglef myAxisAngle;
  gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myAxisAngle );

How do I scale a matrix?

  gmtl::Matrix44f myMat;
  float scale = 0.5;

  gmtl::setScale( myMat, scale );

How do I copy a matrix?

You can simply use the '=' operator to copy from one matrix to another.

  gmtl::Matrix44f matA, matB;
  matA = matB;

How do I access individual data elements of a matrix?

You can simply use the [ row# ][ column# ] operators, just as you would if you were accessing elements of a double array.

  gmtl::Matrix44f myMat;
  float x = myMat[3][2];

How do I extract just the rotation data from a matrix?

You can extract the rotational data as any of GMTL's rotation data types. In any case, you need to use the makeRot templated function. Note that you need to specify which rotation data type you want to extract.

  gmtl::Matrix44f myMat;
  gmtl::EulerAngleXYZf myEuler;
  gmtl::AxisAnglef myAxisAngle;
  gmtl::Quatf myQuat;
  gmtl::Matrix44f myRotationMat;

  myEuler = gmtl::makeRot< gmtl::EulerAngleXYZf >( myMat );
  myAxisAngle = gmtl::makeRot< gmtl::AxisAnglef >( myMat );
  myQuat = gmtl::makeRot< gmtl::Quatf >( myMat );
  myRotationMat = gmtl::makeRot< gmtl::EulerAngleXYZf >( myMat );

How do I extract just the translation data from a matrix?

You can extract the translational data as either a vector or a point. You need to use the templated makeTrans function.

  gmtl::Matrix44f myMat;
  gmtl::Point3f myPoint;
  gmtl::Vec3f myVec;
 
  myVec = gmtl::makeTrans< gmtl::Vec3f >( myMat );
  myPoint = gmtl::makeTrans< gmtl::Point3f >( myMat );

How do I set a matrix to be the identity matrix?

Matrices will automatically be identity matrices upon creation. If you want to set them to the identity later, use the identity function.

  gmtl::Matrix44f myMat;
  gmtl::identity( myMat );

How do I set a matrix to contain all zeros?

  gmtl::Matrix44f myMat;
  gmtl::zero( myMat );

How do I invert a matrix?

In most cases you can simply use the invert function. This will perform a "smart" inversion that selects an inversion method (full, affine, orthonormal, orthogonal, or identity) based on the kinds of transformations it has been through.

  gmtl::Matrix44f myMat;
  gmtl::invert( myMat );

You can optionally force a full inversion by using the invertFull function.

  gmtl::invertFull( myMat );

How do I transpose a matrix?

Use the transpose function.

  gmtl::Matrix44f myMat;
  gmtl::transpose( myMat );

How do I transform a point using a matrix?

This will perform a full transformation on the point.

  gmtl::Point3f myPoint;
  gmtl::Matrix44f myMat;
  gmtl::xform( myPoint, myMat, myPoint );

How do I transform a vector using a matrix?

It is important to note that a vector will only be modified by the rotational transformation contained in a matrix.

  gmtl::Vec3f myVec;
  gmtl::Matrix44f myMat;
  gmtl::xform( myVec, myMat, myVec ); 

How do I use my matrix data with OpenGL?

You can access the raw matrix data for use with OpenGL using the getData() function. For instance, you may want to multiply the OpenGL matrix stack by a GMTL matrix.

  gmtl::Matrix44f myMat;
  glMultMatrixf( myMat.getData() );

Note that GMTL matrix data is also safe to use for other graphics APIs such as DirectX, Performer, and OpenSG.

Quaternions

How do I create quaternions?

You can create quaternions directly using known values.

  float x = 1.0;
  float y, z, w = 0.0;
  gmtl::Quatf myQuat(x, y, z, w);

You can also create quaternions based on other rotational types, such as an EulerAngle or matrix.

  gmtl::EulerAngleXYZf myEuler;
  gmtl::Matrix44f myMat;
  myQuat = gmtl::make<gmtl::Quatf>( myEuler );
  myQuat = gmtl::make<gmtl::Quatf>( myMat );

How do I multiply quaternions?

Simply use the * and *= operators.

  gmtl::Quatf quatA, quatB, quatC;
  quatA *= quatB;
  quatC = quatA * quatB;

How do I combine quaternion rotations?

This is the same as multiplying quaternions.

  gmtl::Quatf quatA, quatB, quatC;
  quatA *= quatB;
  quatC = quatA * quatB;

How do I perform spherical interpolation with quaternions?

Use the slerp function. You need an origin quaternion, a target quaternion, and an interpolation amount between 0 and 1. The following example interpolated halfway between the origin and target quaternions. Note that the interpolation path follows the shortest length arc around a sphere.

  gmtl::Quatf resultQuat, originQuat, targetQuat;
  float amount = 0.5;

  gmtl::slerp( resultQuat, amount, originQuat, targetQuat );

How do I perform linear interpolation with quaternions?

This is similar to performing spherical interpolation, but follows a straight line interpolation path rather than a shortest arc around a sphere.

  gmtl::Quatf resultQuat, originQuat, targetQuat;
  float amount = 0.5;

  gmtl::lerp( resultQuat, amount, originQuat, targetQuat );

How do I make a quaternion that rotates one vector to another along the shortest arc?

If you have an origin vector and a target vector, you can use the makeRot function. Note that you should normalize these vectors first.

  gmtl::Vec3f originVec, targetVec;
  gmtl::Quatf myQuat;

  gmtl::normalize( originVec );
  gmtl::normalize( targetVec );
  myQuat = gmtl::makeRot<gmtl::Quatf>( originVec, targetVec );

How do I invert a quaternion?

Use the invert function.

  gmtl::Quatf myQuat;
  gmtl::invert( myQuat );

How do I conjugate a quaternion?

Use the conj function.

  gmtl::Quatf myQuat;
  gmtl::conj( myQuat );

How do I check if 2 quaternions are the same?

Use the == and != operators.

  gmtl::Quatf quatA, quatB;
  if (quatA == quatB)
  {
     cout << "Quaternions are equal" << endl;
  }
  if (quatA != quatB)
  {
     cout << "Quaternions are not equal" << endl;
  }

Collision and Containment Detection

How do I perform collision detection and containment tests?

GMTL provides various spatial objects, including spheres, line segments, rays, points, triangles, planes, axially-aligned bounding boxes, and oriented bounding boxes.

The library also provides functions to test whether particular objects are intersecting each other or whether one object is contained by another. See below for specific examples.

In general, you can use the 'intersect' function on any two spatial objects to test whether they intersect with each other or not. And you can use the 'isInVolume' to tell whether one volumetric object (such as a sphere or box) contains some other spatial object.

How do I test if a point is contained by a sphere?

Use the isInVolume function, which returns a boolean value. Note that if the point is on the outer boundary of the sphere, it is still considered to be contained.

  gmtl::Point3f myPoint;
  gmtl::Spheref mySphere;

  if ( gmtl::isInVolume( mySphere, myPoint ) )
  {
     cout << "Point is inside the sphere" << endl;
  }

How do I test if a point is on the surface of a sphere?

Use the isOnVolume function, which returns a boolean value.

  gmtl::Point3f myPoint;
  gmtl::Spheref mySphere;

  if ( gmtl::isOnVolume( mySphere, myPoint ) )
  {
     cout << "Point is on the sphere" << endl;
  }

You can optionally supply a tolerance argument, which will change the function to compute whether the point is within a certain distance of the sphere's surface.

  float tolerance = 0.001;
  if ( gmtl::isOnVolume( mySphere, myPoint, tolerance ))
  {
    cout << "Point is on the sphere" << endl;
  }

How do I test if one sphere is contained by another?

Use the isInVolume function, which returns a boolean value.

  gmtl::Spheref sphereA, sphereB;
  if ( gmtl::isInVolume( sphereA, sphereB ) )
  {
     cout << "Sphere is within the other sphere" << endl;
  }

How do I test if two spheres intersect while moving?

We can use the intersect function to compute this. We need a vector for each sphere representing the sphere's movement over the timestep. You also pass by reference 2 floating point numbers that will be modified by the function. The first of these numbers will be the normalized time of contact. The second is the normalized time of disconnection. The second number will only be set when the spheres pass through each other, in which case it will be set to the time when they stop intersecting.

  gmtl::Spheref sphereA, sphereB;
  gmtl::Vec3f pathA, pathB;
  float contactTime, disconnectTime;

  if ( gmtl::intersect( sphereA, sphereB, pathA, pathB, contactTime, disconnectTime ) )
  {
     cout << "Spheres intersect at some time" << endl;
  }

How do I change a sphere so that it contains a given point?

Use the extendVolume function. This will keep the sphere's centerpoint in the same location, but extend its radius just enough to contain the given point. If the point is already inside the sphere, no change occurs.

  gmtl::Spheref mySphere;
  gmtl::Point3f myPoint;
 
  gmtl::extendVolume( mySphere, myPoint );

How do I change a sphere so that it contains a set of points?

There is a version of the extendVolume function that takes a STL vector containing an arbitrary number of points and will increase a sphere's radius to be just large enough to contain all of these points. If the sphere already contains all of the points, then the sphere will be unchanged.

  gmtl::Spheref mySphere;
  std::vector<gmtl::Point3f> myPoints;

  gmtl::extendVolume( mySphere, myPoints );

How do I change a sphere so that it contains another sphere?

Use the extendVolume function. The first sphere's radius will be increased to be just large enough to contain the other sphere. If the first sphere already contains the other sphere, no change occurs.

  gmtl::Spheref sphereA, sphereB;

  gmtl::extendVolume( sphereA, sphereB );

How do I test if two AABoxes intersect?

Use the intersect function, which returns a boolean value.

  gmtl::AABoxf boxA, boxB;

  if ( gmtl::intersect( boxA, boxB ) )
  {
     cout << "Boxes intersect" << endl;
  }

How do I test if an AABox is contained by another?

Use the isInVolume function, which returns a boolean value.

  gmtl::AABoxf boxA, boxB;

  if ( gmtl::isInVolume( boxA, boxB ) )
  {
     cout << "Box A contains box B" << endl;
  }

How do I test if a point is inside an AABox?

Use the isInVolume function, which returns a boolean value. Note that if the point is on the box's surface, it is still considered to be contained.

  gmtl::AABoxf myBox;
  gmtl::Point3f myPoint;
  
  if ( gmtl::isInVolume( myBox, myPoint ) )
  {
     cout << "The point is inside the box" << endl;
  }

How do I test if two AABoxes intersect while moving?

We can use the intersect function to compute this. We need a vector for each AABox representing the box's movement over the timestep. You also pass by reference 2 floating point numbers that will be modified by the function. The first of these numbers will be the normalized time of contact. The second is the normalized time of disconnection. The second number will only be set when the boxes pass through each other, in which case it will be set to the time when they stop intersecting.

  gmtl::AABoxf boxA, boxB;
  gmtl::Vec3f pathA, pathB;
  float contactTime, disconnectTime;

  if ( gmtl::intersect( boxA, boxB, pathA, pathB, contactTime, disconnectTime ) )
  {
     cout << "AABoxes intersect at some time" << endl;
  }

How do I change an AABox so that it contains a given point?

Use the extendVolume function. This will increase the size of one or more of the box's bounding faces. If the point is already inside the box, then no change occurs.

  gmtl::AABox myBox;
  gmtl::Point3f myPoint;

  gmtl::extendVolume( myBox, myPoint );

How do I change an AABox so that it contains another AABox?

Use the extendVolume function. This will increase the size of one or more of the first box's bounding faces. If the other box is already inside the first box, then no change occurs.

  gmtl::AABoxf boxA, boxB;
  
  gmtl::extendVolume( boxA, boxB );

How do I change an AABox so that it contains a given sphere?

Use the extendVolume function. This will increase the size of one or more of the box's bounding faces. If the sphere is already inside the box, then no change occurs.

  gmtl::AABoxf myBox;
  gmtl::Spheref mySphere;

  gmtl::extendVolume( myBox, mySphere );

How do I test if a sphere intersects with an AABox?

Use the intersect function, which returns a boolean value.

  gmtl::AABoxf myBox;
  gmtl::Spheref mySphere;
 
  if ( gmtl::intersect( myBox, mySphere ) 0
  {
     cout << "Box and sphere intersect\n" << endl;
  }

How do I test if a ray intersects with a plane?

Use the intersect function, which returns a boolean value. You also must pass by reference a floating point value, which will be modified to be an indicator of the point in space where the ray intersects the plane. You can then compute the exact point of intersection.

  gmtl::Planef myPlane;
  gmtl::Rayf myRay;
  float isect;
  
  if ( gmtl::intersect( myPlane, myRay, isect ) )
  {
     cout << "The ray intersects the plane" << endl;
  }

  gmtl::Point3f intersectPoint = myRay.origin + mRay.dir * isect; 

General Math

How do I use GMTL's C math abstraction?

In your application, you simply include the

What operations does GMTL's C math abstraction have?

GMTL provides function calls for everything that the standard C math library has. But they are templated functions, so you don't have to worry about what data types you are providing for argments.

What about PI?

There is a floating point value provided for the number Pi. You can reference it using 'gmtl::Math::PI'.

There are also constants provided for Pi divided by 2 and Pi divided by 4, both of which are commonly used in graphical applications. These additional values can be referenced by 'gmtl::Math::PI_OVER_2' and 'gmtl::Math::PI_OVER_4'.

How do I convert from degrees to radians?

Use the deg2Rad function.

  float degrees = 90;
  float radians = gmtl::Math::deg2Rad( degrees );

How do I convert from radians to degrees?

Use the rad2Deg function.

  float radians = 1.57;
  float degrees = gmtl::Math::rad2Deg( radians );


Generated on Mon Apr 7 15:29:24 2003 for GenericMathTemplateLibrary by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002