Kenneth B Russell (kbrussel++at++media.mit.edu)
Sat, 31 Jan 1998 22:04:22 -0500
I found this bug because we never specify the PFGS_COLOR4
attribute in our geometry (instead using a pfMaterial to do so),
and our morphing code broke under 2.2. A rewrite using the
pfFlux/pfEngine mechanism had the same problem. See the attached
example (derived from the old morph.c, but visible in
morph_engine.C as well) which demonstrates the bug.
The only workaround is to specify per-vertex colors in a
pfCycleBuffer/pfFlux, which is a waste of space if the color is
the same across the piece of geometry.
Any chance we could get this fixed in a patch?
Thanks much.
-Ken
__________________________________________________________________________
Kenneth B. Russell Synthetic Characters Group, MIT Media Lab
kbrussel++at++media.mit.edu http://www.media.mit.edu/~kbrussel
------
/*
* Copyright 1995, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
*
* UNPUBLISHED -- Rights reserved under the copyright laws of the United
* States. Use of a copyright notice is precautionary only and does not
* imply publication or disclosure.
*
* U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
* in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
* in similar or successor clauses in the FAR, or the DOD or NASA FAR
* Supplement. Contractor/manufacturer is Silicon Graphics, Inc.,
* 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that (i) the above copyright notices and this
* permission notice appear in all copies of the software and related
* documentation, and (ii) the name of Silicon Graphics may not be
* used in any advertising or publicity relating to the software
* without the specific, prior written permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
* INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
* THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
* OR PERFORMANCE OF THIS SOFTWARE.
*
* morph.c++: Performer program to demonstrate use of pfMorph node.
* Based on simple.c
*
* $Revision: 1.5 $ $Date: 1995/11/22 14:36:00 $
*
*/
#include <stdlib.h>
#include <math.h>
#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <Performer/pr/pfLinMath.h>
#include <Performer/pr/pfGeoSet.h>
#include <Performer/pr/pfGeoState.h>
#include <Performer/pr/pfMaterial.h>
#include <Performer/pr/pfLight.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfScene.h>
#include <Performer/pf/pfMorph.h>
#include <Performer/pf/pfLightSource.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfPipeWindow.h>
// Bug in pfGeoSet, Performer 2.2.
// Demonstrated by Kenneth B. Russell (kbrussel++at++media.mit.edu)
// Switches for the two instances of the bug.
#define MORPH_NORMALS // Turns on morphing of normals
#define MORPH_COORDS // Turns on morphing of coordinates
#define COLORS_AS_CBUF // Makes colors a CycleBuffer. Turning
// this off makes colors malloced using
// pfMalloc. But see NOTE: below.
#define NO_COLORS // Gives GeoSet no colors (inherits from
// pfMaterial)
// Combinations Bug?
// N_C No
// (M_N || M_C) && (C_A_C && N_C) YES
// Neither of these attempted workarounds work properly. The only
// workaround, therefore, is to specify per-vertex colors in every
// GeoSet for which either the normals or the coordinates are morphing
// (either using the pfMorph node OR the pfFlux/pfEngine mechanism).
//#define OVERALL_COLORS
//#define PER_PRIM_COLORS
int nSph;
pfCycleBuffer *cbuf;
/*------------------------------------------------------------------*/
static void
breatheMorph(pfMorph *morph, double t)
{
float s = (sinf(t) + 1.0f) / 2.0f;
float weights[2];
int i;
weights[0] = s;
weights[1] = 1.0f - s;
morph->setWeights(-1, weights);
}
static pfMorph*
initMorph(void)
{
pfGeoSet *gset;
pfGeode *geode;
pfGeoState *gstate;
pfMaterial *mtl;
pfMorph *morph;
ushort *icoords, *inorms;
pfVec3 *coords, *ncoords, *norms, *nnorms;
pfVec4 *colors;
float *srcs[2];
int i;
void *arena = pfGetSharedArena();
morph = new pfMorph;
geode = new pfGeode;
gset = pfdNewSphere(400, arena);
gstate = new(arena) pfGeoState;
mtl = new(arena) pfMaterial;
mtl->setColor(PFMTL_DIFFUSE, 0.0f, 1.0f, 1.0f);
mtl->setColor(PFMTL_SPECULAR, 1.0f, 1.0f, 1.0f);
mtl->setColorMode(PFMTL_BOTH, PFMTL_CMODE_AD);
mtl->setShininess(32);
gstate->setAttr(PFSTATE_FRONTMTL, mtl);
gstate->setMode(PFSTATE_ENLIGHTING, 1);
gset->setGState(gstate);
geode->addGSet(gset);
morph->addChild(geode);
/*
* NULL forces recomputation of bound. Force it to be static
* to avoid expensive recomputation. Static bound should encompass
* the extent of all morph possibilities.
*/
gset->setBound(NULL, PFBOUND_STATIC);
geode->setBound(NULL, PFBOUND_STATIC);
gset->getAttrLists(PFGS_COORD3, (void**)&coords, &icoords);
gset->getAttrLists(PFGS_NORMAL3, (void**)&norms, &inorms);
nSph = pfGetSize(coords) / sizeof(pfVec3);
cbuf = new(arena) pfCycleBuffer(nSph * sizeof(pfVec4));
ncoords = (pfVec3 *)pfMalloc(pfGetSize(coords), arena);
nnorms = (pfVec3 *)pfMalloc(pfGetSize(norms), arena);
#ifdef COLORS_AS_CBUF
colors = (pfVec4*) cbuf->getCurData();
#else
colors = (pfVec4*) pfMalloc(nSph * sizeof(pfVec4));
#endif
for (i = 0; i < nSph; i++)
{
colors[i].set(0.0f, 1.0f, 1.0f, 1.0f);
ncoords[i].scale(2.0f, coords[i]);
nnorms[i] = norms[i];
}
/* Set all pfCycleMemories to the same colors */
cbuf->init(cbuf->getCurData());
#ifndef NO_COLORS
# ifdef COLORS_AS_CBUF
gset->setAttr(PFGS_COLOR4, PFGS_PER_VERTEX,
(void*)cbuf, NULL);
# else
// NOTE: this DOES work if
// colors = (pfVec4*) cbuf->getCurData();
gset->setAttr(PFGS_COLOR4, PFGS_PER_VERTEX,
(void*)colors, NULL);
# endif
#endif
#ifdef OVERALL_COLORS
pfCycleBuffer *tmpBuf = new(arena) pfCycleBuffer(sizeof(pfVec4));
pfVec4 *tmpColors = (pfVec4 *) cbuf->getCurData();
tmpColors[0].set(0.0f, 1.0f, 0.0f, 1.0f);
cbuf->init(cbuf->getCurData());
gset->setAttr(PFGS_COLOR4, PFGS_OVERALL, tmpBuf, NULL);
#endif
#ifdef PER_PRIM_COLORS
int numPrims = gset->getNumPrims();
pfCycleBuffer *tmpBuf = new(arena) pfCycleBuffer(numPrims * sizeof(pfVec4));
pfVec4 *tmpColors = (pfVec4 *) cbuf->getCurData();
for (int q = 0; q < numPrims; q++)
tmpColors[q].set(0.0f, 1.0f, 0.0f, 1.0f);
cbuf->init(cbuf->getCurData());
gset->setAttr(PFGS_COLOR4, PFGS_PER_PRIM, tmpBuf, NULL);
#endif
#ifdef MORPH_COORDS
/* Morph attribute 0 is coordinates */
srcs[0] = (float*)coords;
srcs[1] = (float*)ncoords;
morph->setAttr(0, 3, nSph, NULL, 2, srcs, NULL, NULL);
gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX,
(void*)morph->getDst(0), icoords);
#endif
#ifdef MORPH_NORMALS
/* Morph attribute 1 is normals */
srcs[0] = (float*)norms;
srcs[1] = (float*)nnorms;
morph->setAttr(1, 3, nSph, NULL, 2, srcs, NULL, NULL);
gset->setAttr(PFGS_NORMAL3, PFGS_PER_VERTEX,
(void*)morph->getDst(1), inorms);
#endif
return morph;
}
void
OpenPipeWin (pfPipeWindow *pw)
{
pw->open();
(new pfLightModel)->apply();
}
void
DrawChannel (pfChannel *chan, void *data)
{
pfVec4 clr;
clr.set(.2f, .2f, .2f, 1.0f);
pfClear(PFCL_COLOR|PFCL_DEPTH, &clr);
pfDraw();
}
int
main (int argc, char *argv[])
{
double t = 0.;
pfScene *scene;
pfDCS *morphDCS;
pfMorph *morph;
pfPipe *p;
pfPipeWindow *pw;
pfChannel *chan;
pfSphere bsphere;
pfCoord view;
pfLightSource *ls;
/* Initialize Performer */
pfInit();
/* Use default multiprocessing mode based on number of
* processors.
*/
pfMultiprocess(PFMP_DEFAULT);
/* Configure multiprocessing mode and start parallel
* processes.
*/
pfConfig();
/* Create and attach morph to a pfScene. */
scene = new pfScene;
morphDCS = new pfDCS;
morph = initMorph();
morphDCS->addChild(morph);
scene->addChild(morphDCS);
/* determine extent of scene's geometry */
scene->getBound(&bsphere);
/* Configure and open GL window */
p = pfGetPipe(0);
pw = new pfPipeWindow(p);
pw->setName(argv[0]);
pw->setConfigFunc(OpenPipeWin);
pw->setOriginSize(0, 0, 500, 500);
pw->config();
/* Create and configure a pfChannel. */
chan = new pfChannel(p);
chan->setScene(scene);
chan->setNearFar(1.0f, 10.0f * bsphere.radius);
chan->setFOV(45.0f, 0.0f);
view.xyz = bsphere.center;
view.xyz[PF_Y] -= 3.0f * bsphere.radius;
view.hpr.set(0.0f, 0.0f, 0.0f);
chan->setView(view.xyz, view.hpr);
chan->setTravFunc(PFTRAV_DRAW, DrawChannel);
/* Create a pfLightSource and attach it to scene. */
ls = new pfLightSource;
ls->setPos(view.xyz[0], view.xyz[1], view.xyz[2], 1.0f);
scene->addChild(ls);
/* Simulate for twenty seconds. */
while (1)
{
pfMatrix mat;
t = pfGetTime();
/* Update morph */
breatheMorph(morph, t);
/* Initiate cull/draw for this frame. */
pfFrame();
}
/* Terminate parallel processes and exit. */
pfExit();
return 0;
}
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
Submissions: info-performer++at++sgi.com
Admin. requests: info-performer-request++at++sgi.com
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:56:40 PDT