/** dlfunc wrappers * These function abstract dlopen,dlsym and dlclose for win32, OS-X, BeOS * and POSIX etc. */ void * CqPluginBase::DLOpen( CqString *library ) { void * handle = NULL; Aqsis::log() << info << "Loading plugin \"" << library->c_str() << "\"" << std::endl; #ifndef AQSIS_NO_PLUGINS #ifdef AQSIS_SYSTEM_WIN32 handle = ( void* ) LoadLibrary( library->c_str() ); #else CqString tstring = *library; CqString::size_type pos = tstring.find ("/"); if (pos == CqString::npos) tstring = CqString("./") + *library; handle = ( void * ) dlopen( tstring.c_str(), RTLD_NOW); #endif #endif // AQSIS_NO_PLUGINS if ( handle ) m_activeHandles.push_back( handle ); else /** \todo <b>Code Review</b>: Re-evaluate how the error handling works * here. For now we report the error, but perhaps it would be better * to throw an exception and let the calling code handle the problem. */ Aqsis::log() << error << "Error loading plugin: \"" << DLError() << "\"\n"; return handle; }
/** This returns a list of descriptors of calls to external DSO functions that * implement a named shadeop, entries are returned for each polymorphic function */ std::list<SqDSOExternalCall*>* CqDSORepository::getShadeOpMethods(CqString* pShadeOpName) { CqString strTableSymbol = *pShadeOpName + "_shadeops" ; std::list<SqDSOExternalCall*>* oplist = new (std::list<SqDSOExternalCall*>); std::list<CqString>::iterator itPathEntry; SqShadeOp *pTableSymbol = NULL; Aqsis::log() << debug << "Looking for DSO candidates for shadeop \"" << pShadeOpName->c_str() << "\"" << std::endl; for ( itPathEntry = m_DSOPathList.begin() ; itPathEntry != m_DSOPathList.end() ; itPathEntry++ ) { Aqsis::log() << debug << "Looking in shared library : " << itPathEntry->c_str() << std::endl; void *handle = DLOpen( &(*itPathEntry) ); if( handle != NULL ) { pTableSymbol = (SqShadeOp*) DLSym( handle, &strTableSymbol ); if ( pTableSymbol != NULL ) { //We have an appropriate named shadeop table SqShadeOp *pShadeOp = (SqShadeOp*) pTableSymbol; while( ( pShadeOp->m_opspec )[0] != (char) NULL ) { SqDSOExternalCall *pDSOCall = NULL; pDSOCall = parseShadeOpTableEntry( handle, pShadeOp ); if ( pDSOCall != NULL ) oplist->push_back( pDSOCall ); pShadeOp++; }; }; // Failure here does not neccesarily mean anything since } else { CqString strError = DLError(); Aqsis::log() << error << "DLOpen: " << strError.c_str() << std::endl; }; }; std::stringstream resultStr; if(oplist->empty()) resultStr << "(none found)"; else resultStr << "(found " << oplist->size() << " possibilities)"; Aqsis::log() << debug << "Finished looking for DSO candidates "<< resultStr.str().c_str() << std::endl; return ( oplist->empty() ? NULL : oplist ); };
SqDSOExternalCall* CqDSORepository::parseShadeOpTableEntry(void* handle, SqShadeOp* pShadeOpEntry) { TqInt length = strlen(pShadeOpEntry->m_opspec)+1; char temp[1024]; strncpy(temp, pShadeOpEntry->m_opspec,length); // We remove all the '(),' charachters, so we are left with // returntype name argtype ... for (int x = 0; x < length; x++) if(temp[x]=='('||temp[x]==')'||temp[x]==',') temp[x]=' '; CqString strSpec(temp); // Get the return type of the function std::string strRetType; strRetType = strtok(temp, " "); m_itTypeNameMap = m_TypeNameMap.find(strRetType.c_str()); // ERROR if we cant find this types name; if (m_itTypeNameMap == m_TypeNameMap.end()) { Aqsis::log() << warning << "Discarding DSO Table entry due to unsupported return type: \"" << strRetType.c_str() << "\"" << std::endl; return NULL; } EqVariableType rettype = (*m_itTypeNameMap).second; // Get function name std::string strMethodName; strMethodName = strtok(NULL, " "); CqString s = strMethodName.c_str(); DSOMethod method = (DSOMethod) DLSym (handle,&s); if(method == NULL) { Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for method: \"" << strMethodName.c_str() << "\"" << std::endl; return NULL; }; // Parse each arg type, presumably we need to handle arrays here std::list<EqVariableType> arglist; char *nextarg = NULL; do { // Get the next arguments type std::string strArgType; nextarg = strtok(NULL, " "); if (nextarg == NULL) break; strArgType = nextarg; m_itTypeNameMap = m_TypeNameMap.find(strArgType.c_str()); // ERROR if we cant find this arguments type name; if (m_itTypeNameMap == m_TypeNameMap.end()) { Aqsis::log() << warning << "Discarding DSO Table entry due to unsupported argument type: \"" << strArgType.c_str() << "\"" << std::endl; return NULL; }; arglist.push_back((*m_itTypeNameMap).second); } while(nextarg); // Check if there is a valid init function CqString strInit = pShadeOpEntry->m_init; DSOInit initfunc = NULL; if (strcmp(pShadeOpEntry->m_init,"")) { initfunc = (DSOInit) DLSym(handle,&strInit); if (initfunc == NULL) { Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for init: \"" << strInit.c_str() << "\"" << std::endl; return NULL; // ERROR ; }; } // Check if there is a valid shutdown function CqString strShutdown = pShadeOpEntry->m_shutdown; DSOShutdown shutdownfunc = NULL; if (strcmp(pShadeOpEntry->m_shutdown,"")) { shutdownfunc = (DSOShutdown) DLSym(handle,&strShutdown); if (shutdownfunc == NULL) { Aqsis::log() << warning << "Discarding DSO Table entry due to unknown symbol for shutdown: \"" << strShutdown.c_str() << "\"" << std::endl; return NULL; // ERROR ; }; }; // We have a valid shadeop implementation SqDSOExternalCall *ret = new SqDSOExternalCall; ret->method = method; ret->init = initfunc; ret->shutdown = shutdownfunc; ret->return_type = rettype; ret->arg_types = arglist; ret->initData = NULL; ret->initialised = false; return ret; };
/** \brief Shadeops "texture3d" to restore any parameter from one pointcloud file refer. * \param ptc the name of the pointcloud file * \param position * \param normal * \result result 0 or 1 * \param pShader shaderexecenv * \param cParams number of remaining user parameters. * \param aqParams list of user parameters (to save to ptc) */ void CqShaderExecEnv::SO_texture3d(IqShaderData* ptc, IqShaderData* position, IqShaderData* normal, IqShaderData* Result, IqShader* pShader, TqInt cParams, IqShaderData** apParams ) { const CqBitVector& RS = RunningState(); CqString ptcName; ptc->GetString(ptcName); Partio::ParticlesData* pointFile = g_texture3dCloudCache.find(ptcName); bool varying = position->Class() == class_varying || normal->Class() == class_varying || Result->Class() == class_varying; int npoints = varying ? shadingPointCount() : 1; CqString coordSystem = "world"; std::vector<UserVar> userVars; if(!pointFile || !parseTexture3dVarargs(cParams, apParams, pointFile, coordSystem, userVars)) { // Error - no point file or no arguments to look up: set result to 0 // and return. for(int igrid = 0; igrid < npoints; ++igrid) if(!varying || RS.Value(igrid)) Result->SetFloat(0, igrid); return; } /// Compute transformations CqMatrix positionTrans; getRenderContext()->matSpaceToSpace("current", coordSystem.c_str(), pShader->getTransform(), pTransform().get(), 0, positionTrans); CqMatrix normalTrans = normalTransform(positionTrans); // Grab the standard attributes for computing filter weights Partio::ParticleAttribute positionAttr, normalAttr, radiusAttr; pointFile->attributeInfo("position", positionAttr); pointFile->attributeInfo("normal", normalAttr); pointFile->attributeInfo("radius", radiusAttr); for(int igrid = 0; igrid < npoints; ++igrid) { if(varying && !RS.Value(igrid)) continue; CqVector3D cqP, cqN; position->GetPoint(cqP, igrid); cqP = positionTrans*cqP; normal->GetNormal(cqN, igrid); cqN = normalTrans*cqN; // Using the four nearest neighbours for filtering is roughly the // minimum we can get away with for a surface made out of // quadrilaterals. This isn't exactly perfect near edges but it seems // to be good enough. // // Since the lookups happen without prefiltering, no effort is made to // avoid aliasing by using a filter radius based on the size of the // current shading element. const int nfilter = 4; Partio::ParticleIndex indices[nfilter]; float distSquared[nfilter]; float maxRadius2 = 0; V3f P(cqP.x(), cqP.y(), cqP.z()); // The reinterpret_casts are ugly here of course, but V3f is basically // a POD type, so they work ok. int pointsFound = pointFile->findNPoints(reinterpret_cast<float*>(&P), nfilter, FLT_MAX, indices, distSquared, &maxRadius2); if(pointsFound < nfilter) { Result->SetFloat(0.0f, igrid); Aqsis::log() << error << "Not enough points found to filter!"; } // Read position, normal and radius V3f foundP[nfilter]; pointFile->dataAsFloat(positionAttr, nfilter, indices, false, reinterpret_cast<float*>(foundP)); V3f foundN[nfilter]; pointFile->dataAsFloat(normalAttr, nfilter, indices, false, reinterpret_cast<float*>(foundN)); float foundRadius[nfilter]; pointFile->dataAsFloat(radiusAttr, nfilter, indices, false, foundRadius); // Compute filter weights for nearby points. inverseWidthSquared // decides the blurryness of the gaussian filter. The value was chosen // by eyeballing the results of various widths. As usual it's a trade // off: Too small a value will be too blurry, (and artifacty if nfilter // is 4); too large a value and it ends up looking like nearest // neighbour filtering. const float inverseWidthSquared = 1.3f; float weights[nfilter]; float totWeight = 0; V3f N(cqN.x(), cqN.y(), cqN.z()); for(int i = 0; i < nfilter; ++i) { // The weights depend on how well the normals are aligned, and the // distance between the current shading point and the points found // in the point cloud. float wN = std::max(0.0f, N.dot(foundN[i])); // TODO: Speed this up using a lookup table for exp? float wP = std::exp(-inverseWidthSquared * distSquared[i] / (foundRadius[i]*foundRadius[i])); // Clamping to a minimum of 1e-7 means the weights don't quite // become zero as distSquared becomes large, so texture lookups // even far from any point in the cloud return something nonzero. // // Not sure if this is a good idea or not, so commented out for now // wP = std::max(1e-7f, wP); float w = wN*wP; weights[i] = w; totWeight += w; } // Normalize the weights float renorm = totWeight != 0 ? 1/totWeight : 0; for(int i = 0; i < nfilter; ++i) weights[i] *= renorm; for(std::vector<UserVar>::const_iterator var = userVars.begin(); var != userVars.end(); ++var) { // Read and filter each piece of user-defined data float varData[16*nfilter]; pointFile->dataAsFloat(var->attr, nfilter, indices, false, varData); int varSize = var->attr.count; float accum[16]; for(int c = 0; c < varSize; ++c) accum[c] = 0; for(int i = 0; i < nfilter; ++i) for(int c = 0; c < varSize; ++c) accum[c] += weights[i] * varData[i*varSize + c]; // Ah, if only we could get at the raw floats stored by // IqShaderData, we wouldn't need this switch switch(var->type) { case type_float: var->value->SetFloat(accum[0], igrid); break; case type_color: var->value->SetColor(CqColor(accum[0], accum[1], accum[2]), igrid); break; case type_point: var->value->SetPoint(CqVector3D(accum[0], accum[1], accum[2]), igrid); break; case type_normal: var->value->SetNormal(CqVector3D(accum[0], accum[1], accum[2]), igrid); break; case type_vector: var->value->SetVector(CqVector3D(accum[0], accum[1], accum[2]), igrid); break; case type_matrix: var->value->SetMatrix(CqMatrix(accum), igrid); break; default: assert(0 && "unknown type"); } } // Return success for this point Result->SetFloat(1.0f, igrid); } }
// Parse and validate the varargs part of the texture3d argument list. // // nargs and args specify the varargs list. static bool parseTexture3dVarargs(int nargs, IqShaderData** args, const Partio::ParticlesData* pointFile, CqString& coordSystem, std::vector<UserVar>& userVars) { userVars.reserve(nargs/2); CqString paramName; for(int i = 0; i+1 < nargs; i+=2) { if(args[i]->Type() != type_string) { Aqsis::log() << error << "unexpected non-string for parameter name in texture3d()\n"; return false; } args[i]->GetString(paramName); IqShaderData* paramValue = args[i+1]; EqVariableType paramType = paramValue->Type(); // Parameters with special meanings may be present in the varargs // list, and shouldn't be looked up in the file: if(paramName == "coordsystem" && paramType == type_string) paramValue->GetString(coordSystem); else if(paramName == "filterradius") ; // For brick maps; ignored for now else if(paramName == "filterscale") ; // For brick maps; ignored for now else if(paramName == "maxdepth") ; // For brick maps; ignored for now else { // If none of the above special cases, we have a user-defined // variable. Look it up in the point file, and check whether the // type corresponds with the provided shader variable. Partio::ParticleAttribute attr; pointFile->attributeInfo(paramName.c_str(), attr); if(attr.type != Partio::FLOAT && attr.type != Partio::VECTOR) { Aqsis::log() << warning << "texture3d: Can't load non-float data \"" << paramName << "\"\n"; continue; } int desiredCount = 0; switch(paramType) { case type_float: desiredCount = 1; break; case type_point: desiredCount = 3; break; case type_color: desiredCount = 3; break; case type_normal: desiredCount = 3; break; case type_vector: desiredCount = 3; break; case type_matrix: desiredCount = 16; break; default: Aqsis::log() << warning << "texture3d: Can't load non float-based argument \"" << paramName << "\"\n"; continue; } if(desiredCount != attr.count) { Aqsis::log() << warning << "texture3d: variable \"" << paramName << "\" mismatched in point file\n"; continue; } userVars.push_back(UserVar(paramValue, paramType, attr)); } } return userVars.size() > 0; }
/** \brief Extract details about a shader variable. * * \param shaderVar - variable holding the data to be extracted * \param theArgsArray - array into which the shader variable details should be * stored * \param theNArgs - index into theArgsArray. (Data will be stored in * theArgsArray[theNArgs] ) */ static void AddShaderVar( IqShaderData * shaderVar, SLX_VISSYMDEF * theArgsArray, int *theNArgs ) { EqVariableType theType; EqVariableClass theClass; SLX_TYPE slxType; CqString varNameCqStr; char * varNameCStr; char * theVarNameStr; int nameLength; char * defaultVal = NULL; char * defaultValString = NULL; int defaultValLength; char * spacename; int arrayLen = 0; int arrayIndex; if ( shaderVar != NULL && shaderVar->fParameter() ) { theType = shaderVar->Type(); theClass = shaderVar->Class(); varNameCqStr = shaderVar->strName(); varNameCStr = ( char * ) varNameCqStr.c_str(); nameLength = strlen( varNameCStr ); theVarNameStr = ( char * ) malloc( nameLength + 1 ); strcpy( theVarNameStr, varNameCStr ); spacename = NULL; switch ( theType ) { case type_float: { TqFloat aTqFloat; RtFloat aRtFloat; slxType = SLX_TYPE_SCALAR; if ( !shaderVar->isArray()) { shaderVar->GetFloat( aTqFloat ); aRtFloat = aTqFloat; defaultValLength = sizeof( RtFloat ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtFloat, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtFloat ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetFloat( aTqFloat ); aRtFloat = aTqFloat; memcpy( defaultVal + ( arrayIndex * sizeof( RtFloat ) ), &aRtFloat, sizeof( RtFloat ) ); } } spacename = ( char * ) malloc( 1 ); *spacename = 0x0; // NULL string StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_string: { CqString aCqString; char * aCString; slxType = SLX_TYPE_STRING; if ( !shaderVar->isArray() ) { shaderVar->GetString( aCqString ); aCString = ( char * ) aCqString.c_str(); defaultValLength = strlen( aCString ) + 1; defaultValString = ( char * ) malloc( defaultValLength ); strcpy( defaultValString, aCString ); defaultVal = ( char * ) malloc( sizeof( char * ) ); memcpy( defaultVal, &defaultValString, sizeof( char * ) ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( char * ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetString( aCqString ); aCString = ( char * ) aCqString.c_str(); defaultValLength = strlen( aCString ) + 1; defaultValString = ( char * ) malloc( defaultValLength ); strcpy( defaultValString, aCString ); memcpy( defaultVal + ( arrayIndex * sizeof( char * ) ), &defaultValString, sizeof( char * ) ); } } spacename = ( char * ) malloc( 1 ); *spacename = 0x0; // NULL string StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_point: { CqVector3D aCqVector3D; RtPoint aRtPoint; slxType = SLX_TYPE_POINT; if ( !shaderVar->isArray() ) { shaderVar->GetPoint( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; defaultValLength = sizeof( RtPoint ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtPoint, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtPoint ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetPoint( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; memcpy( defaultVal + ( arrayIndex * sizeof( RtPoint ) ), &aRtPoint, sizeof( RtPoint ) ); } } // shader evaluation space - RI_CURRENT, RI_SHADER, RI_EYE or RI_NDC // just go with RI_CURRENT for now spacename = ( char * ) malloc( sizeof( "current" ) + 1 ); strcpy( spacename, "current" ); StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_normal: { CqVector3D aCqVector3D; RtPoint aRtPoint; slxType = SLX_TYPE_NORMAL; if ( !shaderVar->isArray() ) { shaderVar->GetNormal( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; defaultValLength = sizeof( RtPoint ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtPoint, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtPoint ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetNormal( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; memcpy( defaultVal + ( arrayIndex * sizeof( RtPoint ) ), &aRtPoint, sizeof( RtPoint ) ); } } // shader evaluation space - RI_CURRENT, RI_SHADER, RI_EYE or RI_NDC // just go with RI_CURRENT for now spacename = ( char * ) malloc( sizeof( "current" ) + 1 ); strcpy( spacename, "current" ); StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_vector: { CqVector3D aCqVector3D; RtPoint aRtPoint; slxType = SLX_TYPE_VECTOR; if ( !shaderVar->isArray() ) { shaderVar->GetPoint( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; defaultValLength = sizeof( RtPoint ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtPoint, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtPoint ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetPoint( aCqVector3D ); aRtPoint[ 0 ] = aCqVector3D[ 0 ]; aRtPoint[ 1 ] = aCqVector3D[ 1 ]; aRtPoint[ 2 ] = aCqVector3D[ 2 ]; memcpy( defaultVal + ( arrayIndex * sizeof( RtPoint ) ), &aRtPoint, sizeof( RtPoint ) ); } } // shader evaluation space - RI_CURRENT, RI_SHADER, RI_EYE or RI_NDC // just go with RI_CURRENT for now spacename = ( char * ) malloc( sizeof( "current" ) + 1 ); strcpy( spacename, "current" ); StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_color: { CqColor aCqColor; RtColor aRtColor; slxType = SLX_TYPE_COLOR; if ( !shaderVar->isArray() ) { shaderVar->GetColor( aCqColor ); aRtColor[ 0 ] = aCqColor.r(); aRtColor[ 1 ] = aCqColor.g(); aRtColor[ 2 ] = aCqColor.b(); defaultValLength = sizeof( RtColor ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtColor, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtColor ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetColor( aCqColor ); aRtColor[ 0 ] = aCqColor[ 0 ]; aRtColor[ 1 ] = aCqColor[ 1 ]; aRtColor[ 2 ] = aCqColor[ 2 ]; memcpy( defaultVal + ( arrayIndex * sizeof( RtColor ) ), &aRtColor, sizeof( RtColor ) ); } } // shader evaluation space - RI_RGB, RI_RGBA, RI_RGBZ, RI_RGBAZ, RI_A, RI_Z or RI_AZ // just go with RI_RGB for now spacename = ( char * ) malloc( sizeof( "rgb" ) + 1 ); strcpy( spacename, "rgb" ); StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; case type_matrix: { CqMatrix aCqMatrix; RtMatrix aRtMatrix; slxType = SLX_TYPE_MATRIX; if ( !shaderVar->isArray() ) { shaderVar->GetMatrix( aCqMatrix ); aRtMatrix[ 0 ][ 0 ] = aCqMatrix[ 0 ][ 0 ]; aRtMatrix[ 0 ][ 1 ] = aCqMatrix[ 0 ][ 1 ]; aRtMatrix[ 0 ][ 2 ] = aCqMatrix[ 0 ][ 2 ]; aRtMatrix[ 0 ][ 3 ] = aCqMatrix[ 0 ][ 3 ]; aRtMatrix[ 1 ][ 0 ] = aCqMatrix[ 1 ][ 0 ]; aRtMatrix[ 1 ][ 1 ] = aCqMatrix[ 1 ][ 1 ]; aRtMatrix[ 1 ][ 2 ] = aCqMatrix[ 1 ][ 2 ]; aRtMatrix[ 1 ][ 3 ] = aCqMatrix[ 1 ][ 3 ]; aRtMatrix[ 2 ][ 0 ] = aCqMatrix[ 2 ][ 0 ]; aRtMatrix[ 2 ][ 1 ] = aCqMatrix[ 2 ][ 1 ]; aRtMatrix[ 2 ][ 2 ] = aCqMatrix[ 2 ][ 2 ]; aRtMatrix[ 2 ][ 3 ] = aCqMatrix[ 2 ][ 3 ]; aRtMatrix[ 3 ][ 0 ] = aCqMatrix[ 3 ][ 0 ]; aRtMatrix[ 3 ][ 1 ] = aCqMatrix[ 3 ][ 1 ]; aRtMatrix[ 3 ][ 2 ] = aCqMatrix[ 3 ][ 2 ]; aRtMatrix[ 3 ][ 3 ] = aCqMatrix[ 3 ][ 3 ]; defaultValLength = sizeof( RtMatrix ); defaultVal = ( char * ) malloc( defaultValLength ); memcpy( defaultVal, &aRtMatrix, defaultValLength ); } else { arrayLen = shaderVar->ArrayLength(); defaultValLength = sizeof( RtMatrix ) * arrayLen; defaultVal = ( char * ) malloc( defaultValLength ); for ( arrayIndex = 0; arrayIndex < arrayLen; arrayIndex++ ) { shaderVar->ArrayEntry( arrayIndex ) ->GetMatrix( aCqMatrix ); aRtMatrix[ 0 ][ 0 ] = aCqMatrix[ 0 ][ 0 ]; aRtMatrix[ 0 ][ 1 ] = aCqMatrix[ 0 ][ 1 ]; aRtMatrix[ 0 ][ 2 ] = aCqMatrix[ 0 ][ 2 ]; aRtMatrix[ 0 ][ 3 ] = aCqMatrix[ 0 ][ 3 ]; aRtMatrix[ 1 ][ 0 ] = aCqMatrix[ 1 ][ 0 ]; aRtMatrix[ 1 ][ 1 ] = aCqMatrix[ 1 ][ 1 ]; aRtMatrix[ 1 ][ 2 ] = aCqMatrix[ 1 ][ 2 ]; aRtMatrix[ 1 ][ 3 ] = aCqMatrix[ 1 ][ 3 ]; aRtMatrix[ 2 ][ 0 ] = aCqMatrix[ 2 ][ 0 ]; aRtMatrix[ 2 ][ 1 ] = aCqMatrix[ 2 ][ 1 ]; aRtMatrix[ 2 ][ 2 ] = aCqMatrix[ 2 ][ 2 ]; aRtMatrix[ 2 ][ 3 ] = aCqMatrix[ 2 ][ 3 ]; aRtMatrix[ 3 ][ 0 ] = aCqMatrix[ 3 ][ 0 ]; aRtMatrix[ 3 ][ 1 ] = aCqMatrix[ 3 ][ 1 ]; aRtMatrix[ 3 ][ 2 ] = aCqMatrix[ 3 ][ 2 ]; aRtMatrix[ 3 ][ 3 ] = aCqMatrix[ 3 ][ 3 ]; memcpy( defaultVal + ( arrayIndex * sizeof( RtMatrix ) ), &aRtMatrix, sizeof( RtMatrix ) ); } } // shader evaluation space - RI_CURRENT, RI_SHADER, RI_EYE or RI_NDC // just go with RI_CURRENT for now spacename = ( char * ) malloc( sizeof( "current" ) + 1 ); strcpy( spacename, "current" ); StoreShaderArgDef( theArgsArray, *theNArgs, theVarNameStr, slxType, spacename, defaultVal, arrayLen ); ( *theNArgs ) ++; } break; default: break; } } }