/*
 * Copyright (C) 1997-2009, R3vis Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
 *
 * Original Contributor:
 *   Wes Bethel, R3vis Corporation, Marin County, California
 *   http://www.r3vis.com/
 * Additional Contributor(s):
 *
 * The OpenRM project is located at http://openrm.sourceforge.net/.
 */
/*
 * $Id: rmrstate.c,v 1.8 2006/08/02 04:57:27 wes Exp $
 * Version: $Name: v180-alpha-02 $
 * $Revision: 1.8 $
 * $Log: rmrstate.c,v $
 * Revision 1.8  2006/08/02 04:57:27  wes
 * Added default shader mode to rmglobals, and use it to init the
 * state in private_rmStateInit.
 *
 * Revision 1.7  2005/06/26 19:01:36  wes
 * Use new routine to compute viewport matrix.
 *
 * Revision 1.6  2005/02/19 16:28:54  wes
 * Distro sync and consolidation.
 * Fixes for a number of state tracking buglets.
 *
 * Revision 1.5  2004/12/11 16:19:14  wes
 * Fixed bug in how RMstate->aspect_ratio was computed.
 *
 * Revision 1.4  2004/01/16 16:48:35  wes
 * Updated copyright line for 2004.
 *
 * Revision 1.3  2003/06/14 16:24:20  wes
 * Minor documentation tweaks.
 *
 * Revision 1.2  2003/02/02 02:07:15  wes
 * Updated copyright to 2003.
 *
 * Revision 1.1.1.1  2003/01/28 02:15:23  wes
 * Manual rebuild of rm150 repository.
 *
 * Revision 1.9  2003/01/16 22:21:17  wes
 * Updated all source files to reflect new organization of header files:
 * all header files formerly located in include/rmaux, include/rmi, include/rmv
 * are now located in include/rm.
 *
 * Revision 1.8  2002/06/17 01:02:37  wes
 * Added back in code that syncs the lighting state between the render
 * state cache and the RMrstate used during rendering.
 *
 * Revision 1.7  2002/06/02 15:16:27  wes
 * Added RMstateCache code to help eliminate the number of state changes
 * made during the render traversal. The RMstateCache tracks
 * the actual OpenGL rendering state w/o the need for querying OpenGL
 * directly, and  is queried by draw code that then decides if any
 * real state changes are required given the configuration of data
 * within an RMprimitive.
 *
 * Revision 1.6  2002/04/30 19:33:26  wes
 * Updated copyright dates.
 *
 * Revision 1.5  2001/03/31 17:12:39  wes
 * v1.4.0-alpha-2 checkin.
 *
 * Revision 1.4  2000/08/23 23:28:50  wes
 * Assertions added to some routines.
 *
 * Revision 1.3  2000/05/14 23:37:11  wes
 * Added control via RMpipe attribute to how OpenGL matrix stack
 * is initialized or used during rendering.
 *
 * Revision 1.2  2000/04/20 16:29:47  wes
 * Documentation additions/enhancements, some code rearragement.
 *
 * Revision 1.1.1.1  2000/02/28 21:29:40  wes
 * OpenRM 1.2 Checkin
 *
 * Revision 1.1.1.1  2000/02/28 17:18:48  wes
 * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
 *
 */

/* documentation of public routines is incomplete in this file. */


#include <rm/rm.h>
#include "rmprivat.h"


/*
 * ----------------------------------------------------
 * @Name rmStateNew
 @pstart
 RMstate *rmStateNew (void)
 @pend

 @astart
 No arguments.
 @aend

 @dstart

 Create and initialize an RMstate object, meaning that all RMstate
 matrices are set to the identity.  Upon success, a handle to the new
 RMstate is returned to the caller.  Otherwise, a NULL pointer is
 returned to the caller.

 @dend
 * ----------------------------------------------------
 */
RMstate *
rmStateNew (void)
{
    RMstate *t = (RMstate *)calloc(1, sizeof(RMstate));

    if (RM_ASSERT(t, "rmStateNew() malloc failure") == RM_WHACKED)
	return(NULL);

    private_rmStateInit(NULL, t, (RMenum)GL_RENDER, NULL, NULL, NULL, NULL);

#if 0    
    memset(t, 0, sizeof(RMstate));
    
    /* initialize everything the right way, set matrices to I */
    rmMatrixIdentity(&(t->model));
    rmMatrixIdentity(&(t->view));
    rmMatrixIdentity(&(t->modelView));
    rmMatrixIdentity(&(t->composite));
    rmMatrixIdentity(&(t->pick));
    rmMatrixIdentity(&(t->projection));
    rmMatrixIdentity(&(t->projection_inverse));
    rmMatrixIdentity(&(t->textureMatrix));
#endif    
    return(t);
}


