Bug in pfGeoSet, Performer 2.2

New Message Reply Date view Thread view Subject view Author view

Kenneth B Russell (kbrussel++at++media.mit.edu)
Sat, 31 Jan 1998 22:04:22 -0500


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;
}
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
            Submissions: info-performer++at++sgi.com
        Admin. requests: info-performer-request++at++sgi.com


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:56:40 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.