[BACK]Return to ASD_decal2.c CVS log [TXT][DIR] Up to [Development] / performer / src / pguide / libpf / C

File: [Development] / performer / src / pguide / libpf / C / ASD_decal2.c (download)

Revision 1.1, Tue Nov 21 21:39:36 2000 UTC (16 years, 11 months ago) by flynnt
Branch: MAIN
CVS Tags: HEAD

Initial check-in based on OpenGL Performer 2.4 tree.
-flynnt

/*
 * Copyright 1995, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * This source code ("Source Code") was originally derived from a
 * code base owned by Silicon Graphics, Inc. ("SGI")
 * 
 * LICENSE: SGI grants the user ("Licensee") permission to reproduce,
 * distribute, and create derivative works from this Source Code,
 * provided that: (1) the user reproduces this entire notice within
 * both source and binary format redistributions and any accompanying
 * materials such as documentation in printed or electronic format;
 * (2) the Source Code is not to be used, or ported or modified for
 * use, except in conjunction with OpenGL Performer; and (3) the
 * names of Silicon Graphics, Inc.  and SGI may not be used in any
 * advertising or publicity relating to the Source Code without the
 * prior written permission of SGI.  No further license or permission
 * may be inferred or deemed or construed to exist with regard to the
 * Source Code or the code base of which it forms a part. All rights
 * not expressly granted are reserved.
 * 
 * This Source Code is provided to Licensee AS IS, without any
 * warranty of any kind, either express, implied, or statutory,
 * including, but not limited to, any warranty that the Source Code
 * will conform to specifications, any implied warranties of
 * merchantability, fitness for a particular purpose, and freedom
 * from infringement, and any warranty that the documentation will
 * conform to the program, or any warranty that the Source Code will
 * be error free.
 * 
 * IN NO EVENT WILL SGI BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT
 * LIMITED TO DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES,
 * ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THE
 * SOURCE CODE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT OR
 * OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM,
 * OR AROSE OUT OF USE OR RESULTS FROM USE OF, OR LACK OF ABILITY TO
 * USE, THE SOURCE CODE.
 * 
 * Contact information:  Silicon Graphics, Inc., 
 * 1600 Amphitheatre Pkwy, Mountain View, CA  94043, 
 * or:  http://www.sgi.com
 *
 *	ASD_decal [-A][-a][asd_filename]
 *
 * 	Demonstrate how to generate decals pfASD.
 *
 *	This program uses fluxed geosets as ASD query results. pfASD fills in 
 *	the resulting decal geometry directly into the geoset. There is no 
 *	pfEngine connecting pfASD to the final pfGeoSet therefore - APP 
 *	intervention is not possible.
 *
 *	Without flags: generate an animated triangular decal (move in a circle).
 *	    -a  move the decal triangle in a circle.
 *	    -A  Disable decal motion
 *
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

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

#define EYE_RADIUS	400.0
#define SIZE		100.0
#define	NOF_FRAGMENTS	200

static void 		init_globals(void);
static pfMaterial 	*defaultMaterial (void);
static pfGeoState 	*make_asd_gstate (void);
static void 		advance_motion(void);

static pfNode		*setup_ASD_decal(pfASD *asd, pfGeoSet *base_gset);
static int 		fluxed_gset_create_func (pfFluxMemory *fmem);
static pfFlux 		*make_fluxed_geoset(void);
static pfGeoSet		*make_base_gset (void);

float			decal_azimuth;

char			asd_filename[300];
char			texture_filename[300];

pfASD			*asd;
float			cx, cy;
float			dx, dy;
pfBox			asd_box;
pfBox			decal_box;
int			query_id;
pfGeoSet		*decal_gset;
pfGeoSet		*base_gset;
float			*global_v_attr;
int			animate_decal;


/*===========================================================================*/
void main (int argc, char *argv[])
/*===========================================================================*/
{
    float       	t = 0.0f;
    pfScene     	*scene;
    pfPipe      	*p;
    pfChannel   	*chan;
    pfPipeWindow	*pwin;
    int			i;
    pfLight     	*lt;
    pfGeoState 		*gs, **gsa;
    pfNode		*node;


    init_globals();

    for (i = 1 ; i < argc ; i ++)
    {
	if (argv[i][0] == '-')
	{
	    if (argv[i][1] == 'A')
		animate_decal = 0;
	    else
	    if (argv[i][1] == 'a')
		animate_decal = 1;
   	}
	else
	    strcpy (asd_filename, argv[1]);
    }

    /* Initialize Performer */
    pfInit();	

    pfuInit();

    /* 
     * Use different mode for spawning DBase thread.
     */
    pfMultiprocess(PFMP_APPCULLDRAW | PFMP_FORK_COMPUTE);			

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

    scene = pfNewScene();

    /* 
     *	======================================================
     *	Load ASD. 
     *	======================================================
     */
    pfFilePath(".:/usr/share/Performer/data:/usr/share/Performer/data/asddata");
    asd = (pfASD *) pfdLoadFile (asd_filename);
    if (! asd)
    {
	fprintf (stderr, "ASD file %s not loaded.\n", asd_filename);
	pfExit();
	exit(8);
    }

    pfASDSyncGroup(asd,1);
    pfAddChild(scene, asd);

    /* calculate center of model circular motion. */
    pfGetASDBBox (asd, &asd_box);
    cx = (asd_box . min[0] + asd_box . max[0]) * 0.5;
    cy = (asd_box . min[1] + asd_box . max[1]) * 0.5;

    dx = (asd_box . max[0] - asd_box . min[0]) * 0.5;
    dy = (asd_box . max[1] - asd_box . min[1]) * 0.5;

    /* setup gstate with some texture */
    gsa = pfMalloc(sizeof(pfGeoState*), pfGetSharedArena());
    gs = make_asd_gstate();
    *gsa = gs;
    pfASDGStates(asd, gsa, 1);
    pfFree(gsa);

    /*
     *	============================================================
     * 	Setup alignment
     *	============================================================
     */
    base_gset = make_base_gset();
    node = setup_ASD_decal(asd, base_gset);

    pfAddChild(scene, node);

    /*
     *	============================================================
     * 	other common setup.
     *	============================================================
     */
    /* Configure and open GL window */
    p = pfGetPipe(0);

    pwin = pfNewPWin (p);
    pfPWinType (pwin, PFWIN_TYPE_X);
    pfPWinOriginSize (pwin, 0, 0, 500, 500);
    pfOpenPWin (pwin);

    /* Create and configure a pfChannel. */
    chan = pfNewChan(p);	
    pfChanScene(chan, scene);
    pfChanNearFar(chan, 1.0f, 100000.0f);
    pfChanFOV(chan, 45.0f, 0.0f);

    pfInitClock (0.0f);

    /* Make some light */

    pfEnable(PFEN_LIGHTING);
    lt = pfNewLight(pfGetSharedArena());
    pfLightPos(lt, 0.0f, 0.0f, 1.0f, 0.0f);
    pfLightOn(lt);

    pfEnable(PFEN_TEXTURE);

    /* Simulate for twenty seconds. */
    while (t < 200.0f)
    {
	pfCoord	   	view;
	float		x, y, z, pitch, cz;

	if (animate_decal)
	    advance_motion();

	/* Go to sleep until next frame time. */
	pfSync();		

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

	/* Compute new view position. */
	t = pfGetTime();

	cz = (decal_box . min[2] + decal_box . max[2]) * 0.5;

	x = cx + EYE_RADIUS;
	y = cy - EYE_RADIUS;
	z = cz + 2.0 * EYE_RADIUS;

	pitch = - atan2 (fabs(z - cz), sqrt ((x-cx)*(x-cx) + (y-cy)*(y-cy))) 
			* 180.0 / M_PI;

        pfSetVec3(view.hpr, 45.0f, pitch, 0);
        pfSetVec3(view.xyz, x, y, z);

	pfChanView(chan, view.xyz, view.hpr);
    }

    /* Terminate parallel processes and exit. */
    pfExit();
}


