pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
NAMEpfDoubleDCS - Create, modify and get the matrix of a double-precision
dynamic coordinate system.
FUNCTION SPECIFICATION
#include <Performer/pf/pfDoubleDCS.h>
pfDoubleDCS::pfDoubleDCS();
static pfType * pfDoubleDCS::getClassType(void);
void pfDoubleDCS::setTrans(double x, double y, double z);
void pfDoubleDCS::setRot(double h, double p, double r);
void pfDoubleDCS::setCoord(pfCoordd *coord);
void pfDoubleDCS::setScale(double s);
void pfDoubleDCS::setScale(double x, double y, double z);
void pfDoubleDCS::setMat(pfMatrix4d &m);
void pfDoubleDCS::getMat(pfMatrix4d &m);
const pfMatrix4d* pfDoubleDCS::getMatPtr(void);
void pfDoubleDCS::setMatType(uint val);
uint pfDoubleDCS::getMatType();
PARENT CLASS FUNCTIONS
The OpenGL Performer class pfDoubleDCS is derived from the parent class
pfDoubleSCS, so each of these member functions of class pfDoubleSCS are
also directly usable with objects of class pfDoubleDCS. This is also
true for ancestor classes of class pfDoubleSCS.
void pfDoubleSCS::getMat(pfMatrix4d &mat);
const pfMatrix4d* pfDoubleSCS::getMatPtr(void);
Since the class pfDoubleSCS is itself derived from the parent class
pfGroup, objects of class pfDoubleDCS can also be used with these
functions designed for objects of class pfGroup.
int pfGroup::addChild(pfNode *child);
int pfGroup::insertChild(int index, pfNode *child);
int pfGroup::replaceChild(pfNode *old, pfNode *new);
int pfGroup::removeChild(pfNode* child);
int pfGroup::searchChild(pfNode* child);
Page 1
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfNode * pfGroup::getChild(int index);
int pfGroup::getNumChildren(void);
int pfGroup::bufferAddChild(pfNode *child);
int pfGroup::bufferRemoveChild(pfNode *child);
Since the class pfGroup is itself derived from the parent class pfNode,
objects of class pfDoubleDCS can also be used with these functions
designed for objects of class pfNode.
pfGroup * pfNode::getParent(int i);
int pfNode::getNumParents(void);
void pfNode::setBound(pfSphere *bsph, int mode);
int pfNode::getBound(pfSphere *bsph);
pfNode* pfNode::clone(int mode);
pfNode* pfNode::bufferClone(int mode, pfBuffer *buf);
int pfNode::flatten(int mode);
int pfNode::setName(const char *name);
const char * pfNode::getName(void);
pfNode* pfNode::find(const char *pathName, pfType *type);
pfNode* pfNode::lookup(const char *name, pfType* type);
int pfNode::isect(pfSegSet *segSet, pfHit **hits[]);
void pfNode::setTravMask(int which, uint mask, int setMode,
int bitOp);
uint pfNode::getTravMask(int which);
void pfNode::setTravFuncs(int which, pfNodeTravFuncType pre,
pfNodeTravFuncType post);
void pfNode::getTravFuncs(int which, pfNodeTravFuncType *pre,
pfNodeTravFuncType *post);
void pfNode::setTravData(int which, void *data);
void * pfNode::getTravData(int which);
void pfNode::setTravMode(int which, int mode, int val);
int pfNode::getTravMode(int which, int mode) const;
Since the class pfNode is itself derived from the parent class pfObject,
objects of class pfDoubleDCS can also be used with these functions
designed for objects of class pfObject.
void* pfObject::operator new(size_t);
void* pfObject::operator new(size_t, pfFluxMemory *fmem);
void pfObject::setUserData(void *data);
void pfObject::setUserData(int slot, void *data);
void* pfObject::getUserData(pfObject *obj);
void* pfObject::getUserData(pfObject *obj, int slot);
int pfObject::getNumUserData();
Since the class pfObject is itself derived from the parent class
pfMemory, objects of class pfDoubleDCS can also be used with these
functions designed for objects of class pfMemory.
Page 2
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
void* pfMemory::getData(const void *ptr);
pfType * pfMemory::getType();
int pfMemory::isOfType(pfType *type);
int pfMemory::isExactType(pfType *type);
const char * pfMemory::getTypeName();
int pfMemory::copy(pfMemory *src);
int pfMemory::compare(const pfMemory *mem);
void pfMemory::print(uint which, uint verbose, char *prefix,
FILE *file);
int pfMemory::getArena(void *ptr);
void* pfMemory::getArena();
int pfMemory::ref();
int pfMemory::unref();
int pfMemory::unrefDelete();
int pfMemory::unrefGetRef();
int pfMemory::getRef();
int pfMemory::checkDelete();
int pfMemory::isFluxed();
void * pfMemory::getArena();
int pfMemory::getSize();
DESCRIPTION
A pfDoubleDCS (Double-precision Dynamic Coordinate System) is a
pfDoubleSCS whose matrix can be modified. It is useful for generating
scenes with objects very far away from the origin.
new pfDoubleDCS creates and returns a handle to a pfDoubleDCS. Like
other pfNodes, pfDoubleDCSes are always allocated from shared memory and
cannot be created statically, on the stack or in arrays. pfDoubleDCSes
should be deleted using pfDelete rather than the delete operator.
pfDoubleDCS::getClassType returns the pfType* for the class pfDoubleDCS.
The pfType* returned by pfDoubleDCS::getClassType is the same as the
pfType* returned by invoking the virtual function getType on any instance
of class pfDoubleDCS. Because OpenGL Performer allows subclassing of
built-in types, when decisions are made based on the type of an object,
it is usually better to use the member function isOfType to test if an
object is of a type derived from a Performer type rather than to test for
strict equality of the pfType*'s.
The initial transformation is the identity matrix. The transformation of
a pfDoubleDCS can be set by specifying a matrix or translation, scale and
rotation. When independently setting translation, rotation, and scale,
the pfDoubleDCS matrix is computed as S*R*T, where S is the scale, R is
the rotation, and T is the translation. The order of effect is then scale
followed by rotation followed by translation.
pfDoubleDCS operations are absolute rather than cumulative. For example:
dcs->setTrans(2.0f, 0.0f, 0.0f);
dcs->setTrans(1.0f, 0.0f, 0.0f);
Page 3
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
specifies a translation by 1 unit along the X coordinate axis, not 3
units.
By default a pfDoubleDCS uses a bounding sphere which is dynamic, so it
is automatically updated when the pfDoubleDCS transformation is changed
or when children are added, deleted or changed. This behavior may be
changed using pfNode::setBound. The bound for a pfDoubleDCS encompasses
all B(i)*S*R*T, where B(i) is the bound for the child 'i' and S*R*T
represents the scale, rotation, and translation transformation of the
pfDoubleDCS.
pfDoubleDCS::setTrans sets the translation part of the pfDoubleDCS to (x,
y, z). The rotational portion of the matrix is unchanged.
pfDoubleDCS::setScale sets the scale portion of the pfDoubleDCS to scale
uniformly by a scale factor s. This supersedes the previous scale
leaving the rotation and translation unchanged. pfDoubleDCS::setScale
specifies a non-uniform scale of x, y, z.
pfDoubleDCS::setRot sets the rotation portion of the matrix:
h Specifies heading, the rotation about the Z axis.
p Specifies pitch, the rotation about the X axis.
r Specifies roll, rotation about the Y axis.
The matrix created is R*P*H, where R is the roll transform, P is the
pitch transform and H is the heading transform. The new (h,p,r)
combination replaces the previous specification, leaving the scale and
translation unchanged. The convention is natural for a model in which +Y
is "forward," +Z is "up" and +X is "right". To maintain 1/1000 degree
resolution in the single precision arithmetic used internally for sine
and cosine calculations, the angles h, p, r should be in the range of
-7500 to +7500 degrees.
pfDoubleDCS::setCoord sets the rotation and translation portion of the
pfDoubleDCS according to coord. This is equivalent to:
dcs->setRot(coord->hpr[0], coord->hpr[1], coord->hpr[2]);
dcs->setTrans(coord->xyz[0], coord->xyz[1], coord->xyz[2]);
pfDoubleDCS::setMat sets the transformation matrix for the pfDoubleDCS to
m.
Normally pfDoubleDCS::setMat is used as a replacement for the above
routines which individually set the scale, rotation and translational
components. The mechanisms can be combined but only if the supplied
matrix can be represented as scale followed by a rotation followed by a
translation (e.g. a point pt is transformed by the matrix as: pt' =
Page 4
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pt*S*R*T), which implies that no shearing or non-uniform scaling is
present.
pfDoubleDCS::setMatType allows the specification of information about the
type of transformation the matrix represents. This information allows
Performer to speed up some operations. The matrix type is specified as
the OR of
PFMAT_TRANS:
matrix may include a translational component in the 4th row.
PFMAT_ROT
matrix may include a rotational component in the left upper 3X3
submatrix.
PFMAT_SCALE
matrix may include a uniform scale in the left upper 3X3
submatrix.
PFMAT_NONORTHO
matrix may include a non-uniform scale in the left upper 3X3
submatrix.
PFMAT_PROJ
matrix may include projections.
PFMAT_HOM_SCALE
matrix may have mat[4][4] != 1.
PFMAT_MIRROR
matrix may include mirroring transformation that switches
between right handed and left handed coordinate systems.
pfDoubleDCS::getMatType returns the matrix type as set by
pfDoubleDCS::setMatType. If no matrix type is set the default is ~0,
corresponding to a general matrix.
The transformation of a pfDoubleDCS affects all its children. As the
hierarchy is traversed from top to bottom, each new matrix is pre-
multiplied to create the new transformation. For example, if DoubleDCSb
is below DoubleDCSa in the scene graph, any geometry G below DoubleDCSa
is transformed as G*DoubleDCSb*DoubleDCSa.
pfNode::flatten cannot flatten pfDoubleDCSes since they may change at
run-time. In this case pfNode::flatten will compute a pfDoubleSCS
representing the accumulated static transformation that the pfDoubleDCS
inherits and insert it above the pfDoubleDCS. Static transformations
below a pfDoubleDCS are flattened as usual. See pfNode::flatten for more
details.
The presence of transformations in the scene graph impacts the
Page 5
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
performance of intersection, culling and drawing. pfGeoSet culling (see
PFCULL_GSET in pfChannel::setTravMode) is disabled in portions of the
scene graph below pfDoubleDCSes.
Both pre and post CULL and DRAW callbacks attached to a pfDoubleDCS (-
pfNode::setTravFuncs) will be affected by the transformation represented
by the pfDoubleDCS, i.e. - the pfDoubleDCS matrix will already have been
applied to the matrix stack before the pre callback is called and will be
popped only after the post callback is called.
pfDoubleDCS::getMat copies the transformation matrix value from the
pfDoubleDCS into the matrix m. For faster matrix access,
pfDoubleDCS::getMatPtr can be used to get a const pointer to the
pfDoubleDCS's matrix.
pfDoubleDCS nodes are useful for modeling objects very far from the
origin or the database - so far away that the resolution of floating
point numbers isn't high enough to express small movements of the
objects. We use a common example to describe this feature of pfDoubleDCS
nodes:
When modeling a round Earth and placing the origin in the center of the
Earth, the surface of the Earth is very far from the origin. The
resolution of floating point numbers is not high enough to express
translations of 1 cm on the surface of the Earth.
Since the underlying OpenGL implementation does not support double-
precision math, modeling in double precision numbers does not help.
Instead, we observe that when we fly/drive over the surface of the Earth,
we want to depict small translations only in the vicinity of the camera.
Translating an object 200 miles away from the camera by 1 cm has
negligible effect on the output image. pfDoubleDCS nodes provide a
method to translate the camera position to the origin of the database
every frame, and to correct the relative position of the scene to that of
the camera. This way, all the geometry in the vicinity of the camera
becomes close enough to the origin that the resolution of floating point
numbers is high enough to express small object translations.
In more practical terms, given a camera position at E = (Ex, Ey, Ez), and
a database tile position at T = (Tx, Ty, Tz), we build a scene graph with
a single pfDoubleDCS node at the root, and one pfDoubleDCS node above
each tile. We set the channel eyepoint in the origin by seting the
channel viewing matrix to the identity matrix. We then use the
pfDoubleDCS node at the root to express the real camera position and the
pfDoubleDCS node above each tile to express the position of the tile. We
load the translation -E = (-Ex, -Ey, -Ez) onto the root pfDoubleDCS and
the translation T = (Tx, Ty, Tz) onto the tile pfDoubleDCS. When
Performer traverses the scene graph, it composes the final translation
T-E = (Tx-Ex, Ty-Ey, Tz-Ez). When the camera is fairly close to the tile,
this translation is small enough that even floating point numbers provide
a high enough resolution for it.
Page 6
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
Coding the above example we get:
void
setDoublePrecisionDCS (pfChannel *chan,
pfDoubleDCS *ddcs,
pfCoordd *coord)
{
pfMatrix4d mat, invMat;
// Channel camera is at origin.
chan -> setViewMat(pfIdentMat);
mat -> makeCoordd (coord);
invMat -> invertOrthoN (mat);
// Put inverse of camera position in double DCS.
ddcs -> setMat (invMat);
}
where coord contains the camera position, and ddcs is the pfDoubleDCS at
the root of the scene graph. Every time the camera position changes, we
have to update the pfDoubleDCS at the root of the scene graph. The tiles
contain vertex coordinates relative to the tile origin. This origin is
translated by the tile pfDoubleDCS to the correct position.
Important Note
During the Performer CULL traversal, Performer maintains the accumulated
matrix from the root of the scene graph to the current node. Performer
also maintains the precision level of this accumulated matrix. When the
last matrix node on the path from the root of the scene graph to a node
is a double-precision matrix, the CULL test is ignored on this node. In
other words, all the nodes whose closest parent matrix node is a double-
precision node are accepted by the CULL traversal and are always drawn.
Performer does not CULL these nodes because the standard Performer node
bounding sphere is single-precision and can not correctly express double
precision matrix operations. Converting to double-precision bounding
spheres would have slowed down the CULL traversal.
There is a simple workaround that forces Performer back to single
precision mode: Add a pfSCS node below the lowest pfDouble?CS node. Use
an identity matrix for the new pfSCS node. The pfSCS node demotes the
CULL traversal back to single-precision mode, and the CULL test becomes
active again.
Page 7
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C++ Reference Pages
pfScene
|
pfDoubleSCS
|
pfDoubleSCS
|
pfSCS
|
<Geometry>
The sample code under
/usr/share/Performer/src/pguide/libpf/C/doubleDCS2.c demonstrates how to
create a scene graph with the correct node setup.
SEE ALSO
pfCoord, pfGroup, pfChannel, pfLookupNode, pfFlatten, pfMatrix, pfNode,
pfDCS, pfSCS, pfFCS, pfDoubleSCS, pfDoubleFCS, pfScene, pfTraverser,
pfDelete
Page 8