pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
NAME
pfNewDoubleDCS, pfGetDoubleDCSClassType, pfDoubleDCSTrans,
pfDoubleDCSRot, pfDoubleDCSCoord, pfDoubleDCSScale, pfDoubleDCSScaleXYZ,
pfDoubleDCSMat, pfGetDoubleDCSMat, pfGetDoubleDCSMatPtr,
pfDoubleDCSMatType, pfGetDoubleDCSMatType - Create, modify and get the
matrix of a double-precision dynamic coordinate system.
FUNCTION SPECIFICATION
#include <Performer/pf.h>
pfDoubleDCS * pfNewDoubleDCS(void);
pfType * pfGetDoubleDCSClassType(void);
void pfDoubleDCSTrans(pfDoubleDCS *dcs, double x,
double y, double z);
void pfDoubleDCSRot(pfDoubleDCS *dcs, double h, double p,
double r);
void pfDoubleDCSCoord(pfDoubleDCS *dcs, pfCoordd *coord);
void pfDoubleDCSScale(pfDoubleDCS *dcs, double s);
void pfDoubleDCSScaleXYZ(pfDoubleDCS *dcs, double x,
double y, double z);
void pfDoubleDCSMat(pfDoubleDCS *dcs, pfMatrix4d m);
void pfGetDoubleDCSMat(pfDoubleDCS *dcs, pfMatrix4d m);
const pfMatrix4d* pfGetDoubleDCSMatPtr(pfDoubleDCS *dcs);
void pfDoubleDCSMatType(pfDoubleDCS *dcs, uint val);
uint pfGetDoubleDCSMatType(pfDoubleDCS *dcs);
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. Casting an
object of class pfDoubleDCS to an object of class pfDoubleSCS is taken
care of automatically. This is also true for casts to objects of
ancestor classes of class pfDoubleSCS.
void pfGetDoubleSCSMat(pfDoubleSCS *scs, pfMatrix4d mat);
const pfMatrix4d* pfGetDoubleSCSMatPtr(pfDoubleSCS *scs);
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.
Page 1
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
int pfAddChild(pfGroup *group, pfNode *child);
int pfInsertChild(pfGroup *group, int index, pfNode *child);
int pfReplaceChild(pfGroup *group, pfNode *old, pfNode *new);
int pfRemoveChild(pfGroup *group, pfNode* child);
int pfSearchChild(pfGroup *group, pfNode* child);
pfNode * pfGetChild(const pfGroup *group, int index);
int pfGetNumChildren(const pfGroup *group);
int pfBufferAddChild(pfGroup *group, pfNode *child);
int pfBufferRemoveChild(pfGroup *group, 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 * pfGetParent(const pfNode *node, int i);
int pfGetNumParents(const pfNode *node);
void pfNodeBSphere(pfNode *node, pfSphere *bsph, int mode);
int pfGetNodeBSphere(pfNode *node, pfSphere *bsph);
pfNode* pfClone(pfNode *node, int mode);
pfNode* pfBufferClone(pfNode *node, int mode, pfBuffer *buf);
int pfFlatten(pfNode *node, int mode);
int pfNodeName(pfNode *node, const char *name);
const char * pfGetNodeName(const pfNode *node);
pfNode* pfFindNode(pfNode *node, const char *pathName,
pfType *type);
pfNode* pfLookupNode(const char *name, pfType* type);
int pfNodeIsectSegs(pfNode *node, pfSegSet *segSet,
pfHit **hits[]);
void pfNodeTravMask(pfNode *node, int which, uint mask,
int setMode, int bitOp);
uint pfGetNodeTravMask(const pfNode *node, int which);
void pfNodeTravFuncs(pfNode* node, int which,
pfNodeTravFuncType pre, pfNodeTravFuncType post);
void pfGetNodeTravFuncs(const pfNode* node, int which,
pfNodeTravFuncType *pre, pfNodeTravFuncType *post);
void pfNodeTravData(pfNode *node, int which, void *data);
void * pfGetNodeTravData(const pfNode *node, int which);
void pfNodeTravMode(pfNode* node, int which, int mode,
int val);
int pfGetNodeTravMode(const pfNode* node, int which,
int mode);
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 pfUserDataSlot(pfObject *obj, int slot, void *data);
void pfUserData(pfObject *obj, void *data);
Page 2
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
void* pfGetUserDataSlot(pfObject *obj, int slot);
void* pfGetUserData(pfObject *obj);
int pfGetNumUserData(pfObject *obj);
int pfGetNamedUserDataSlot(const char *name);
const char* pfGetUserDataSlotName(int slot);
int pfGetNumNamedUserDataSlots(void);
int pfDeleteGLHandle(pfObject *obj);
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.
pfType * pfGetType(const void *ptr);
int pfIsOfType(const void *ptr, pfType *type);
int pfIsExactType(const void *ptr, pfType *type);
const char * pfGetTypeName(const void *ptr);
int pfRef(void *ptr);
int pfUnref(void *ptr);
int pfUnrefDelete(void *ptr);
int pfUnrefGetRef(void *ptr);
int pfGetRef(const void *ptr);
int pfCopy(void *dst, void *src);
int pfDelete(void *ptr);
int pfIsFluxed(void *ptr);
int pfCompare(const void *ptr1, const void *ptr2);
void pfPrint(const void *ptr, uint which, uint verbose,
FILE *file);
void * pfGetArena(void *ptr);
PARAMETERS
dcs identifies a pfDoubleDCS
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.
pfNewDoubleDCS creates and returns a handle to a pfDoubleDCS. Like other
pfNodes, pfDoubleDCSes are always allocated from shared memory and can be
deleted using pfDelete.
pfGetDoubleDCSClassType returns the pfType* for the class pfDoubleDCS.
The pfType* returned by pfGetDoubleDCSClassType is the same as the
pfType* returned by invoking pfGetType 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 pfIsOfType 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
Page 3
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
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:
pfDoubleDCSTrans(dcs, 2.0f, 0.0f, 0.0f);
pfDoubleDCSTrans(dcs, 1.0f, 0.0f, 0.0f);
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 pfNodeBSphere. 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.
pfDoubleDCSTrans sets the translation part of the pfDoubleDCS to (x, y,
z). The rotational portion of the matrix is unchanged.
pfDoubleDCSScale 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. pfDoubleDCSScaleXYZ
specifies a non-uniform scale of x, y, z.
pfDoubleDCSRot 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.
pfDoubleDCSCoord sets the rotation and translation portion of the
pfDoubleDCS according to coord. This is equivalent to:
Page 4
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
pfDoubleDCSRot(dcs, coord->hpr[0], coord->hpr[1], coord->hpr[2]);
pfDoubleDCSTrans(dcs, coord->xyz[0], coord->xyz[1], coord->xyz[2]);
pfDoubleDCSMat sets the transformation matrix for dcs to m.
Normally pfDoubleDCSMat 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' = pt*S*R*T), which
implies that no shearing or non-uniform scaling is present.
pfDoubleDCSMatType 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.
pfGetDoubleDCSMatType returns the matrix type as set by
pfDoubleDCSMatType. 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
Page 5
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
is below DoubleDCSa in the scene graph, any geometry G below DoubleDCSa
is transformed as G*DoubleDCSb*DoubleDCSa.
pfFlatten cannot flatten pfDoubleDCSes since they may change at run-time.
In this case pfFlatten 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 pfFlatten for more details.
The presence of transformations in the scene graph impacts the
performance of intersection, culling and drawing. pfGeoSet culling (see
PFCULL_GSET in pfChanTravMode) is disabled in portions of the scene graph
below pfDoubleDCSes.
Both pre and post CULL and DRAW callbacks attached to a pfDoubleDCS (-
pfNodeTravFuncs) 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.
pfGetDoubleDCSMat copies the transformation matrix value from dcs into
the matrix m. For faster matrix access, pfGetDoubleDCSMatPtr can be used
to get a const pointer to dcs'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
Page 6
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
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.
Coding the above example we get:
void
setDoublePrecisionDCS (pfChannel *chan,
pfDoubleDCS *ddcs,
pfCoordd *coord)
{
pfMatrix4d mat, invMat;
/* Channel camera is at origin */
pfChanViewMat(chan, pfIdentMat);
pfMakeCoorddMat4d (mat, coord);
pfInvertOrthoNMat4d (invMat, mat);
/* Put inverse of camera position in double DCS. */
pfDoubleDCSMat (ddcs, 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.
Page 7
pfDoubleDCS(3pf) OpenGL Performer 3.2.2 libpf C Reference Pages
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.
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, pfChanTravMode, pfLookupNode, pfFlatten, pfMatrix,
pfNode, pfDCS, pfSCS, pfFCS, pfDoubleSCS, pfDoubleFCS, pfScene,
pfTraverser, pfDelete
Page 8