/*===========================================================================*/
static void advance_motion(void)
/*===========================================================================*/
{
    float	*v;
    ushort	*dummy_ushort;
    float	down[3];

    pfGetGSetAttrLists(base_gset, PFGS_COORD3, (void **) &v, &dummy_ushort);

    decal_azimuth += 0.01;
    if (decal_azimuth > 2.0 * M_PI)
	decal_azimuth -= 2.0 * M_PI;

    v[0] = cx;
    v[1] = cy;
    v[2] = 0.0;

    v[3] = cx + SIZE * cos(decal_azimuth);
    v[4] = cy + SIZE * sin(decal_azimuth);
    v[5] = 0.0;

    v[6] = cx + SIZE * cos(decal_azimuth + M_PI * 0.25);
    v[7] = cy + SIZE * sin(decal_azimuth + M_PI * 0.25);
    v[8] = 0.0;

    pfGSetAttr(base_gset, PFGS_COORD3, PFGS_PER_VERTEX, v, NULL);

    down[0] = 0.0;
    down[1] = 0.0;
    down[2] = -1.0;

    pfASDReplaceQueryGeoSet (asd, query_id, base_gset, down);
}


/*===========================================================================*/
static void init_globals(void)
/*===========================================================================*/
{
    strcpy (asd_filename, "tinyASD.pfb");
    strcpy (texture_filename, "marble.rgb");
    decal_azimuth = 0.0;
    animate_decal = 1;
}


