Re: Shadows in the CAVE

New Message Reply Date view Thread view Subject view Author view

Athanasios Gaitatzes (gaitat++at++fhw.gr)
Thu, 18 Nov 1999 15:23:52 +0200


 
Hi pfers'

Since couple of people have asked here is the modified shadows.c. No local lights and no spotlights or projected textures unless there is something I really don't understand. I use it as 'shadows -s iris.flt' on a Onyx2
8 processors latest Iris and Performer code.
I have been unable though to make the same thing work in a CAVE and that's what I am interested in so if someone has any suggestions they would be most welcome.

Thank you

/*
 * shadows.c: Performer program to demonstrate use of pfLightSource shadowing
 *
 * cc -s -O2 -n32 -o shadows shadows.c -L/usr/lib32 -lpfdu -lpfutil -lpf \
 *                                     -lGL -lGLU -lX11 -lm -lC -limage
 *
 */

static int Shadow = 0;
static int enable_shadows = 1; /* disable shadows if HW does not handle it */

#include <stdlib.h>
#include <math.h>
#include <unistd.h>

#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <Performer/pfutil.h>
 

static int FBAttrs[] = {
    PFFB_RGBA,
    PFFB_DOUBLEBUFFER,
    PFFB_DEPTH_SIZE, 1,
    None,
};
 

void
OpenPipeWin (pfPipeWindow *pw)
{
    pfOpenPWin(pw);
}

/* ARGSUSED */
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_NOTICE, PFNFY_USAGE, "Usage: shadows [-s] file.ext ...\n");
    pfNotify(PFNFY_NOTICE, PFNFY_USAGE, "       -s : enable shadow \n");

    exit(1);
}

/*
*       docmdline() -- use getopt to get command-line arguments,
*       executed at the start of the application process.
*/

static int
docmdline(int argc, char *argv[])
{
    int opt;

    /* process command-line arguments */
    while ((opt = getopt(argc, argv, "sh")) != -1)
    {
        switch (opt)
        {
        case 's':
            Shadow = 1;
            break;
        case 'h':
            Usage();
        }
    }
    return optind;
}
 

/* 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 FOV             45.0f
#define NEAR            1.0f
#define SQRT2INV        .7071067811865475244

static pfDCS            *shadDCS;
static pfLightSource    *shad;

static pfGroup*
initLSources(pfSphere *bsphere)
{
    pfFrustum   *shadFrust;
    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);

    if (enable_shadows)
    {
        /* 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, .2f);  /* shadow not complety dark *//*      pfLSourcePos(shad, 0.0f, 0.0f, 0.0f, 1.0f);  */   /* Make light local */        pfLSourceVal(shad, PFLS_SHADOW_SIZE, 256);
    }

    group = pfNewGroup();

    /* Make DCSes to move lights around */
    if (enable_shadows)
    {
        shadDCS = pfNewDCS();

        pfMakeTransMat(mat, d*SQRT2INV, 0.0f, d*SQRT2INV);
        pfDCSMat(shadDCS, mat);
        lookAt(shadDCS, bsphere->center);

        pfAddChild(shadDCS, shad);
        if (Shadow)
            pfAddChild(group, shadDCS);
    }

    return group;
}
 

int
main (int argc, char *argv[])
{
    pfScene     *scene;
    pfNode      *root;
    pfDCS       *dcs;
    pfPipe      *p;
    pfPipeWindow *pw;
    pfChannel   *chan;
    pfSphere    bsphere;
    pfCoord     view;
    pfMatrix    mat, orbit;
    int         ret;
    int         arg = 1;
    int         found;

    arg = docmdline(argc,argv);

    /* Initialize Performer */
    pfInit();

    if (Shadow)
    {
        pfQueryFeature(PFQFTR_TEXTURE_SHADOW, &ret);
        if (!(ret == PFQFTR_FAST))
        {
            printf("Sorry, Shadows are not supported !\n");
            enable_shadows = 0;
        }
    }
    else
        enable_shadows = 0;

    /* Use default multiprocessing mode based on number of
     * processors.
     */
    pfMultiprocess(PFMP_DEFAULT);

    /* Load all loader DSO's before pfConfig() forks */
    for (found = arg; found < argc; found++)
        pfdInitConverter(argv[found]);

    /* Configure multiprocessing mode and start parallel
     * processes.
     */
    pfConfig();

    /* Append to PFPATH additional standard directories where
     * geometry and textures exist
     */
    pfFilePath(".:/usr/share/Performer/data");

    /* load files named by command line arguments */
    scene = pfNewScene();
    dcs = pfNewDCS();
    pfMakeRotMat(mat, 30.0f, 1.0f, 0.0f, 0.0f);
    pfDCSMat(dcs, mat);
    pfAddChild(scene, dcs);

    for (found = 0; arg < argc; arg++)
    {
        if ((root = pfdLoadFile(argv[arg])) != NULL)
        {
            pfAddChild(dcs, root);
            found++;
        }
    }

    if (!found)
    {
        pfNotify(PFNFY_FATAL,PFNFY_USAGE,"Error loading database files");
        exit(-1);
    }

    /* determine extent of scene's geometry */
    pfGetNodeBSphere (scene, &bsphere);

    /* Create pfLightSources and add to scene */
    pfAddChild(scene, initLSources(&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);
    pfPWinType(pw, PFPWIN_TYPE_X);
    pfPWinFBConfigAttrs(pw, FBAttrs);
    pfConfigPWin(pw);

    /* Create and configure a pfChannel. */
    chan = pfNewChan(p);
    pfChanScene(chan, scene);
    pfChanNearFar(chan, NEAR, 5.0f * bsphere.radius);
    pfChanFOV(chan, FOV, 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);

    pfMakeRotMat(orbit, -1.2f, 0.f, 0.0f, 1.0f);

    /* Simulate for ever ! */
    while (1)
    {
        /* Spin light sources around object */
        if (enable_shadows)
        {
                pfMultMat(mat, *pfGetDCSMatPtr(shadDCS), orbit);
                pfDCSMat(shadDCS, mat);
                lookAt(shadDCS, bsphere.center);
        }

        /* Initiate cull/draw for this frame. */
        pfFrame();
    }
}

--
Athanasios Gaitatzes (gaitat++at++fhw.gr)
Virtual Reality Department
Foundation of the Hellenic World
38 Poulopoulou St., Athens 11851, Greece
Tel: +30 1 3422292 Fax: +30 1 3422272
 


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Thu Nov 18 1999 - 05:31:20 PST

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