////////////////////////////////////////////////////////////////////// // // Pixie // // Copyright © 1999 - 2003, Okan Arikan // // Contact: okan@cs.berkeley.edu // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU 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 // General Public License for more details. // // You should have received a copy of the GNU 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 // /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // File : attributes.cpp // Classes : CAttributes // Description : Implementation // //////////////////////////////////////////////////////////////////////// #include #include #include "attributes.h" #include "ri.h" #include "renderer.h" #include "stats.h" #include "photonMap.h" #include "irradiance.h" #include "error.h" /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : CAttributes // Description : The constructor, the default values for // attributes are given here // Return Value : - // Comments : // Date last edited : 3/11/2003 CAttributes::CAttributes() { next = NULL; refCount = 0; stats.numAttributes++; stats.attributesMemory += sizeof(CAttributes); surface = NULL; displacement = NULL; atmosphere = NULL; interior = NULL; exterior = NULL; usedParameters = 0; initv(surfaceColor,1,1,1); initv(surfaceOpacity,1,1,1); s[0] = 0.0; s[1] = 1.0; s[2] = 0.0; s[3] = 1.0; t[0] = 0.0; t[1] = 0.0; t[2] = 1.0; t[3] = 1.0; initv(bmin,C_INFINITY,C_INFINITY,C_INFINITY); initv(bmax,-C_INFINITY,-C_INFINITY,-C_INFINITY); bexpand = 0.00001f; // Epsilon { int i,j; for (i=0;i<4;i++) for (j=0;j<4;j++) { uBasis[element(i,j)] = RiBezierBasis[i][j]; vBasis[element(i,j)] = RiBezierBasis[i][j]; } } uStep = 3; vStep = 3; nSides = 2; flags = 0; flags |= ATTRIBUTES_FLAGS_PRIMARY_VISIBLE; flags |= ATTRIBUTES_FLAGS_SINGULARITYFIX; minSubdivision = 2; maxSubdivision = 5; flatness = 0.5f; pointDeviation = C_INFINITY; normalDeviation = cosf(radians(45)); maxDisplacement = 0; maxDisplacementSpace = NULL; lightSources = NULL; shadingRate = 1.0f; motionFactor = 0.0f; name = NULL; numUProbes = 4; numVProbes = 4; minSplits = 2; rasterExpand = 0.5f; shadowBias = 0.01f; transmission = 'o'; emit = -1; relativeEmit = 1; shadingModel = SM_MATTE; globalMapName = NULL; causticMapName = NULL; globalMap = NULL; causticMap = NULL; irradianceHandle = NULL; irradianceHandleMode = NULL; irradianceMaxError = 1.0f; irradianceMaxPixelDistance = 20.0f; photonEstimator = 100; photonIor = 1.5; maxDiffuseDepth = 1; maxSpecularDepth = 2; shootStep = 1000; // Shoot 1000 rays at a time lodRange[0] = -C_INFINITY; lodRange[1] = -C_INFINITY; lodRange[2] = C_INFINITY; lodRange[3] = C_INFINITY; lodSize = 0; lodImportance = 1; defaultsReady = FALSE; defaults = NULL; } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : CAttributes // Description : This functions creates an exact replica of // another attribute set // Return Value : - // Comments : // Date last edited : 3/13/2003 CAttributes::CAttributes(const CAttributes *a) { CActiveLight *cLight,*nLight; stats.numAttributes++; stats.attributesMemory += sizeof(CAttributes); this[0] = a[0]; refCount = 0; if (surface != NULL) surface->attach(); if (displacement != NULL) displacement->attach(); if (atmosphere != NULL) atmosphere->attach(); if (interior != NULL) interior->attach(); if (exterior != NULL) exterior->attach(); if (globalMapName != NULL) globalMapName = strdup(a->globalMapName); if (causticMapName != NULL) causticMapName = strdup(a->causticMapName); if (globalMap != NULL) globalMap->attach(); if (causticMap != NULL) causticMap->attach(); irradianceHandle = (a->irradianceHandle == NULL ? NULL : strdup(a->irradianceHandle)); irradianceHandleMode = (a->irradianceHandleMode == NULL ? NULL : strdup(a->irradianceHandleMode)); if (a->maxDisplacementSpace != NULL) maxDisplacementSpace = strdup(a->maxDisplacementSpace); lightSources = NULL; for (cLight=a->lightSources;cLight!=NULL;cLight=cLight->next) { nLight = new CActiveLight; nLight->light = cLight->light; nLight->defaults = NULL; nLight->next = lightSources; lightSources = nLight; } name = (a->name != NULL ? strdup(a->name) : NULL); defaultsReady = FALSE; defaults = NULL; if (a->next != NULL) next = new CAttributes(a->next); } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : ~CAttributes // Description : Deallocate everything // Return Value : - // Comments : // Date last edited : 3/3/2001 CAttributes::~CAttributes(){ CActiveLight *cLight; CGlobalDefault *cGlobal; stats.numAttributes--; stats.attributesMemory -= sizeof(CAttributes); if (surface != NULL) surface->detach(); if (displacement != NULL) displacement->detach(); if (atmosphere != NULL) atmosphere->detach(); if (interior != NULL) interior->detach(); if (exterior != NULL) exterior->detach(); if (globalMapName != NULL) free(globalMapName); if (causticMapName != NULL) free(causticMapName); if (globalMap != NULL) globalMap->detach(); if (causticMap != NULL) causticMap->detach(); if (irradianceHandle != NULL) free(irradianceHandle); if (irradianceHandleMode != NULL) free(irradianceHandleMode); if (name != NULL) free(name); if (maxDisplacementSpace != NULL) free(maxDisplacementSpace); while((cLight=lightSources) != NULL) { lightSources = cLight->next; while((cGlobal=(CGlobalDefault*)cLight->defaults) != NULL) { cLight->defaults = (CGlobalDefault*)cGlobal->next; delete cGlobal; } delete cLight; } while((cGlobal=defaults) != NULL) { defaults = cGlobal->next; delete cGlobal; } if (next != NULL) delete next; } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : addLight // Description : Obvious ! // Return Value : - // Comments : // Date last edited : 3/3/2001 void CAttributes::addLight(CShaderInstance *cLight) { CActiveLight *nLight; for (nLight=lightSources;nLight!=NULL;nLight=nLight->next) { if (nLight->light == cLight) return; } nLight = new CActiveLight; nLight->defaults = NULL; nLight->light = (CProgrammableShaderInstance*) cLight; nLight->next = lightSources; lightSources = nLight; } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : removeLight // Description : This method must be used to remove a light // source from the active light source list // Return Value : - // Comments : // Date last edited : 3/3/2001 void CAttributes::removeLight(CShaderInstance *light) { CActiveLight *cLight,*pLight; CGlobalDefault *cGlobal; for (pLight=NULL,cLight=lightSources;cLight!=NULL;pLight=cLight,cLight=cLight->next) { if (cLight->light == light) { if (pLight == NULL) lightSources = cLight->next; else pLight->next = cLight->next; while((cGlobal=(CGlobalDefault*)cLight->defaults) != NULL) { cLight->defaults = (CGlobalDefault*)cGlobal->next; delete cGlobal; } delete cLight; break; } } } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : lightParameterCheck // Description : Check the light parameters // Return Value : - // Comments : // Date last edited : 3/3/2001 void CAttributes::checkParameters() { CActiveLight *cLight; usedParameters = 0; if (displacement != NULL) usedParameters |= displacement->requiredParameters(); if (surface != NULL) usedParameters |= surface->requiredParameters(); if (atmosphere != NULL) usedParameters |= atmosphere->requiredParameters(); if (interior != NULL) usedParameters |= interior->requiredParameters(); if (exterior != NULL) usedParameters |= exterior->requiredParameters(); if (surface == NULL) usedParameters |= PARAMETER_N; for (cLight=lightSources;cLight!=NULL;cLight=cLight->next) { usedParameters |= cLight->light->requiredParameters(); } } /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : initDefaults & initLightDefaults // Description : Initialise the default global variables // Return Value : - // Comments : // Date last edited : 3/3/2001 // Init the default values #define performInitCopy() \ for (;cDef!=NULL;cDef=cDef->next) { \ CVariable *cVar = cDef->variable; \ \ i = ((cVar->container == CONTAINER_UNIFORM) ? 1 : numVertices); \ numItems = cVar->numItems; \ \ switch(cVar->type) { \ case TYPE_FLOAT: \ \ srcFloat = (const float *) cDef->value; \ destFloat = variables[cVar->entry]; \ for (;i>0;i--) { \ for (j=0;jentry]; \ for (;i>0;i--) { \ srcFloat = (const float *) cDef->value; \ for (j=numItems;j>0;j--) { \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ } \ } \ break; \ case TYPE_MATRIX: \ \ destFloat = variables[cVar->entry]; \ for (;i>0;i--) { \ srcFloat = (const float *) cDef->value; \ for (j=numItems;j>0;j--) { \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ } \ } \ break; \ \ case TYPE_QUAD: \ \ destFloat = variables[cVar->entry]; \ for (;i>0;i--) { \ srcFloat = (const float *) cDef->value; \ for (j=numItems;j>0;j--) { \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ } \ } \ break; \ \ case TYPE_DOUBLE: \ \ destFloat = variables[cVar->entry]; \ for (;i>0;i--) { \ srcFloat = (const float *) cDef->value; \ for (j=numItems;j>0;j--) { \ *destFloat++ = *srcFloat++; \ *destFloat++ = *srcFloat++; \ } \ } \ break; \ \ case TYPE_STRING: \ \ destString = (const char **) variables[cVar->entry]; \ for (;i>0;i--) { \ srcString = (const char **) cDef->value; \ for (j=numItems;j>0;j--) { \ *destString++ = *srcString++; \ } \ } \ break; \ \ case TYPE_INTEGER: \ case TYPE_BOOLEAN: \ default: \ error(CODE_BUG,"Unexpected global variable type\n"); \ break; \ } \ } void CAttributes::initDefaults(int numVertices,float **variables) { CGlobalDefault *cDef; const float *srcFloat; const char **srcString; float *destFloat; const char **destString; int i,j,numItems; // Are the variables that we need to init collected ? if (defaultsReady == FALSE) { CActiveLight *cLight; // Ask every shader to register global parameter defaults if (surface != NULL) surface->registerDefaults(this); if (displacement != NULL) displacement->registerDefaults(this); if (atmosphere != NULL) atmosphere->registerDefaults(this); if (interior != NULL) interior->registerDefaults(this); if (exterior != NULL) exterior->registerDefaults(this); for (cLight=lightSources;cLight!=NULL;cLight=cLight->next) cLight->light->registerDefaults(this,cLight); defaultsReady = TRUE; } cDef = defaults; performInitCopy(); } void CAttributes::initLightDefaults(int numVertices,float **variables, CActiveLight *light) const { CGlobalDefault *cDef; const float *srcFloat; const char **srcString; float *destFloat; const char **destString; int i,j,numItems; // We are initializing defaults for a light, the defaults // must already be ready because lights can only be called from // within another shading context cDef = (CGlobalDefault*)light->defaults; performInitCopy(); } #undef performInitCopy /////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : addDefault // Description : Add a global variable that needs to be defaulted // Return Value : - // Comments : // Date last edited : 3/3/2001 void CAttributes::addDefault(CVariable *cVariable,void *cData,CActiveLight *light) { CGlobalDefault *cDefault = new CGlobalDefault; if ( light != NULL ){ // These are defaults for a light cDefault->variable = cVariable; cDefault->value = cData; cDefault->next = (CGlobalDefault*)light->defaults; light->defaults = cDefault; } else { cDefault->variable = cVariable; cDefault->value = cData; cDefault->next = defaults; defaults = cDefault; } }