Anita Kishore (kishore++at++triavest.com)
Mon, 16 Jun 1997 15:51:03 -0700
Here is the smaple code that is distributed with performer 2.0.1 for RE2.
Hope this helps.
-anita
kishore++at++triavest.com
/*
* 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.
*
* shadows.c: Performer program to demonstrate use of pfLightSource shadowing
* and projected texturing.
* Based on simple.c
*
* $Revision: 1.7 $ $Date: 1995/12/03 23:53:00 $
*
*/
#include <stdlib.h>
#include <math.h>
#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <Performer/pfutil.h>
/*------------------------------------------------------------------*/
void
OpenPipeWin (pfPipeWindow *pw)
{
pfLightModel *lm;
int numSamples = 16;
pfOpenPWin(pw);
#ifdef IRISGL
/* Shadows require a 32 bit non-multisampled zbuffer */
do
{
zbsize(32);
stensize(1);
mssize(numSamples, 32, 1);
gconfig();
numSamples >>= 1;
} while (PF_ABS(getgconfig(GC_BITS_ZBUFFER)) < 32 && numSamples > 0);
if (numSamples > 0)
multisample(1);
else
{
RGBsize(12);
mssize(0, 0, 0);
zbsize(32);
stensize(1);
gconfig();
multisample(0);
}
pfNotify(PFNFY_NOTICE, PFNFY_RESOURCE,
"mssize(%d, %d, %d) zbsize(%d) Zrange 0x%x - 0x%x\n",
getgconfig(GC_MS_SAMPLES),
getgconfig(GC_BITS_MS_ZBUFFER),
getgconfig(GC_BITS_MS_STENCIL),
getgconfig(GC_BITS_ZBUFFER),
getgconfig(GC_MS_ZMIN), getgconfig(GC_MS_ZMAX));
#endif
lm = pfNewLModel(NULL);
pfLModelLocal(lm, 1);
pfApplyLModel(lm);
pfCullFace(PFCF_BACK);
}
void
DrawChannel (pfChannel *chan, void *data)
{
pfVec4 clr;
pfSetVec4(clr, .2f, .2f, .2f, 1.0f);
pfClear(PFCL_COLOR|PFCL_DEPTH, clr);
pfDraw();
}
/*
* Usage() -- print usage advice and exit. This
* procedure is executed in the application process.
*/
static void
Usage (void)
{
pfNotify(PFNFY_FATAL, PFNFY_USAGE, "Usage: shadows file.ext ...\n");
exit(1);
}
/* Compute matrix so +Y axis of DCS is pointing at 'at' */
static void
lookAt(pfDCS *dcs, pfVec3 at)
{
pfVec3 v, pos;
pfMatrix mat;
static pfVec3 yaxis = {0.0f, 1.0f, 0.0f};
/* v is origin of dcs */
pfGetMatRowVec3(*pfGetDCSMatPtr(dcs), 3, pos);
/* v is direction vector from dcs to 'at' */
pfSubVec3(v, at, pos);
pfNormalizeVec3(v);
/* Rotate y-axis onto v */
pfMakeVecRotVecMat(mat, yaxis, v);
pfSetMatRowVec3(mat, 3, pos); /* restore dcs origin */
pfDCSMat(dcs, mat);
}
#define SPOT_SIZE 256
#define SPOT_RADIUS 64
/*
* Create circular image for projected spotlight texture.
*/
static pfTexture*
initSpotTex(void)
{
long i, j, win;
pfTexture *tex;
unsigned short *image;
image = pfMalloc(sizeof(unsigned short) * SPOT_SIZE * SPOT_SIZE,
pfGetSharedArena());
for (i = 0; i < SPOT_SIZE / 2; i++)
{
for (j = 0; j < SPOT_SIZE / 2; j++)
{
unsigned long val;
val = 0;
/* See if corners of texel are within circle. This antialiases
* the edge of the circle somewhat. */
if ((i * i + j * j) <= SPOT_RADIUS * SPOT_RADIUS)
val += 0xffff;
if (((i + 1) * (i + 1) + j * j) <= SPOT_RADIUS * SPOT_RADIUS)
val += 0xffff;
if (((i + 1) * (i + 1) + (j + 1) * (j + 1)) <= SPOT_RADIUS * SPOT_RADIUS)
val += 0xffff;
if ((i * i + (j + 1) * (j + 1)) <= SPOT_RADIUS * SPOT_RADIUS)
val += 0xffff;
val >>= 2;
/* Set all 4 quadrants to val */
image[(SPOT_SIZE / 2 - i) * SPOT_SIZE + (SPOT_SIZE / 2 - j)] =
image[(SPOT_SIZE / 2 - i) * SPOT_SIZE + (SPOT_SIZE / 2 + j)] =
image[(SPOT_SIZE / 2 + i) * SPOT_SIZE + (SPOT_SIZE / 2 + j)] =
image[(SPOT_SIZE / 2 + i) * SPOT_SIZE + (SPOT_SIZE / 2 - j)] =
val;
}
}
tex = pfNewTex(pfGetSharedArena());
pfTexImage(tex, (uint*) image, 2, SPOT_SIZE, SPOT_SIZE, 0);
pfTexFormat(tex, PFTEX_INTERNAL_FORMAT, PFTEX_IA_8);
pfTexRepeat(tex, PFTEX_WRAP, PFTEX_CLAMP);
return tex;
}
#define FOV 60.0f
#define NEAR 1.0f
#define SQRT2INV .7071067811865475244
static pfDCS *shadDCS, *projDCS;
static pfGroup*
initLSources(pfSphere *bsphere)
{
pfFrustum *shadFrust;
pfLightSource *shad, *proj;
pfTexture *tex;
pfGroup *group;
float d;
pfMatrix mat;
void *arena = pfGetSharedArena();
/* Create and configure shadow frustum. Fit frustum tightly to scene. */
shadFrust = pfNewFrust(arena);
pfMakeSimpleFrust(shadFrust, FOV);
d = bsphere->radius / sinf(PF_DEG2RAD(FOV/2.0f));
d = PF_MAX2(d, NEAR + bsphere->radius);
pfFrustNearFar(shadFrust, NEAR, d + 1.1f * bsphere->radius);
/* Create and configure white shadow casting light source */
shad = pfNewLSource();
pfLSourceMode(shad, PFLS_SHADOW_ENABLE, 1);
pfLSourceAttr(shad, PFLS_PROJ_FRUST, shadFrust);
pfLSourceColor(shad, PFLT_DIFFUSE, 1.0f, 1.0f, 1.0f);
pfLSourceVal(shad, PFLS_INTENSITY, .5f);
pfLSourcePos(shad, 0.0f, 0.0f, 0.0f, 1.0f); /* Make light local */
/* Create and configure blue spotlight */
proj = pfNewLSource();
tex = initSpotTex();
/* You can load your own spotlight texture if you wish
* tex = pfNewTex(arena);
* pfLoadTexFile(tex, "spotlight.inta");
*/
pfLSourceMode(proj, PFLS_PROJTEX_ENABLE, 1);
pfLSourceAttr(proj, PFLS_PROJ_FRUST, shadFrust);
pfLSourceAttr(proj, PFLS_PROJ_TEX, tex);
pfLSourceColor(proj, PFLT_DIFFUSE, 0.0f, 0.0f, 1.0f);
pfLSourceVal(proj, PFLS_INTENSITY, .5f);
pfLSourcePos(proj, 0.0f, 0.0f, 0.0f, 1.0f); /* Make light local */
group = pfNewGroup();
/* Make DCSes to move lights around */
shadDCS = pfNewDCS();
pfMakeTransMat(mat, d*SQRT2INV, 0.0f, d*SQRT2INV);
pfDCSMat(shadDCS, mat);
lookAt(shadDCS, bsphere->center);
pfAddChild(shadDCS, shad);
pfAddChild(group, shadDCS);
projDCS = pfNewDCS();
pfMakeTransMat(mat, -d*SQRT2INV, 0.0f, d*SQRT2INV);
pfDCSMat(projDCS, mat);
lookAt(projDCS, bsphere->center);
pfAddChild(projDCS, proj);
pfAddChild(group, projDCS);
return group;
}
static pfGeode*
initFloor(pfSphere *bsphere)
{
pfGeoSet *gset;
pfGeoState *gstate;
pfGeode *geode;
pfVec3 *v;
pfMaterial *mtl;
float d;
void *arena = pfGetSharedArena();
gset = pfNewGSet(arena);
gstate = pfNewGState(arena);
geode = pfNewGeode();
v = (pfVec3*)pfMalloc(sizeof(pfVec3) * 4, arena);
d = 3.0f * bsphere->radius;
pfSetVec3(v[0], -d, -d, -d/3.0f);
pfSetVec3(v[1], d, -d, -d/3.0f);
pfSetVec3(v[2], d, d, -d/3.0f);
pfSetVec3(v[3], -d, d, -d/3.0f);
pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, v, NULL);
v = (pfVec3*)pfMalloc(sizeof(pfVec3), arena);
pfSetVec3(v[0], 0.0f, 0.0f, 1.0f);
pfGSetAttr(gset, PFGS_NORMAL3, PFGS_OVERALL, v, NULL);
pfGSetPrimType(gset, PFGS_QUADS);
pfGSetNumPrims(gset, 1);
mtl = pfNewMtl(arena);
pfMtlColorMode(mtl, PFMTL_BOTH, PFMTL_CMODE_OFF);
pfGStateAttr(gstate, PFSTATE_FRONTMTL, mtl);
pfGStateMode(gstate, PFSTATE_ENLIGHTING, 1);
pfGSetGState(gset, gstate);
pfAddGSet(geode, gset);
return geode;
}
int
main (int argc, char *argv[])
{
double t = 0.;
pfScene *scene;
pfNode *root;
pfDCS *dcs;
pfPipe *p;
pfPipeWindow *pw;
pfChannel *chan;
pfSphere bsphere;
pfCoord view;
pfMatrix mat, orbit;
pfList *texList;
int ret;
#ifndef IRISGL
printf("Sorry, shadows doesn't work in OPENGL\n");
return 0;
#endif
if (argc < 2)
Usage();
/* Initialize Performer */
pfInit();
pfQueryFeature(PFQFTR_TEXTURE_PROJECTIVE, &ret);
if (!(ret == PFQFTR_FAST))
{
printf("Sorry, shadows aren't supported on this machine.\n");
return 0;
}
/* Use default multiprocessing mode based on number of
* processors.
*/
pfMultiprocess(PFMP_DEFAULT);
/* Load all loader DSO's before pfConfig() forks */
pfdInitConverter(argv[1]);
/* Configure multiprocessing mode and start parallel
* processes.
*/
pfConfig();
/* Append to PFPATH additional standard directories where
* geometry and textures exist
*/
pfFilePath(".:/usr/share/Performer/data");
/* Do not use FLAT_ primitives because they look bad
* with local lighting.
*/
pfdBldrMode(PFDBLDR_MESH_LOCAL_LIGHTING, 1);
/* Read a single file, of any known type. */
if ((root = pfdLoadFile(argv[1])) == NULL)
{
pfExit();
exit(-1);
}
/* Create and attach loaded subgraph to a pfScene. */
scene = pfNewScene();
dcs = pfNewDCS();
pfMakeRotMat(mat, 30.0f, 1.0f, 0.0f, 0.0f);
pfDCSMat(dcs, mat);
pfAddChild(dcs, root);
pfAddChild(scene, dcs);
/* determine extent of scene's geometry */
pfGetNodeBSphere (scene, &bsphere);
/* Create pfLightSources and add to scene */
pfAddChild(scene, initLSources(&bsphere));
/* Create "floor" for shadows */
pfAddChild(dcs, initFloor(&bsphere));
/* Configure and open GL window */
p = pfGetPipe(0);
pw = pfNewPWin(p);
pfPWinName(pw, argv[0]);
pfPWinConfigFunc(pw, OpenPipeWin);
pfPWinOriginSize(pw, 0, 0, 500, 500);
pfConfigPWin(pw);
/* Create and configure a pfChannel. */
chan = pfNewChan(p);
pfChanScene(chan, scene);
pfChanNearFar(chan, 1.0f, 5.0f * bsphere.radius);
pfChanFOV(chan, 45.0f, 0.0f);
pfCopyVec3(view.xyz, bsphere.center);
view.xyz[PF_Y] -= 3.0f * bsphere.radius;
pfSetVec3(view.hpr, 0.0f, 0.0f, 0.0f);
pfChanView(chan, view.xyz, view.hpr);
pfChanTravFunc(chan, PFTRAV_DRAW, DrawChannel);
/* If scene is non-textured then we can save an entire rendering pass */
texList = pfuMakeSceneTexList(scene);
if (pfGetNum(texList) == 0)
{
pfChanTravMode(chan, PFTRAV_MULTIPASS, PFMPASS_NONTEX_SCENE);
pfNotify(PFNFY_NOTICE, PFNFY_PRINT,
"Scene is non-textured! Using PFMPASS_NONTEX_SCENE "
"optimization");
}
pfMakeRotMat(orbit, 1.0f, 0.0f, 0.0f, 1.0f);
/* Simulate for twenty seconds. */
while (t < 20.0f)
{
/* Spin light sources around object */
pfMultMat(mat, *pfGetDCSMatPtr(projDCS), orbit);
pfDCSMat(projDCS, mat);
lookAt(projDCS, bsphere.center);
pfMultMat(mat, *pfGetDCSMatPtr(shadDCS), orbit);
pfDCSMat(shadDCS, mat);
lookAt(shadDCS, bsphere.center);
/* 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:55:27 PDT