/*===========================================================================*/
static pfNode	*setup_ASD_decal(pfASD *asd, pfGeoSet *base_gset)
/*===========================================================================*/
{
    /*
     *  =====================
     *  Final tree structure:
     *  =====================
     *
     *      <pfLOD>                               <asd> <-- base_gset
     *         |                                    |
     *      <Geode>                                 |
     *         |                                    |
     *   [Fluxed pfGeoSet] <-------------------------
     *        
     */

    pfLOD	*lod;
    pfGeoSet	*gset;
    pfFlux	*fluxed_gset;
    pfGeode 	*geode;
    pfSphere    big_sphere;
    pfBox       *box_p;
    float	*s_down;

    s_down = (float *) pfMalloc(3 * sizeof(float), pfGetSharedArena());

    s_down[0] = 0.0;
    s_down[1] = 0.0;
    s_down[2] = -1.0;

    /*
     *  =====================================================================
     *	Make a fluxed geoset. Add to a geode.
     *  =====================================================================
     */

    fluxed_gset = make_fluxed_geoset();
    gset = (pfGeoSet*) pfGetFluxCurData (fluxed_gset);

    pfFluxSyncGroup((pfFlux *) fluxed_gset, 1);
    pfFluxMode((pfFlux *) fluxed_gset, PFFLUX_PUSH, PF_ON);

    geode = pfNewGeode();
    pfAddGSet (geode, gset);


    query_id = pfASDAddQueryGeoSet (
			    asd,
                            base_gset,
                            s_down,
                            PR_QUERY_TRI_COORD,
                            (pfFlux *) fluxed_gset);

    pfASDGetQueryArrayPositionSpan(asd, query_id, &decal_box);

    /*
     *  ==================================================================
     *  Calculate the maximum bbox of the morphing object.
     *  ==================================================================
     */

    box_p = & decal_box;
    pfSphereAroundBoxes(&big_sphere, (const pfBox **)&box_p, 1);

    lod = pfNewLOD();
    pfAddChild(lod, geode);

    pfLODRange(lod, 0, 0.0);
    pfLODRange(lod, 1, 100000.0 + big_sphere.radius);
    pfLODCenter(lod, big_sphere.center);

    pfNodeBSphere(lod,   &big_sphere, PFBOUND_STATIC);
    pfNodeBSphere(geode, &big_sphere, PFBOUND_STATIC);

    return((pfNode *)lod);
}

/*===========================================================================*/
static pfGeoState *make_asd_gstate (void)
/*===========================================================================*/
{
    pfGeoState 	*gs;
    pfTexture  	*tex;
    pfTexGen	*tgen;
    float	s;

    s = 1.0 / (asd_box . max[0] - asd_box . min[0]);

    gs = pfNewGState (pfGetSharedArena());
    tex = pfNewTex( pfGetSharedArena());
    tgen = pfNewTGen( pfGetSharedArena());

    pfMakeBasicGState(gs);
    pfGStateMode(gs, PFSTATE_CULLFACE, PFCF_BACK);
    pfGStateMode(gs, PFSTATE_ENLIGHTING, PF_ON);
    pfGStateMode(gs, PFSTATE_ENTEXTURE, PF_ON);
    pfGStateAttr(gs, PFSTATE_FRONTMTL, defaultMaterial());

    pfLoadTexFile( tex, texture_filename );
    pfGStateAttr( gs, PFSTATE_TEXTURE, tex );

    pfGStateMode(gs, PFSTATE_ENTEXGEN, PF_ON);

    pfGStateAttr( gs, PFSTATE_TEXGEN, tgen );
    pfGStateAttr( gs, PFSTATE_TEXENV, pfNewTEnv( pfGetSharedArena() ) );

    pfTGenPlane(tgen, PF_S,   s, 0.0, 0.0, 0.0);
    pfTGenPlane(tgen, PF_T, 0.0,   s, 0.0, 0.0);
    pfTGenPlane(tgen, PF_R, 0.0, 0.0,   s, 0.0);
    pfTGenPlane(tgen, PF_Q, 0.0, 0.0, 0.0, 1.0);

    pfTGenMode(tgen, PF_S, PFTG_OBJECT_LINEAR);
    pfTGenMode(tgen, PF_T, PFTG_OBJECT_LINEAR);
    pfTGenMode(tgen, PF_R, PFTG_OBJECT_LINEAR);
    pfTGenMode(tgen, PF_Q, PFTG_OBJECT_LINEAR);

    return (gs);
}

