[BACK]Return to lpoint.c CVS log [TXT][DIR] Up to [Development] / performer / src / lib / libpfutil

File: [Development] / performer / src / lib / libpfutil / lpoint.c (download)

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

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

/*
 * Copyright 1993, 1994, 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.
 *
 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
 * GRAPHICS, INC.
 */
/*
 * lpoint.c
 * --------------
 * $Revision: 1.1 $
 * $Date: 2000/11/21 21:39:36 $
 */

#include <string.h>
#include <values.h>
#include <math.h>

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

	/*------------------------------------------------------*/

/* Make reflection map which describes the lightpoint envelope */
void
pfuMakeLPStateShapeTex(pfLPointState *lps, pfTexture *tex, int size)
{
    int                 i, j, shapeMode;
    char                *img, *image;
    pfMatrix            rollMat;
    pfVec3              norm;
    float               alpha;
    float		henv, venv, roll, falloff, ambient;
    float		horizParam, vertParam, ambientScale;
    static pfVec3       eye = {0.0f, 1.0f, 0.0f};
    static float	eta = 1.0e-15f;

    image = img = (char*)pfCalloc(1, sizeof(char) * size * size * 2, 
				  pfGetArena(tex));

    pfGetLPStateShape(lps, &henv, &venv, &roll, &falloff, &ambient);
    shapeMode = pfGetLPStateMode(lps, PFLPS_SHAPE_MODE);
    ambientScale = 1.0f - ambient;
    pfMakeRotMat(rollMat, roll, 0.0f, 1.0f, 0.0f);

    if (henv > 180.0f - eta && henv < 180.0f + eta)
        horizParam = 0.0f;
    else
    {
        horizParam = tanf(PF_DEG2RAD(henv / 2.0f));
        horizParam = 1.0f / (horizParam * horizParam);
    }

    if (venv > 180.0f - eta && venv < 180.0f + eta)
        vertParam = 0.0f;
    else
    {
        vertParam = tanf(PF_DEG2RAD(venv / 2.0f));
        vertParam = 1.0f / (vertParam * vertParam);
    }

    /* 'i' ranges over 't' texture coordinate which maps to Z */
    for (i=0; i<size; i++)
    {
        norm[PF_Z] = ((float)i / (size - 1.0f) - 0.5f) * 2.0f;

        /* 'j' ranges over 's' texture coordinate which maps to X */
        for (j=0; j<size; j++)
        {
	    float		sqlen;
	    pfMatrix		dirMat;
	    pfVec3		viewVec;
	    static pfVec3      	zaxis = {0.0f, 0.0f, 1.0f};

            /* Compute normal of unit sphere */
            norm[PF_X] = ((float)j / (size - 1.0f) - 0.5f) * 2.0f;
            norm[PF_Y] = 1.0f - (norm[PF_X] *  norm[PF_X] + 
				 norm[PF_Z] *  norm[PF_Z]);
            if (norm[PF_Y] < 0.0f)
            {
		*img++ = 0xff;	/* Intensity is ON */
                *img++ = ambient * 255.0f;
                continue;
            }
            norm[PF_Y] = pfSqrt(norm[PF_Y]);

	    /* Construct coordinate system of lightpoint with normal
	     * becoming the +Y axis and "up" being aligned with the 
	     * +Z axis in object coordinates.
	    */
	    pfCopyVec3(dirMat[PF_Y], norm);

	    /* Compute new X axis */
	    pfCrossVec3(dirMat[PF_X], norm, zaxis);	

	    /* Check for norm collinear with +Z axis */
	    if ((sqlen = pfDotVec3(dirMat[PF_X], dirMat[PF_X])) < 1e-15)
	    {
		if (pfDotVec3(dirMat[PF_Y], zaxis) > 0.0f)
		{
		    pfSetVec3(dirMat[PF_X], 1.0f,  0.0f, 0.0f);
		    pfSetVec3(dirMat[PF_Z], 0.0f, -1.0f, 0.0f);
		}
		else
		{
		    pfSetVec3(dirMat[PF_X], 1.0f, 0.0f, 0.0f);
		    pfSetVec3(dirMat[PF_Z], 0.0f, 1.0f, 0.0f);
		}
	    }
	    else
	    {
		/* Normalize new X axis */
		sqlen = 1.0f / sqlen;
		PFSCALE_VEC3(dirMat[PF_X], sqlen, dirMat[PF_X]);

		/* Compute new Z axis */
		pfCrossVec3(dirMat[PF_Z], dirMat[PF_X], dirMat[PF_Y]);  
	    }

	    /* Pre-roll new coordinate system */
	    if (roll)
		pfPreMultMat(dirMat, rollMat);

	    /* Find image of eye in new coordinate system */
	    viewVec[PF_X] = PFDOT_VEC3(eye, dirMat[PF_X]);
	    viewVec[PF_Y] = PFDOT_VEC3(eye, dirMat[PF_Y]);
	    viewVec[PF_Z] = PFDOT_VEC3(eye, dirMat[PF_Z]);

	    if (shapeMode == PFLPS_SHAPE_MODE_UNI && viewVec[PF_Y] < 0.0f)
		alpha = ambient;
	    else
	    {
		float   x, z, intens;

		if (PF_ABSLT(viewVec[PF_Y], eta))
		    x = z = PF_HUGEVAL;
		else
		{
		    float       iy;
		    
		    iy = 1.0f / viewVec[PF_Y];
		    x = viewVec[PF_X] * iy;
		    z = viewVec[PF_Z] * iy;
		}
		
		intens = 1.0f - ((x * x) * horizParam + (z * z) * vertParam);
		
		if (intens <= 0.0f)
		    alpha = ambient;
		else if (intens >= 1.0f)
		    alpha = 1.0f;
		else
		    alpha = powf(intens, falloff) * ambientScale + ambient;
	    }

	    *img++ = 0xff;	/* Intensity is ON */
            *img++ = alpha * 255.0f;
        }
    }
    pfTexImage(tex, (uint*)image, 2, size, size, 1);
}

