pfMorph OBSOLETED by pfEngine and pfFlux(3pf)NAME
pfNewMorph, pfGetMorphClassType, pfMorphAttr, pfMorphWeights,
pfGetMorphWeights, pfGetMorphNumAttrs, pfGetMorphSrc, pfGetMorphNumSrcs,
pfGetMorphDst, pfEvaluateMorph - Create, modify, and query a pfMorph
node.
FUNCTION SPECIFICATION
#include <Performer/pf.h>
pfMorph * pfNewMorph(void);
pfType * pfGetMorphClassType(void);
int pfMorphAttr(pfMorph *morph, int index, int floatsPerElt,
int nelts, void *dst, int nsrcs, float *alist[],
ushort *ilist[], int nlist[]);
int pfMorphWeights(pfMorph *morph, int index, float *weights);
int pfGetMorphWeights(const pfMorph *morph, int index,
float *weights);
int pfGetMorphNumAttrs(const pfMorph *morph);
int pfGetMorphSrc(const pfMorph *morph, int index, int src,
float **alist, ushort **ilist, int *nlist);
int pfGetMorphNumSrcs(const pfMorph *morph, int index);
void * pfGetMorphDst(const pfMorph *morph, int index);
void pfEvaluateMorph(pfMorph *morph);
PARENT CLASS FUNCTIONS
The OpenGL Performer class pfMorph is derived from the parent class
pfGroup, so each of these member functions of class pfGroup are also
directly usable with objects of class pfMorph. Casting an object of
class pfMorph to an object of class pfGroup is taken care of
automatically. This is also true for casts to objects of ancestor
classes of class pfGroup.
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);
Page 1
pfMorph OBSOLETED by pfEngine and pfFlux(3pf)
Since the class pfGroup is itself derived from the parent class pfNode,
objects of class pfMorph 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 pfMorph 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);
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 pfMorph can also be used with these functions
designed for objects of class pfMemory.
Page 2
pfMorph OBSOLETED by pfEngine and pfFlux(3pf)
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
morph identifies a pfMorph.
DESCRIPTION
A pfMorph node does not define geometry; rather, it manipulates geometric
attributes of pfGeoSets and other geometric primitives. While pfMorph is
very general, its primary use is for geometric morphing where the colors,
normals, texture coordinates and coordinates of geometry are smoothly
changed over time to simulate actions such as facial and skeletal
animation, ocean waves, continuous level-of-detail, and advanced special
effects. In these situations, the rigid body transformations provided by
matrices do not suffice - instead, efficient per-vertex manipulations are
required.
A pfMorph consists of one or more "sources" and a single "destination"
which together are termed an "attribute". Both sources and destination
are arrays of "elements" where each element consists of 1 or more
floating point numbers, e.g., an array of pfVec3 coordinates. The
pfMorph node produces the destination by computing a weighted sum of the
sources. By varying the source weights and using the morph destination as
a pfGeoSet attribute array, the application can achieve smooth, geometric
animation. A pfMorph can "morph" multiple attributes.
pfNewMorph creates and returns a handle to a pfMorph. Like other
pfNodes, pfMorphs are always allocated from shared memory and can be
deleted using pfDelete.
pfGetMorphClassType returns the pfType* for the class pfMorph. The
pfType* returned by pfGetMorphClassType is the same as the pfType*
returned by invoking pfGetType on any instance of class pfMorph. 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.
Page 3
pfMorph OBSOLETED by pfEngine and pfFlux(3pf)
pfMorphAttr configures the indexth attribute of morph. floatsPerElt
specifies how many floating point numbers comprise a single attribute
element. For example, when morphing pfGeoSet coordinate and texture
coordinate arrays (PFGS_COORD3, PFGS_TEXCOORD2), floatsPerElt would be 3
and 2 respectively. nelts specifies how many attribute elements are in
the destination array. If the required number of pfGeoSet coordinates is
33, then nelts would be 33, not 33 * 3 = 99. dst is a pointer to the
destination array which should be at least of size floatsPerElt * nelts *
sizeof(float). If dst is NULL, then morph will automatically create and
use a pfCycleBuffer of appropriate size. (pfCycleBuffers are useful when
OpenGL Performer is configured to multiprocess.)
There are 2 distinct methods of accessing the source arrays of a pfMorph
attribute: non-indexed and indexed. Indexing provides a means of
efficiently applying sparse changes to the destination array. The nsrcs
argument to pfMorphAttr specifies how many source arrays are provided in
alist, i.e., alist[i] is the i'th source and is treated as an array of
elements where each element consists of floatsPerElt floating point
numbers. Index arrays and their lengths are provided in ilist and nlist
respectively. If ilist is NULL then all sources are non-indexed. If ilist
is non-NULL, it contains a list of index lists corresponding to the
source lists in alist. If nlist is NULL, then the index lists are assumed
to be nelts long and if non-NULL, the length of each index list is
specified in nlist. ilist may contain NULL pointers to mix indexed and
non-indexed source arrays.
All source arrays referenced in alist and ilist are reference counted by
pfMorphAttr.
pfMorphWeights specifies the source weights of the indexth attribute of
morph in the array weights. weights should consist of nsrcs floating
point numbers where nsrcs is the number of attribute sources specified in
pfMorphAttr. If index is < 0, then weights is used for all attributes of
morph. pfGetMorphWeights copies the weights of the indexth attribute of
morph into weights. weights should be an array of at least nsrcs floats.
A pfMorph node is evaluated, i.e., its destination array is computed,
during the APP traversal which is triggered directly by the application
through pfAppFrame (see pfAppFrame) or indirectly by pfSync.
Alternately, the pfMorph node may be explicitly evaluated by calling the
function pfEvaluateMorph. In all cases, destination elements are
computed as in the following pseudocode:
zero destination array;
for (s=0; s<nsrcs; s++)
{
if (ilist == NULL || ilist[s] == NULL)
{
/* Source is non-indexed */
for (i=0; i<nelts; i++)
for (e=0; e<floatsPerElt; e++)
Page 4
pfMorph OBSOLETED by pfEngine and pfFlux(3pf)
dst[i][e] += weights[s] * alist[s][i][e];
}
else
{
/* Source is indexed */
int nindex;
if (nlist == NULL)
nindex = nelts;
else
nindex = nlist[s];
for (i=0; i<nindex; i++)
for (e=0; e<floatsPerElt; e++)
dst[ilist[s][i]][e] += weights[s] * alist[s][i][e];
}
}
Note that the actual implementation is much more efficient than above,
particularly for the special weights of 0 and 1.
Since pfMorph is a pfGroup, it is guaranteed to be evaluated before its
children in the APP traversal. The pfMorph is only evaluated by the APP
traversal when its weights change.
pfGetMorphNumAttrs returns the number of morph's attributes.
pfGetMorphSrc returns the srcth source parameters of the indexth
attribute of morph. The source attribute array and index array pointers
are copied into alist and ilist respectively. The size of the srcth index
array is copied into nlist and the number of floats per element is
returned by pfGetMorphSrc.
pfGetMorphNumSrcs returns the number of sources of the indexth attribute
of morph.
pfGetMorphDst returns the indexth destination array of morph. The
destination array is either that provided earlier by pfMorphAttr or the
pfCycleBuffer automatically created when NULL was passed as the dst
argument to pfMorphAttr.
OBSOLETE
pfMorph has been obsoleted by pfEngine and pfFlux. pfFluxes are
multibuffered data objects for asyncrhonous evaluation, such as by
pfEngines, that can be directly used as vertex attribute arrays, full
pfGeoSets, matrices for pfFSC tranformation nodes, and other special
asynchronous values for pfLOD and pfSwitch. See these man pages for more
information.
Page 5
pfMorph OBSOLETED by pfEngine and pfFlux(3pf)SEE ALSO
pfAppFrame, pfCycleBuffer, pfGroup, pfDelete, pfEngine, pfFlux,
pfLookupNode
Page 6