/*===========================================================================*/
static pfMaterial *defaultMaterial (void)
/*===========================================================================*/
{
    pfMaterial	*material;

    material = pfNewMtl(pfGetSharedArena());
    pfMtlColor(material, PFMTL_AMBIENT,  0.8f, 0.8f, 0.8f);
    pfMtlColor(material, PFMTL_DIFFUSE,  0.8f, 0.8f, 0.8f);
    pfMtlColor(material, PFMTL_SPECULAR, 0.0f, 0.0f, 0.0f);
    pfMtlShininess(material, 0.0f);

    pfMtlColorMode(material, PFMTL_FRONT, PFMTL_CMODE_OFF);
    return material;
}

/*===========================================================================*/
static int fluxed_gset_create_func (pfFluxMemory *fmem)
/*===========================================================================*/
{
    float 	*c_attr;
    pfGeoState  *gstate;
    pfGeoSet 	*gset;

    if (fmem == NULL)
        return pfFluxedGSetInit(fmem);

    pfFluxedGSetInit(fmem);

    gset = (pfGeoSet*)pfGetData(fmem);

    c_attr = pfMalloc(4 * sizeof(float), pfGetSharedArena());
    c_attr[0] = 0.1;
    c_attr[1] = 0.1;
    c_attr[2] = 0.1;
    c_attr[3] = 0.6;
    pfGSetAttr(gset, PFGS_COLOR4, PFGS_OVERALL, c_attr, NULL);

    /*
     *  ===========================================================
     *  Build state.
     *  ===========================================================
     */
    gstate = pfNewGState (pfGetSharedArena());
    pfMakeBasicGState (gstate);
    pfGStateMode (gstate, PFSTATE_CULLFACE, PFCF_OFF);
    pfGStateMode (gstate, PFSTATE_ENLIGHTING, PF_OFF);
    pfGStateMode (gstate, PFSTATE_TRANSPARENCY, PFTR_ON | PFTR_NO_OCCLUDE);
    pfGStateMode(gstate, PFSTATE_DECAL,
        PFDECAL_LAYER_DISPLACE | PFDECAL_LAYER_7 | PFDECAL_LAYER_OFFSET);
    pfGStateMode (gstate, PFSTATE_ENTEXTURE, 0);


    /*
     *  ===========================================================
     *  Gset attributes.
     *  ===========================================================
     */
    pfGSetPrimType(gset, PFGS_TRIS);
    pfGSetNumPrims(gset, 0);
    pfGSetGState(gset, gstate);

    return 0;
}

/*===========================================================================*/
static pfFlux *make_fluxed_geoset(void)
/*===========================================================================*/
{
    pfFlux	*fluxed_gset;

    fluxed_gset = pfNewFluxInitFunc (
				fluxed_gset_create_func, 
				PFFLUX_DEFAULT_NUM_BUFFERS, 
				pfGetSharedArena());

    return fluxed_gset;
}

/*===========================================================================*/
static pfGeoSet	*make_base_gset (void)
/*===========================================================================*/
{
    pfGeoSet 	*gset;
    float	*v;

    gset = pfNewGSet (pfGetSharedArena());

    pfGSetPrimType(gset, PFGS_TRIS);
    pfGSetNumPrims(gset, 1);

    v = pfMalloc (9 * sizeof (float), pfGetSharedArena());
    v[0] = cx;
    v[1] = cy;
    v[2] = 0.0;

    v[3] = cx + SIZE;
    v[4] = cy;
    v[5] = 0.0;

    v[6] = cx;
    v[7] = cy + SIZE;
    v[8] = 0.0;

    pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, v, NULL);

    return (gset);
}