#define NOMINAL_NEAR_PIX_DIST   1236.075f

/* 
 * Make texture map which descibes light point fade ramp and/or
 * fog ramp. 
*/
void
pfuMakeLPStateRangeTex(pfLPointState *lps, pfTexture *tex, int size, pfFog *fog) 
{
    float       isize;
    int         i, j, dim, tsize;
    char        *img, *image;

    int		transpRangeMode, fogRangeMode;
    float	transpScale, actualSize, transpPixSize, transpClamp, transpExp;
    float	maxTranspRange, minTranspRange, deltaTranspRange;
    float	maxFogRange, minFogRange, deltaFogRange;

    transpRangeMode = pfGetLPStateMode(lps, PFLPS_TRANSP_MODE);
    fogRangeMode = pfGetLPStateMode(lps, PFLPS_FOG_MODE);
    actualSize = pfGetLPStateVal(lps, PFLPS_SIZE_ACTUAL);
    transpScale = pfGetLPStateVal(lps, PFLPS_TRANSP_SCALE);
    transpPixSize = pfGetLPStateVal(lps, PFLPS_TRANSP_PIXEL_SIZE);
    transpExp = pfGetLPStateVal(lps, PFLPS_TRANSP_EXPONENT);
    transpClamp = pfGetLPStateVal(lps, PFLPS_TRANSP_CLAMP);

    dim = (transpRangeMode == PFLPS_TRANSP_MODE_TEX) + 
          (fogRangeMode == PFLPS_FOG_MODE_TEX);

    if (dim == 0)
    {
        pfNotify(PFNFY_WARN, PFNFY_USAGE, "pfuMakeLPStateRangeTex() 0x%x "
                 "is not configured to use texturing for fog or "
                 "transparency.\n", lps);
        return;
    }
    
    if (dim == 1)
    {
        image = img = (char*)pfCalloc(1, sizeof(char) * size * 2, 
				      pfGetArena(tex));
    }
    else
    {
        image = img = (char*)pfCalloc(1, sizeof(char) * size * size * 2, 
				      pfGetArena(tex));
    }

    if (transpRangeMode == PFLPS_TRANSP_MODE_TEX)
    {
        minTranspRange = 
            transpScale * actualSize *
                NOMINAL_NEAR_PIX_DIST / 
                    (transpScale * transpPixSize);

        maxTranspRange = transpScale * actualSize *
            NOMINAL_NEAR_PIX_DIST / 
                (transpScale * transpPixSize - 
                 powf(1.0f - transpClamp, 1.0f / transpExp));
        
        deltaTranspRange = maxTranspRange - minTranspRange;
    }
    if (fogRangeMode == PFLPS_FOG_MODE_TEX)
    {
	float	onset, opaque, a, b;

	pfGetFogOffsets(fog, &onset, &opaque);
	pfGetFogRange(fog, &a, &b);
	
        minFogRange = onset + a;
        maxFogRange = opaque + b;
        deltaFogRange = maxFogRange - minFogRange;
    }

    tsize = (transpRangeMode == PFLPS_TRANSP_MODE_TEX) ? size : 1;
    isize = 1.0f / ((float)size - 1.0f);

    for (i=0; i<tsize; i++)     /* transp loop */
    {
        float   s, a, d, f;

        if (transpRangeMode == PFLPS_TRANSP_MODE_TEX)
        {
            d = minTranspRange + (float)i * isize * deltaTranspRange;
            s = actualSize * NOMINAL_NEAR_PIX_DIST / d;

            if (transpPixSize > s)
            {
                if (transpExp == 1.0f)
		    a = 1.0f - transpScale * (transpPixSize - s);
                else
                    a = 1.0f - transpScale * 
                        powf((transpPixSize - s), transpExp);

                if (a < transpClamp)
                    a = transpClamp;
            }
            else
                a = 1.0f;
        }
        else
            a = 1.0f;

        if (fogRangeMode == PFLPS_FOG_MODE_TEX)
        {
            for (j=0; j<size; j++)     /* fog loop */
            {
                d = minFogRange + (float)j * isize * deltaFogRange;
                f = 1.0f - pfGetFogDensity(fog, d);

                *img++ = 0xff;          /* intensity */
                *img++ = f * a * 0xff;  /* alpha */
            }
        }
        else
        {
	    *img++ = 0xff;	/* Intensity is ON */
            *img++ = a * 0xff;  /* alpha */
        }
    }

    pfTexRepeat(tex, PFTEX_WRAP, PFTEX_CLAMP);
    pfTexFilter(tex, PFTEX_MAGFILTER, PFTEX_BILINEAR);
    pfTexFilter(tex, PFTEX_MINFILTER, PFTEX_MIPMAP_TRILINEAR);
    pfTexFormat(tex, PFTEX_INTERNAL_FORMAT, PFTEX_IA_8);
    if (dim == 1)
        pfTexImage(tex, (uint*)image, 2, size, 1, 1);
    else
        pfTexImage(tex, (uint*)image, 2, size, size, 1);

    return;
}