/*
 * ----------------------------------------------------
 * @Name rmStateDelete
 @pstart
 void rmStateDelete (RMstate *s)
 @pend

 @astart 
 RMstate *s - a handle to the RMstate object to delete (modified).
 @aend

 @dstart

 Frees the resources for an RMstate object.  No error checking is
 performed, so the result of deleting a non-object will be
 system-dependent (generllay this is something to avoid).

 No status is returned.

 @dend
 * ----------------------------------------------------
 */
void
rmStateDelete (RMstate *s)
{
    if (RM_ASSERT(s,"rmStateDelete() error: the input RMstate object is NULL.") == RM_WHACKED)
	return;
    free((void *)s);
}


/*
 * ----------------------------------------------------
 * @Name rmStateCopy
 @pstart
 void rmStateCopy (const RMstate *s,
                   RMstate *d)
 @pend

 @astart
 const RMstate *s - a handle to the source RMstate (input).

 RMstate *d - a handle to the destination RMstate (modified).
 @aend

 @dstart

 Copies the RMstate object s to the RMstate object d.  No error
 checking is performed, so the copy is only valid if s and d are valid
 RMstate objects.

 No status is returned.

 @dend
 * ----------------------------------------------------
 */
void
rmStateCopy (const RMstate *s,
	     RMstate *d)
{
    if ((RM_ASSERT(s,"rmStateCopy() error: the input RMstate object is NULL") == RM_WHACKED) ||
	(RM_ASSERT(d,"rmStateCopy() error: the destination RMstate object is NULL") == RM_WHACKED))
	return;
    
    memcpy((void *)d, (void *)s, sizeof(RMstate));
}


/*
 * ----------------------------------------------------
 * @Name rmStateGetModelViewMatrix
 @pstart
 const RMmatrix *rmStateGetModelViewMatrix (const RMstate *toQuery)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMstate object (input).
 @aend

 @dstart

 During a render-time traversal, the RMstate object reflects the
 current state of many rendering parameters as affected by nodes in
 the scene graph. The RMstate object is provided to node callback
 functions as a parameter. The rmStateGet*() family of routines can be
 used by developers to obtain current render state parameters.
 
 This routine is used to obtain a handle to the OpenGL "model-view"
 matrix.  The modelView matrix is the concatenation of model
 transformations with the view transformation defined by the current
 camera.
 
 The RMmatrix handle that is returned is "read only." NULL is returned
 if the input RMstate object is NULL.

 @dend
 * ----------------------------------------------------
 */
const RMmatrix *
rmStateGetModelViewMatrix (const RMstate *s)
{
    if (RM_ASSERT(s, "rmStateGetModelViewMatrix() error: the input RMstate object is NULL.\n") == RM_WHACKED)
	return(NULL);

    return(&(s->modelView));
}


/*
 * ----------------------------------------------------
 * @Name rmStateGetProjectionMatrix
 @pstart
 const RMmatrix *rmStateGetProjectionMatrix (const RMstate *toQuery)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMstate object (input).
 @aend

 @dstart

 During a render-time traversal, the RMstate object reflects the
 current state of many rendering parameters as affected by nodes in
 the scene graph. The RMstate object is provided to node callback
 functions as a parameter. The rmStateGet*() family of routines can be
 used by developers to obtain current render state parameters.
 
 This routine is used to obtain a handle to the OpenGL "projection"
 matrix.  The projection matrix represents the transformation from eye
 coordinates to clip coordinates, typically defined only by 3D
 cameras.
 
 The RMmatrix handle that is returned is "read only." NULL is returned
 if the input RMstate object is NULL.

 @dend
 * ----------------------------------------------------
 */
