/** @file gmtlfaq.doxygen
*
*/
/** @page gmtlfaq Generic Math Template Library FAQ
* Welcome to the GMTL frequently asked questions list.
*
* Topics:
*
* - @ref faqgeneral
* - @ref Vectors
* - @ref Matrices
* - @ref Quaternions
* - @ref Collision
* - @ref General
* - @ref CompileProblems
*
*
* @section faqgeneral General Questions about GMTL
*
* @subsection faqwhytemplates 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.
*
* @code
*
* gmtl::Matrix44f myMatrix;
* gmtl::Vec3f myVector;
* gmtl::Quatf myQuaternion;
*
* @endcode
*
* Similarly, GMTL's function calls also need to have this namespace:
*
* @code
*
* gmtl::identity( myMatrix );
* gmtl::normalize( myVector );
*
* @endcode
*
* Developers can also specify that they are using a particular namespace
* in their code, aleviating the need to specify the namespace for each
* object.
*
* @code
*
* using namespace gmtl
* {
* Matrix44f myMatrix;
* Vec3f myVector;
* normalize( myVector );
* };
*
* @endcode
*
* 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.
*
* @code
*
* float cosine = gmtl::Math::cos( 3.14 );
* float minimum = gmtl::Math::Min( 3.0, 1.4, -43.2 );
*
* @endcode
*
*
* 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:
*
* @code
*
* gmtl::Matrix44f myMat;
* int row, column = 2;
* float data = myMat[column][row];
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::EulerAngleXYZf myEuler;
* gmtl::Quatf myQuat = gmtl::make( myEuler );
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::AxisAnglef myAA = gmtl::make( myMat );
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::EulerAngleXYZf myEuler;
* gmtl::Quatf myQuat;
*
* gmtl::set( myQuat, myEuler );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myFullMat;
* gmtl::Matrix44f myTransMat;
*
* myTransMat = gmtl::makeTrans( myFullMat );
*
* @endcode
*
* 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:
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::CoordVec3EulerAngleXYZf myCoord;
*
* gmtl::setTrans( myMat, myCoord );
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Vec3f xDestAxis, yDestAxis, zDestAxis;
* gmtl::Vec3f xSrcAxis, ySrcAxis, zSrcAxis;
*
* gmtl::Matrix44f myMat = gmtl::makeDirCos( xDestAxis, yDestAxis, zDestAxis, xSrcAxis, ySrcAxis, zSrcAxis );
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* gmtl::Quatf myQuat = gmtl::makePure( myVec );
*
* @endcode
*
* You can use the makeVec function to extract the axis of rotation from a
* quaternion object.
*
* @code
*
* gmtl::Quatf myQuat;
* gmtl::Vec3f myVec = gmtl::makeVec( myQuat );
*
* @endcode
*
* The makeNormal function allows you to create a normalized object from a
* source object. Usually this will deal with vectors.
*
* @code
*
* gmtl::Vec3f srcVec;
* gmtl::Vec3f normVec = gmtl::makeNormal( srcVec );
*
* @endcode
*
* The makeXRot, makeYRot, makeZRot functions can be used to extract rotational
* data about particular axes.
*
* @code
*
* gmtl::Matrix44f myMat;
* float xrot = gmtl::makeXRot( myMat );
*
* @endcode
*
* 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:
*
* @code
*
* gmtl::Matrix myMatrix; //This will not work
* gmtl::Matrix44f myMatrix; //This is correct
*
* @endcode
*
* 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:
*
* @code
*
* gmtl::Matrix44f myMatrix;
* gmtl::Matrix myMatrix;
*
* @endcode
*
* 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.
*
* @code
*
* typedef gmtl::Matrix Mat;
* typedef gmtl::Vec Vector;
*
* @endcode
*
* These type definitions make the following pairs of object instantiations
* equivalent:
*
* @code
*
* gmtl::Matrix myMatrix;
* Mat myMatrix;
*
* gmtl::Vec myVec;
* Vector myVec;
*
* @endcode
*
*
* @section Spatial 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.
*
*
* @section Howto How Do I ...?
*
* @subsection Vectors 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.
*
* @code
*
* 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;
*
* @endcode
*
*
* How do I find the cross product of 2 vectors?
*
* You can use the makeCross function, which returns another vector.
*
* @code
*
* gmtl::Vec3f vecA, vecB, crossVec;
* crossVec = gmtl::makeCross( vecA, vecB );
*
* @endcode
*
*
* 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).
*
* @code
*
* gmtl::Vec3d vecA, vecB;
* double x = gmtl::dot( vecA, vecB );
*
* @endcode
*
*
* How do I check if a vector is normalized?
*
* Use the isNormalized function, which returns a boolean value.
*
* @code
*
* gmtl::Vec3f myVec;
* if ( gmtl::isNormalized( myVec ) )
* {
* cout << "Vector is normalized" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* gmtl::normalize( myVec );
*
* @endcode
*
*
* 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'.
*
* @code
*
* gmtl::Vec3f vecA, vecB;
* if ( vecA == vecB )
* {
* cout << "Vectors are equal" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* float length = gmtl::length( myVec );
*
* @endcode
*
* 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.
*
* @code
*
* float lengthSq = gmtl::lengthSquared( myVec );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* myVec *= -1;
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f resultVec, vecA. vecB;
* float weight = 0.333;
*
* gmtl::lerp( resultVec, weight, vecA, vecB );
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec, anotherVec;
* float myScalar = 3.5;
*
* myVec *= myScalar;
* anotherVec = myVec * myScalar;
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f vecA, vecB, vecC;
*
* vecA = vecB * vecC;
* vecA = vecB / vecC;
* vecA += vecB;
* vecA = vecB + vecC;
* vecA -= vecC;
* vecA = vecB - vecC;
*
* @endcode
*
* etc.
*
*
*
* @subsection Matrices Matrices
* How do I multiply matrices?
*
* The simplest way to multiply one matrix by another is to use the * operator.
*
* @code
*
* gmtl::Matrix44f A, B, C;
* A = B * C;
*
* @endcode
*
* Note that when multiplying matrices, the ordering matters. The following
* line of code could make matrix A have a different result:
*
* @code
*
* A = C * B;
*
* @endcode
*
* Alternatively, you can use the preMult and postMult functions.
*
* This preMult call is the same as "A = B * A;"
*
* @code
*
* gmtl::preMult( A, B );
*
* @endcode
*
* This postMult call is the same as "A = A * B;"
*
* @code
*
* gmtl::postMult( A, B );
*
* @endcode
*
* The *= operator also acts as a postMult function.
*
* @code
*
* A *= B;
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::Matrix23d otherMat;
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Matrix< float, 4, 6 > newMatrix;
*
* @endcode
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* gmtl::Matrix44f myMat = gmtl::makeTrans< gmtl::Matrix44f >( myVec );
*
* @endcode
*
*
* How do I create a matrix from a point?
*
* Using the make function, you can create a purely translational matrix from a
* point.
*
* @code
*
* gmtl::Point3f myPoint;
* gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myPoint );
*
* @endcode
*
*
* How do I create a matrix from a quaterion?
*
* Using the make function, you can create a purely rotational matrix from a
* quaternion object.
*
* @code
*
* gmtl::Quatf myQuat;
* gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myQuat );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::EulerAngleXYZf myEulerAngle;
* gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myEulerAngle );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::AxisAnglef myAxisAngle;
* gmtl::Matrix44f myMat = gmtl::make< gmtl::Matrix44f >( myAxisAngle );
*
* @endcode
*
*
* How do I scale a matrix?
*
* @code
*
* gmtl::Matrix44f myMat;
* float scale = 0.5;
*
* gmtl::setScale( myMat, scale );
*
* @endcode
*
*
* How do I copy a matrix?
*
* You can simply use the '=' operator to copy from one matrix to another.
*
* @code
*
* gmtl::Matrix44f matA, matB;
* matA = matB;
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* float x = myMat[3][2];
*
* @endcode
*
*
* 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.
*
* @code
*
* 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 );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::Point3f myPoint;
* gmtl::Vec3f myVec;
*
* myVec = gmtl::makeTrans< gmtl::Vec3f >( myMat );
* myPoint = gmtl::makeTrans< gmtl::Point3f >( myMat );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::identity( myMat );
*
* @endcode
*
*
* How do I set a matrix to contain all zeros?
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::zero( myMat );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::invert( myMat );
*
* @endcode
*
* You can optionally force a full inversion by using the invertFull function.
*
* @code
*
* gmtl::invertFull( myMat );
*
* @endcode
*
*
* How do I transpose a matrix?
*
* Use the transpose function.
*
* @code
*
* gmtl::Matrix44f myMat;
* gmtl::transpose( myMat );
*
* @endcode
*
*
* How do I transform a point using a matrix?
*
* This will perform a full transformation on the point.
*
* @code
*
* gmtl::Point3f myPoint;
* gmtl::Matrix44f myMat;
* gmtl::xform( myPoint, myMat, myPoint );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f myVec;
* gmtl::Matrix44f myMat;
* gmtl::xform( myVec, myMat, myVec );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Matrix44f myMat;
* glMultMatrixf( myMat.getData() );
*
* @endcode
*
* Note that GMTL matrix data is also safe to use for other graphics APIs
* such as DirectX, Performer, and OpenSG.
*
*
*
* @subsection Quaternions Quaternions
* How do I create quaternions?
*
* You can create quaternions directly using known values.
*
* @code
*
* float x = 1.0;
* float y, z, w = 0.0;
* gmtl::Quatf myQuat(x, y, z, w);
*
* @endcode
*
* You can also create quaternions based on other rotational types, such
* as an EulerAngle or matrix.
*
* @code
*
* gmtl::EulerAngleXYZf myEuler;
* gmtl::Matrix44f myMat;
* myQuat = gmtl::make( myEuler );
* myQuat = gmtl::make( myMat );
*
* @endcode
*
*
* How do I multiply quaternions?
*
* Simply use the * and *= operators.
*
* @code
*
* gmtl::Quatf quatA, quatB, quatC;
* quatA *= quatB;
* quatC = quatA * quatB;
*
* @endcode
*
*
* How do I combine quaternion rotations?
*
* This is the same as multiplying quaternions.
*
* @code
*
* gmtl::Quatf quatA, quatB, quatC;
* quatA *= quatB;
* quatC = quatA * quatB;
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Quatf resultQuat, originQuat, targetQuat;
* float amount = 0.5;
*
* gmtl::slerp( resultQuat, amount, originQuat, targetQuat );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Quatf resultQuat, originQuat, targetQuat;
* float amount = 0.5;
*
* gmtl::lerp( resultQuat, amount, originQuat, targetQuat );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Vec3f originVec, targetVec;
* gmtl::Quatf myQuat;
*
* gmtl::normalize( originVec );
* gmtl::normalize( targetVec );
* myQuat = gmtl::makeRot( originVec, targetVec );
*
* @endcode
*
*
* How do I invert a quaternion?
*
* Use the invert function.
*
* @code
*
* gmtl::Quatf myQuat;
* gmtl::invert( myQuat );
*
* @endcode
*
*
* How do I conjugate a quaternion?
*
* Use the conj function.
*
* @code
*
* gmtl::Quatf myQuat;
* gmtl::conj( myQuat );
*
* @endcode
*
*
* How do I check if 2 quaternions are the same?
*
* Use the == and != operators.
*
* @code
*
* gmtl::Quatf quatA, quatB;
* if (quatA == quatB)
* {
* cout << "Quaternions are equal" << endl;
* }
* if (quatA != quatB)
* {
* cout << "Quaternions are not equal" << endl;
* }
*
* @endcode
*
*
*
* @subsection Collision 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.
*
* @code
*
* gmtl::Point3f myPoint;
* gmtl::Spheref mySphere;
*
* if ( gmtl::isInVolume( mySphere, myPoint ) )
* {
* cout << "Point is inside the sphere" << endl;
* }
*
* @endcode
*
*
* How do I test if a point is on the surface of a sphere?
*
* Use the isOnVolume function, which returns a boolean value.
*
* @code
*
* gmtl::Point3f myPoint;
* gmtl::Spheref mySphere;
*
* if ( gmtl::isOnVolume( mySphere, myPoint ) )
* {
* cout << "Point is on the sphere" << endl;
* }
*
* @endcode
*
* 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.
*
* @code
*
* float tolerance = 0.001;
* if ( gmtl::isOnVolume( mySphere, myPoint, tolerance ))
* {
* cout << "Point is on the sphere" << endl;
* }
*
* @endcode
*
*
* How do I test if one sphere is contained by another?
*
* Use the isInVolume function, which returns a boolean value.
*
* @code
*
* gmtl::Spheref sphereA, sphereB;
* if ( gmtl::isInVolume( sphereA, sphereB ) )
* {
* cout << "Sphere is within the other sphere" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* 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;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Spheref mySphere;
* gmtl::Point3f myPoint;
*
* gmtl::extendVolume( mySphere, myPoint );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Spheref mySphere;
* std::vector myPoints;
*
* gmtl::extendVolume( mySphere, myPoints );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::Spheref sphereA, sphereB;
*
* gmtl::extendVolume( sphereA, sphereB );
*
* @endcode
*
*
* How do I test if two AABoxes intersect?
*
* Use the intersect function, which returns a boolean value.
*
* @code
*
* gmtl::AABoxf boxA, boxB;
*
* if ( gmtl::intersect( boxA, boxB ) )
* {
* cout << "Boxes intersect" << endl;
* }
*
* @endcode
*
*
* How do I test if an AABox is contained by another?
*
* Use the isInVolume function, which returns a boolean value.
*
* @code
*
* gmtl::AABoxf boxA, boxB;
*
* if ( gmtl::isInVolume( boxA, boxB ) )
* {
* cout << "Box A contains box B" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::AABoxf myBox;
* gmtl::Point3f myPoint;
*
* if ( gmtl::isInVolume( myBox, myPoint ) )
* {
* cout << "The point is inside the box" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* 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;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::AABox myBox;
* gmtl::Point3f myPoint;
*
* gmtl::extendVolume( myBox, myPoint );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::AABoxf boxA, boxB;
*
* gmtl::extendVolume( boxA, boxB );
*
* @endcode
*
*
* 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.
*
* @code
*
* gmtl::AABoxf myBox;
* gmtl::Spheref mySphere;
*
* gmtl::extendVolume( myBox, mySphere );
*
* @endcode
*
*
* How do I test if a sphere intersects with an AABox?
*
* Use the intersect function, which returns a boolean value.
*
* @code
*
* gmtl::AABoxf myBox;
* gmtl::Spheref mySphere;
*
* if ( gmtl::intersect( myBox, mySphere ) 0
* {
* cout << "Box and sphere intersect\n" << endl;
* }
*
* @endcode
*
*
* 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.
*
* @code
*
* 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;
*
* @endcode
*
*
* @subsection General General Math
* How do I use GMTL's C math abstraction?
*
* In your application, you simply include the gmtl/Math.h header file. Then
* you can use any of the functions by appending the gmtl::Math:: namespace
* prefix onto the function name.
*
* 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 arguments.
*
*
* 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.
*
* @code
*
* float degrees = 90;
* float radians = gmtl::Math::deg2Rad( degrees );
*
* @endcode
*
*
* How do I convert from radians to degrees?
*
* Use the rad2Deg function.
*
* @code
*
* float radians = 1.57;
* float degrees = gmtl::Math::rad2Deg( radians );
*
* @endcode
*
* @subsection CompileProblems Common compile problems
*
* Errors with Vec/Point expression conversions
*
* Example error: error: no matching function for call
* to `lengthSquared(gmtl::VecBase, gmtl::VecBase, gmtl::meta::VecPlusBinary> >)'
*
* GMTL makes extensive use of expression templates. These templates come into
* play when evaluating statement such as:
*
* @code
*
* gmtl::Vec3f vec1, vec2, vec3;
* vec1 = vec2 + (vec3 * 6.0);
*
* @endcode
*
* When evaluating the expression on the second line, GMTL creates an expression
* template tree to fully evaluate this expression when = is called. The details
* of this process are normally hidden from the user, but can come to the forefront
* when a method expects a Vec or Point argument and is passed an expression. For example:
*
*
* @code
*
* void myMethod(gmtl::Vec3f vec)
* { ... }
*
* gmtl::Vec3f vec1, vec2;
*
* myMethod(vec1); // Works correctly
* myMethod(vec1 + vec2); // Fails to compile
*
* @endcode
*
* The reason the second line fails to compile is that the type for "vec1 + vec2" is not
* a Vec3f. It is an expression template that describes how to sum two Vec3f's.
* (You may expect an autoconversion to happen, but it does not because of template argument
* deduction rules).
*
* There are two solutions to this, either explicitly construct a temporary
* object to pass to the method (which is what an auto conversion would do anyway) or
* write the method to handle expression templates. This second option is not difficult,
* but does require a further understanding of GMTL then is documented here.
*
* Here is how the first option could be used:
*
* @code
*
* myMethod(gmtl::Vec3f(vec1 + vec2)); // Creates a temporary to pass in
*
* @endcode
*
*/