Kenneth B Russell (kbrussel++at++media.mit.edu)
Wed, 28 Apr 1999 10:56:25 -0400 (EDT)
I reported this problem over a year ago on this mailing list
(note: with no notification of receipt or confirmation that the
bug exists); I've included a copy of my earlier message below.
This appears to be a new bug in pfGeoSet in Performer 2.2 (wasn't
present in 2.1) where if any part of a GeoSet is "fluxed" (i.e.,
normals or coordinates) via the use of either pfFlux,
pfCycleBuffer or pfMorph, all of them must be. The workaround is
to specify a static, fluxed buffer of colors as well.
-Ken
__________________________________________________________________________
Kenneth B. Russell Synthetic Characters Group, MIT Media Lab
kbrussel++at++media.mit.edu http://www.media.mit.edu/~kbrussel
--- Date: Sat, 31 Jan 1998 22:04:22 -0500 From: Kenneth B Russell <kbrussel++at++media.mit.edu> To: Performer Enthusiasts <info-performer++at++sgi.com> Subject: Bug in pfGeoSet, Performer 2.2 Reply-to: kbrussel++at++media.mit.edu Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-UIDL: 7402f6013bd0ca2ef2c762ab2a387c41
If either coordinates OR normals are specified as either pfFluxes or pfCycleBuffers (the latter from the output of the now-obsolete pfMorph node), then: - the color attribute for the GeoSet must be set, and - the colors must be specified PER_VERTEX, and - the colors must be allocated out of a pfFlux/pfCycleBuffer. They can not be allocated even using pfMalloc().
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; }
This archive was generated by hypermail 2.0b2 on Wed Apr 28 1999 - 07:56:39 PDT