/** 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;
}
Exemple #6
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;
		}
	}
}