const RMmatrix *
rmStateGetProjectionMatrix (const RMstate *s)
{
    if (RM_ASSERT(s, "rmStateGetModelViewMatrix() error: the input RMstate object is NULL.\n") == RM_WHACKED)
	return(NULL);

    return(&(s->projection));
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetShader
 @pstart
 RMenum rmStateGetShader(const RMstate *toQuery)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMstate object (input).
 @aend

 @dstart
 Use this routine to obtain the shader attribute of an RMstate object.
 Upon success, one of the RM shade model enumerators is returned to the
 caller (RM_SHADER_SMOOTH, RM_SHADER_FLAT or RM_SHADER_NOLIGHT). Otherwise,
 RM_WHACKED is returned.

 This routine is intended to be used from inside application callback
 code, either node callbacks or application-defined RMprimitive draw
 routines.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetShader(const RMstate *s)
{
    if (RM_ASSERT(s,"rmStateGetShader() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    return(s->shademodel);
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetPolygonDrawMode
 @pstart
 RMenum rmStateGetPolygonDrawMode(const RMstate *toQuery,
		                  RMenum *whichFaceReturn,
				  RMenum *drawModeReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 RMenum *whichFaceReturn, *drawModeReturn - handles to caller-supplied
    RMenum's (result). A value of NULL is acceptable.
 @aend

 @dstart
 Use this routine to query the render-time values for the polygon draw
 mode. See rmNodeSetPolygonDrawMode() for more details about these parameters.
 This routine is intended to be used from inside an application callback
 that would be attached to an RMnode, to be invoked during a render-time
 traversal of the scene graph.

 If the caller specifies NULL for one of the return parameters, that
 value will not be queried.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetPolygonDrawMode(const RMstate *s,
			  RMenum *whichFaceReturn,
			  RMenum *drawModeReturn)
{
    if (RM_ASSERT(s,"rmStateGetPolygonDrawMode() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (whichFaceReturn != NULL)
	*whichFaceReturn = s->poly_mode_face;

    if (drawModeReturn != NULL)
	*drawModeReturn = s->poly_mode_drawstyle;

    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmStateGetPolygonCullMode
 @pstart
 RMenum rmStateGetPolygonCullMode(const RMstate *toQuery,
				  RMenum *cullModeReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 RMenum *cullModeReturn - handles to caller-supplied
    RMenum's (result). A value of NULL is acceptable.
 @aend

 @dstart
 Use this routine to query the render-time values for the polygon cull
 mode. See rmNodeSetPolygonCullMode() for more details about this parameter.
 This routine is intended to be used from inside an application callback
 that would be attached to an RMnode, to be invoked during a render-time
 traversal of the scene graph.

 If the caller specifies NULL for the return parameter, the polygon
 cull mode from the RMstate object will not be copied into caller-supplied
 memory.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetPolygonCullMode(const RMstate *s,
			  RMenum *cullModeReturn)
{
    if (RM_ASSERT(s,"rmStateGetPolygonCullMode() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (cullModeReturn != NULL)
	*cullModeReturn = s->cull_mode;

    return(RM_CHILL);
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetFrontFace
 @pstart
 RMenum rmStateGetFrontFace(const RMstate *toQuery,
		            RMenum *frontFaceReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 RMenum *frontFaceReturn - a handle to a caller-supplied RMenum (result).
 @aend

 @dstart
 Use this routine to query the render-time values for the polygon front
 face attribute. See rmNodeSetFrontFace() for more details about this
 parameter.  This routine is intended to be used from inside an
 application callback that would be attached to an RMnode, to be
 invoked during a render-time traversal of the scene graph.

 If the caller specifies NULL for the return parameter, the polygon
 front face mode from the RMstate object will not be copied into
 caller-supplied memory.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetFrontFace(const RMstate *s,
		    RMenum *frontFaceReturn)
{
    if (RM_ASSERT(s,"rmStateGetFrontFace() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (frontFaceReturn != NULL)
	*frontFaceReturn = s->front_face;

    return(RM_CHILL);
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetLineWidth
 @pstart
 RMenum rmStateGetLineWidth(const RMstate *toQuery,
		            RMenum *lineWidthReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 RMenum *lineStyleReturn - a handle to a caller-supplied RMenum (result).
 @aend

 @dstart
 Use this routine to query the render-time values for the current
 line style attribute. See rmNodeSetLineWidth() for more details about this
 parameter.  This routine is intended to be used from inside an
 application callback that would be attached to an RMnode, to be
 invoked during a render-time traversal of the scene graph.

 Note that an RM line width enumerator is returned, not the actual pixel
 width of the lines.

 If the caller specifies NULL for the return parameter, the line style
 attribute from the RMstate object will not be copied into
 caller-supplied memory.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */

RMenum
rmStateGetLineWidth(const RMstate *s,
		    RMenum *lineWidthReturn)
{
    if (RM_ASSERT(s,"rmStateGetLineWidth() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (lineWidthReturn != NULL)
	*lineWidthReturn = s->linewidth;

    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmStateGetLineStyle
 @pstart
 RMenum rmStateGetLineStyle(const RMstate *toQuery,
		            RMenum *lineStyleReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 RMenum *lineStyleReturn - a handle to a caller-supplied RMenum (result).
 @aend

 @dstart
 Use this routine to query the render-time values for the current
 line style attribute. See rmNodeSetLineStyle() for more details about this
 parameter.  This routine is intended to be used from inside an
 application callback that would be attached to an RMnode, to be
 invoked during a render-time traversal of the scene graph.

 If the caller specifies NULL for the return parameter, the line style
 attribute from the RMstate object will not be copied into
 caller-supplied memory.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetLineStyle(const RMstate *s,
		    RMenum *lineStyleReturn)
{
    if (RM_ASSERT(s,"rmStateGetLineStyle() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (lineStyleReturn != NULL)
	*lineStyleReturn = s->linestyle;

    return(RM_CHILL);
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetPointSize
 @pstart
 RMenum rmStateGetPointSize(const RMstate *toQuery,
		            float *sizeReturn)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMnode (input).
 float *sizeReturn - a handle to a caller-supplied float (result).
 @aend

 @dstart
 Use this routine to query the render-time values for the current
 point size attribute. See rmNodeSetPointSize() for more details about this
 parameter.  This routine is intended to be used from inside an
 application callback that would be attached to an RMnode, to be
 invoked during a render-time traversal of the scene graph.

 If the caller specifies NULL for the return parameter, the point size
 attribute from the RMstate object will not be copied into
 caller-supplied memory.

 RM_CHILL is returned upon success. Upon failure, RM_WHACKED is returned,
 and caller supplied memory remains unmodified.
 @dend
 * ----------------------------------------------------
 */
RMenum
rmStateGetPointSize(const RMstate *s,
		    float *sizeReturn)
{
    if (RM_ASSERT(s,"rmStateGetPointSize() error: the input RMstate object is NULL") == RM_WHACKED)
	return(RM_WHACKED);

    if (sizeReturn != NULL)
	*sizeReturn = s->pointsize;

    return(RM_CHILL);
}

/*
 * ----------------------------------------------------
 * @Name rmStateGetFrameNumber
 @pstart
 int rmStateGetFrameNumber(const RMstate *toQuery)
 @pend

 @astart
 const RMstate *toQuery - a handle to an RMstate object.
 @aend

 @dstart
 Use this routine to query the render-time frame number from the RMstate
 object "toQuery." This routine is intended to be used by application-
 supplied render- or view-traversal callback routines in order to
 implement operations that are a function of the current frame number.
 @dend
 * ----------------------------------------------------
 */
int
rmStateGetFrameNumber(const RMstate *toQuery)
{
    if (RM_ASSERT(toQuery, "rmStateGetFrameNumber error(): the input RMstate object is NULL. The returned frame number is invalid. ") == RM_WHACKED)
	return(0);
    else
	return(toQuery->frameNumber);
}


/* PRIVATE */
void
private_rmStateInit (const RMpipe *p,
		     RMstate *s,
		     RMenum rendermode,
		     RMmatrix *model,
		     RMmatrix *view,
		     RMmatrix *proj,
		     RMmatrix *texture)
{
    memset(s, 0, sizeof(RMstate));

    if (view != NULL)
	rmMatrixCopy(&(s->view), view);
    else
	rmMatrixIdentity(&(s->view));

    if (model != NULL)
	rmMatrixCopy(&(s->model), model);
    else
	rmMatrixIdentity(&(s->model));

    if (proj != NULL)
	rmMatrixCopy(&(s->projection), proj);
    else
	rmMatrixIdentity(&(s->projection));

    if (texture != NULL)
	rmMatrixCopy(&(s->textureMatrix), texture);
    else
	rmMatrixIdentity(&(s->textureMatrix));


    rmMatrixIdentity(&(s->pick));
    
    rmMatrixInverse(&(s->projection), &(s->projection_inverse));
    rmMatrixMultiply(&(s->model), &(s->view), &(s->modelView));
    rmMatrixMultiply(&(s->modelView), &(s->projection), &(s->composite));
    
    if (p != NULL)
    {
	float fw, fh;
	
	rmPipeGetWindowSize(p, &(s->w), &(s->h));

	/*
	 * in the RMstate structure, viewport settings are in pixel,
	 * not NDC coordinates.
	 */

	/*
	 * we assign the default viewport to take up the entire screen.
	 * eventually, we want to be able to take into account any
	 * existing viewport value that might be set.
	 */

	fw = (float)s->w;
	fh = (float)s->h;
	
	s->vp[0] = s->vp[1] = 0.0F;
	s->vp[2] = fw;
	s->vp[3] = fh;

	/* set the viewport matrix */
	private_rmComputeViewportMatrix(s->vp, fw, fh, &(s->vpm));
	
	s->aspect_ratio = fw/fh;
	
	s->frameNumber = p->frameNumber;
    }
    
    s->rendermode = rendermode;

    /* initialize various other attributes */

    {
	/* linestyle */
	extern RMenum RM_DEFAULT_LINESTYLE;
	extern RMenum RM_DEFAULT_LINEWIDTH;
	s->linestyle = RM_DEFAULT_LINESTYLE;
	s->linewidth = RM_DEFAULT_LINEWIDTH;
    }
    {
	/* polygon draw mode */
	extern RMenum RM_DEFAULT_POLYGON_DRAWMODE_WHICHFACE;
	extern RMenum RM_DEFAULT_POLYGON_DRAWMODE_MODE;
	s->poly_mode_face = RM_DEFAULT_POLYGON_DRAWMODE_WHICHFACE;
	s->poly_mode_drawstyle = RM_DEFAULT_POLYGON_DRAWMODE_MODE;
    }

    {
	extern RMenum RM_DEFAULT_SHADER;
	s->shademodel=RM_DEFAULT_SHADER;
    }

    /* need to do more initializtion here */
#if 0
    /* is this necessary/correct here? */
    s->colorMaterialActive = RM_FALSE;
    s->lightingActive = RM_FALSE;
#endif
}

RMstateCache *
private_rmStateCacheNew (void)
{
    RMstateCache *t = malloc(sizeof(RMstateCache));
    t->colorMaterialActive = RM_FALSE;
    t->lightingActive = RM_FALSE;
    t->texturingActive = RM_FALSE;
    return(t);
}

void
private_rmStateCacheDelete(RMstateCache *t)
{
    free((void *)t);
}

void
private_rmStateCacheSync(const RMstate *s,
			 RMstateCache *rsc)
{
    /* check texturing */
    if ((s->texture_mode != 0) && (rsc->texturingActive == RM_FALSE))
	rsc->texturingActive = RM_TRUE;
    else if ((s->texture_mode == 0) && (rsc->texturingActive == RM_TRUE))
	rsc->texturingActive = RM_FALSE;

    /* check lighting */
    if ((s->lightingActive == RM_TRUE) && (rsc->lightingActive == RM_FALSE))
	rsc->lightingActive = RM_TRUE;
    else if ((s->lightingActive == RM_FALSE) && (rsc->lightingActive == RM_TRUE))
	rsc->lightingActive = RM_FALSE;
    
    /* check color material state */
    if ((s->colorMaterialActive == RM_TRUE) && (rsc->colorMaterialActive == RM_FALSE))
	rsc->colorMaterialActive = RM_TRUE;
    else if ((s->colorMaterialActive == RM_FALSE) && (rsc->colorMaterialActive == RM_TRUE))
	rsc->colorMaterialActive = RM_FALSE;

}

void
private_rmSyncStateToCache(RMstateCache *rsc,
			   RMstate *s)
{
    /* sync the RMstate to the values indicated in the rsc */
#if 0
    /* check texturing */
    if ((s->texture_mode != 0) && (rsc->texturingActive == RM_FALSE))
	s->texturingActive = RM_TRUE;
    else if ((s->texture_mode == 0) && (rsc->texturingActive == RM_TRUE))
	rsc->texturingActive = RM_FALSE;
#endif
    /* check lighting */
    if ((s->lightingActive == RM_TRUE) && (rsc->lightingActive == RM_FALSE))
	s->lightingActive = RM_FALSE;
    else if ((s->lightingActive == RM_FALSE) && (rsc->lightingActive == RM_TRUE))
	s->lightingActive = RM_TRUE;
    
    /* check color material state */
    if ((s->colorMaterialActive == RM_TRUE) && (rsc->colorMaterialActive == RM_FALSE))
	s->colorMaterialActive = RM_FALSE;
    else if ((s->colorMaterialActive == RM_FALSE) && (rsc->colorMaterialActive == RM_TRUE))
	s->colorMaterialActive = RM_TRUE;

}
/* EOF */
