Ejemplo n.º 1
0
void
SoUnknownEngine::copyContents(const SoFieldContainer *fromFC,
			      SbBool copyConnections)
//
////////////////////////////////////////////////////////////////////////
{
    // Make sure the copy has the correct class name
    const SoUnknownEngine *fromUnk = (const SoUnknownEngine *) fromFC;
    setClassName(fromUnk->className);

    // For each input in the original engine, create a new input and add
    // it to the new engine

    // NOTE: We can't use SoEngine::copyContents() to copy the field
    // data, since that uses SoFieldData::overlay(), which assumes the
    // fields have the same offsets in both engines. Instead, we just
    // copy the field values ourselves.

    const SoFieldData *fromData = fromUnk->getFieldData();
    SoFieldData  *toData	= (SoFieldData *) getFieldData();
    int i;
    for (i = 0; i < fromData->getNumFields(); i++) {

	SoField      *fromField	= fromData->getField(fromUnk, i);
        const SbName fieldName	= fromData->getFieldName(i);
        SoType       fieldType	= fromField->getTypeId();
        SoField      *toField	= (SoField *) (fieldType.createInstance());

        toField->enableNotify(FALSE);
        toField->setContainer(this);
        toField->setDefault(TRUE);
        toField->enableNotify(TRUE);

        toData->addField(this, fieldName.getString(), toField);

	toField->setContainer(this);
	toField->copyFrom(*fromField);
	toField->setIgnored(fromField->isIgnored());
	toField->setDefault(fromField->isDefault());
	toField->fixCopy(copyConnections);
	if (fromField->isConnected() && copyConnections)
	    toField->copyConnection(fromField);
    }

    // Copy the outputs
    SoEngineOutputData *toOutData = (SoEngineOutputData *) getOutputData();

    SoEngineOutputList outList;
    fromUnk->getOutputs(outList);

    for(i = 0; i < outList.getLength(); i++) {
        SoEngineOutput *newOut = new SoEngineOutput;
        const SoType outType = outList[i]->getConnectionType();
	SbName outName;
        getOutputName( outList[i], outName );
	toOutData->addOutput(this, outName.getString(), newOut, outType);
	newOut->setContainer(this);
    }
}
Ejemplo n.º 2
0
void
SoUnknownNode::createFromIsA(SoMFString *isA)
//
////////////////////////////////////////////////////////////////////////
{
    for (int i = 0; i < isA->getNum(); i++) {
	SoType t = SoType::fromName((*isA)[i]);

	if (t.canCreateInstance() &&
	    t.isDerivedFrom(SoNode::getClassTypeId())) {

	    SoNode *alternateRep = (SoNode *)t.createInstance();
	    alternateRep->ref();
#ifdef DEBUG
	    if (alternateRep == NULL) {
		SoDebugError::post("SoUnknownNode::createFromIsA",
				   "SoType.createInstance returned "
				   "NULL (type %s)",
				   t.getName().getString());
		return;
	    }
#endif
	    // Copy over all fields that are shared:
	    int num = instanceFieldData->getNumFields();
	    for (int j=0; j<num; j++) {
		const SbName &fieldName = instanceFieldData->getFieldName(j);
		SoField *f = instanceFieldData->getField(this, j);
		// Don't copy over fields with default values:
		if (f->isDefault()) continue;
		
		SoField *nf = alternateRep->getField(fieldName);
		if (nf != NULL && nf->getTypeId() == f->getTypeId()) {
		    nf->copyFrom(*f);
		    if (f->isConnectedFromField()) {
			SoField *cf;
			f->getConnectedField(cf);
			nf->connectFrom(cf);
		    } else if (f->isConnectedFromEngine()) {
			SoEngineOutput *eo;
			f->getConnectedEngine(eo);
			nf->connectFrom(eo);
		    }
		}
	    }
	    // And if alternateRep is a group, copy over hidden
	    // children:
	    if (alternateRep->isOfType(SoGroup::getClassTypeId())) {
		SoGroup *g = (SoGroup *)alternateRep;
		for (int kid = 0; kid < hiddenChildren.getLength();
		     kid++) {
		    g->addChild(hiddenChildren[kid]);
		}
	    }
	    addChild(alternateRep);
	    return;
	}
    }
}
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::setCameraType(SoType type)
{
    if(!getSoRenderManager()->getCamera()->isOfType(SoPerspectiveCamera::getClassTypeId()) &&
            !getSoRenderManager()->getCamera()->isOfType(SoOrthographicCamera::getClassTypeId())) {
        Base::Console().Warning("Quarter::setCameraType",
                                "Only SoPerspectiveCamera and SoOrthographicCamera is supported.");
        return;
    }


    SoType perspectivetype = SoPerspectiveCamera::getClassTypeId();
    SbBool oldisperspective = getSoRenderManager()->getCamera()->getTypeId().isDerivedFrom(perspectivetype);
    SbBool newisperspective = type.isDerivedFrom(perspectivetype);

    if((oldisperspective && newisperspective) ||
            (!oldisperspective && !newisperspective)) // Same old, same old..
        return;


    SoCamera* currentcam = getSoRenderManager()->getCamera();
    SoCamera* newcamera = (SoCamera*)type.createInstance();

    // Transfer and convert values from one camera type to the other.
    if(newisperspective) {
        convertOrtho2Perspective((SoOrthographicCamera*)currentcam,
                                 (SoPerspectiveCamera*)newcamera);
    }
    else {
        convertPerspective2Ortho((SoPerspectiveCamera*)currentcam,
                                 (SoOrthographicCamera*)newcamera);
    }

    getSoRenderManager()->setCamera(newcamera);
    getSoEventManager()->setCamera(newcamera);

    //if the superscene has a camera we need to replace it too
    SoSeparator* superscene = (SoSeparator*) getSoRenderManager()->getSceneGraph();
    SoSearchAction sa;
    sa.setInterest(SoSearchAction::FIRST);
    sa.setType(SoCamera::getClassTypeId());
    sa.apply(superscene);

    if(sa.getPath()) {
        SoNode* node = sa.getPath()->getTail();
        SoGroup* parent = (SoGroup*) sa.getPath()->getNodeFromTail(1);

        if(node && node->isOfType(SoCamera::getClassTypeId())) {
            parent->replaceChild(node, newcamera);
        }
    }
};
void SIM::Coin3D::Quarter::SoQTQuarterAdaptor::saveHomePosition(void)
{
    SoType t = getSoRenderManager()->getCamera()->getTypeId();
    assert(t.isDerivedFrom(SoNode::getClassTypeId()));
    assert(t.canCreateInstance());

    if(m_storedcamera) {
        m_storedcamera->unref();
    }

    m_storedcamera = (SoNode*)t.createInstance();
    m_storedcamera->ref();

    m_storedcamera->copyFieldValues(getSoRenderManager()->getCamera());
}
Ejemplo n.º 5
0
/*!
  Creates an instance of a suitable SoForeignFileKit subtype.
  Returns NULL on failure or a kit with refcount of 1 on success.
*/
static SoForeignFileKit *create_foreignfilekit(const char *filename, SbBool exhaust)
{
  assert(SoForeignFileKitP::fileexts != NULL);

  const char * extptr = strrchr(filename, '.');
  if (extptr) {
    extptr++;
    SbName ext(SbString(extptr).lower());
    SoType handler = SoType::badType();
    if (SoForeignFileKitP::fileexts->get(ext.getString(), handler)) {
      SoForeignFileKit * foreignfile = (SoForeignFileKit *)handler.createInstance();
      foreignfile->ref();
      if (foreignfile->canReadFile(filename)) {
        return foreignfile;
      }
      else {
        foreignfile->unref();
      }
    }
    else {
      // We try to synthesize a classname from the extension (e.g. SoFBXFileKit),
      // and load it using the SoType autoloader feature.
      SbString filekitname;
      filekitname.sprintf("So%sFileKit", SbString(ext.getString()).upper().getString());
      SoType filekittype = SoType::fromName(SbName(filekitname));
      if (!filekittype.isBad()) return create_foreignfilekit(filename, exhaust);

      // FIXME: Some filekits supports more than one file format/extension (e.g. FBX).
      // We need a way of mapping extensions to library, or a way of loading
      // each external kit and testing for support.
      // FIXME: Temporary hack: Load SoFBXFileKit
      filekitname = "SoFBXFileKit";
      filekittype = SoType::fromName(SbName(filekitname));
      if (!filekittype.isBad()) return create_foreignfilekit(filename, exhaust);
    }
  }
  if (exhaust) {
    // FIXME: Implement
    // SoForeignFileKitP::fileexts->apply()
  }
  return NULL;
}
Ejemplo n.º 6
0
/*!
  Try creating a node of name \a name with Inventor version \a ivversion.

  Returns NULL if no such node exists.
*/
SoBase *
SoUpgrader::tryCreateNode(const SbName & name, const float ivversion)
{
  if ((ivversion == 1.0f) || (ivversion == 2.0f)) {
    soupgrader_init_classes();

    SbString s(name.getString());
    s += (ivversion == 1.0f) ? "V10" : "V20";

    if (soupgrader_exists(s.getString())) {
      SoType type = SoType::fromName(SbName(s.getString()));
      if (type.canCreateInstance()) {
        SoBase * b = (SoBase*) type.createInstance();
        if (SoInputP::debug()) {
          SoDebugError::postInfo("SoUpgrader::tryCreateNode",
                                 "name=='%s', ivversion==%f => SoBase==%p",
                                 name.getString(), ivversion, b);
        }
        return b;
      }
    }
  }
  return NULL;
}
Ejemplo n.º 7
0
TSeparatorKit* ComponentHeliostatField::CreateField()
{
	//Define heliostat tracker for the field
	QVector< TTrackerFactory* > trackersFactoryList = m_pPluginManager->GetTrackerFactories();
	if( trackersFactoryList.size() == 0 )
	{
        QMessageBox::warning( 0, QString( "Campo Heliostatos" ),
        		QString( "No se ha encontrado plugins de tipo tracker." ) );
		return 0;
	}

	QVector< QString > trackerNames;
	for( int i = 0; i < trackersFactoryList.size(); i++ )
		trackerNames<< trackersFactoryList[i]->TTrackerName();

	int selectedTracker = trackerNames.indexOf( QLatin1String( "Heliostat_tracker" ) );
	if( selectedTracker < 0 )
	{
        QMessageBox::warning( 0, QString( "Campo Heliostatos" ),
        		QString( "No se ha encontrado el plugin de tipo 'Heliostat_tracker' " ) );
		return 0;
	}

	TTrackerFactory* heliostatTrackerFactory = trackersFactoryList[ selectedTracker ];


	HeliostatFieldWizard wizard;
	if( !wizard.exec() )
	{
		QMessageBox::information( 0, QString( "Campo Heliostatos" ),
				QString( "The field has not been created." ) );
		return 0;
	}

	//Aiming point
	Point3D aimingPoint = wizard.GetHeliostatsAimingPoint();

	//Read heliostat component

	//TSeparatorKit::initClass();

	TSeparatorKit* heliostatComponentNode = OpenHeliostatComponent( wizard.GetHeliostatComponentFile() );
	if( !heliostatComponentNode )
	{
		QMessageBox::information( 0, QString( "Campo Heliostatos" ),
				QString( "Error al leer el componente para los heliostatos." ) );
		return 0;
	}


	QFile coordinatesFile( wizard.GetCoordinatesFile() );
	if( !coordinatesFile.open( QIODevice::ReadOnly ) )
	{
		QMessageBox::information( 0, QString( "Campo Heliostatos" ),
				QString( "Error al leer el archivo de coordenadas de los heliostatos." ) );
		return 0;
	}


	QTextStream coordIn( &coordinatesFile );


	std::vector< Point3D > hCenterList;
	while( !coordIn.atEnd() )
	{
		QString inLine = coordIn.readLine();
		QStringList heliostat = inLine.split(QRegExp("[\\t,;]"), QString::SkipEmptyParts);
		if( heliostat.count() >=3 )
			hCenterList.push_back( Point3D( heliostat[0].toDouble(),
					heliostat[1].toDouble(),
					heliostat[2].toDouble() ) );
	}


	SoType separatorType = SoType::fromName( SbName ( "TSeparatorKit" ) );

	/*TSeparatorKit* rootSeparator = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
	//TSeparatorKit* rootSeparator = new TSeparatorKit;
	rootSeparator->setName( "CampoHeliostatos" );
	rootSeparator->ref();

	SoNodeKitListPart* rootPartList = static_cast< SoNodeKitListPart* >( rootSeparator->getPart( "childList", true ) );
	if( !rootPartList ) return 0;
	*/


	TSeparatorKit* heliostatsNodeSeparator = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
	//TSeparatorKit* heliostatsNodeSeparator = new TSeparatorKit;
	//rootPartList->addChild(heliostatsNodeSeparator);
	heliostatsNodeSeparator->setName( "Heliostatos" );
	heliostatsNodeSeparator->ref();



	CreateHeliostatZones( hCenterList, heliostatsNodeSeparator, heliostatTrackerFactory, aimingPoint, heliostatComponentNode, 1 );

	return heliostatsNodeSeparator;

}
Ejemplo n.º 8
0
void ComponentHeliostatField::CreateHeliostatZones( std::vector< Point3D >  heliostatCenterList, TSeparatorKit* parentNode,
		TTrackerFactory* heliostatTrackerFactory,
		Point3D aimingPoint,
		TSeparatorKit* heliostatComponentNode,
		int eje )
{

	SoType separatorType = SoType::fromName( SbName ( "TSeparatorKit" ) );

	SoNodeKitListPart* heliostatsNodePartList = static_cast< SoNodeKitListPart* >( parentNode->getPart( "childList", true ) );
	if( !heliostatsNodePartList ) return;

	int nHeliostatCenters = ( int ) heliostatCenterList.size();
	if( nHeliostatCenters < 8 )
	{

		for( int nHeliostat = 0; nHeliostat < nHeliostatCenters; nHeliostat++ )
		{

			//TSeparatorKit* heliostatSeparator = new TSeparatorKit;
			TSeparatorKit* heliostatSeparator = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
			heliostatsNodePartList->addChild(heliostatSeparator);
			QString heliostatName = QString( QLatin1String( "Heliostat%1" ) ).arg( QString::number( nHeliostat ) );
			heliostatSeparator->setName( heliostatName.toStdString().c_str() );
			SoTransform* nodeTransform = dynamic_cast< SoTransform* >( heliostatSeparator->getPart( "transform", true ) );
			nodeTransform->translation.setValue( heliostatCenterList[nHeliostat].x,
					heliostatCenterList[nHeliostat].y,
					heliostatCenterList[nHeliostat].z );

			SoNodeKitListPart*  heliostatPartList = static_cast< SoNodeKitListPart* >( heliostatSeparator->getPart( "childList", true ) );
			if( !heliostatPartList ) return;

			//TSeparatorKit* heliostatTrackerNode= new TSeparatorKit;
			TSeparatorKit* heliostatTrackerNode = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
			heliostatPartList->addChild( heliostatTrackerNode );
			heliostatTrackerNode->setName( "HeliostatTrackerNode" );
			SoNodeKitListPart*  heliostaTrackerNodetPartList = static_cast< SoNodeKitListPart* >( heliostatTrackerNode->getPart( "childList", true ) );
			if( !heliostaTrackerNodetPartList ) return;

			TTracker* tracker = heliostatTrackerFactory->CreateTTracker();
			heliostatTrackerNode->setPart( "tracker", tracker );
			SoSFVec3f* aimingPointField = dynamic_cast< SoSFVec3f* > ( tracker->getField ( "aimingPoint" ) );
			if( aimingPointField )	aimingPointField->setValue( SbVec3f( aimingPoint.x, aimingPoint.y, aimingPoint.z ) );

			if( heliostatComponentNode )	heliostaTrackerNodetPartList->addChild( heliostatComponentNode );

		}
	}
	else
	{
		//TSeparatorKit* heliostatSeparator1 = new TSeparatorKit;
		TSeparatorKit* heliostatSeparator1 = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
		heliostatsNodePartList->addChild(heliostatSeparator1);
		QString heliostatName1 = QString( QLatin1String( "DivisionPor%1_1" ) ).arg( ( eje == 3 )? QString( 'Z' ): QString( 'X' ) );
		heliostatSeparator1->setName( heliostatName1.toStdString().c_str() );

		//TSeparatorKit* heliostatSeparator2 = new TSeparatorKit;
		TSeparatorKit* heliostatSeparator2 = static_cast< TSeparatorKit* > ( separatorType.createInstance() );
		heliostatsNodePartList->addChild(heliostatSeparator2);
		QString heliostatName2 = QString( QLatin1String( "DivisionPor%1_2" ) ).arg( ( eje == 3 )? QString( 'Z' ): QString( 'X' ) );
		heliostatSeparator2->setName( heliostatName2.toStdString().c_str() );


		if( fabs( eje - 3 ) < 0.001 )
		{
			std::sort( heliostatCenterList.begin(), heliostatCenterList.end(), comparePuntosPorZ );

			std::vector< Point3D >::iterator it;

			double zMin = heliostatCenterList[0].z;
			double zMax = heliostatCenterList[nHeliostatCenters-1].z;

			double splitPoint = zMin + ( 0.5 * ( zMax - zMin ) );
			std::vector< Point3D > hCenterListPart1;
			double position = 0;
			while( ( position < heliostatCenterList.size() )
					&& ( heliostatCenterList[position].z < splitPoint ) )
			{
				hCenterListPart1.push_back( heliostatCenterList[position] );
				position++;
			}


			std::vector< Point3D > hCenterListPart2;
			while( position < heliostatCenterList.size() )
			{
				hCenterListPart2.push_back( heliostatCenterList[position] );
				position++;
			}
			CreateHeliostatZones( hCenterListPart1, heliostatSeparator1, heliostatTrackerFactory, aimingPoint, heliostatComponentNode, 1 );
			CreateHeliostatZones( hCenterListPart2, heliostatSeparator2, heliostatTrackerFactory, aimingPoint, heliostatComponentNode, 1 );

		}
		else
		{
			std::sort( heliostatCenterList.begin(), heliostatCenterList.end(), comparePuntosPorX );
			double xMin = heliostatCenterList[0].x;
			double xMax = heliostatCenterList[nHeliostatCenters-1].x;

			double splitPoint = xMin + ( 0.5 * ( xMax - xMin ) );
			std::vector< Point3D > hCenterListPart1;
			double position = 0;
			while( ( position < heliostatCenterList.size() )
					&& ( heliostatCenterList[position].x < splitPoint ) )
			{
				hCenterListPart1.push_back( heliostatCenterList[position] );
				position++;
			}


			std::vector< Point3D > hCenterListPart2;
			while( position < heliostatCenterList.size() )
			{
				hCenterListPart2.push_back( heliostatCenterList[position] );
				position++;
			}
			CreateHeliostatZones( hCenterListPart1, heliostatSeparator1, heliostatTrackerFactory, aimingPoint, heliostatComponentNode, 3 );
			CreateHeliostatZones( hCenterListPart2, heliostatSeparator2, heliostatTrackerFactory, aimingPoint, heliostatComponentNode, 3 );
		}


	}
}
Ejemplo n.º 9
0
void
SoGate::setup(SoType inputType)
//
////////////////////////////////////////////////////////////////////////
{
#ifdef DEBUG
    if (input != NULL) {
	SoDebugError::post("SoGate::setup",
			   "Already initialized!");
    }
#endif

    if (inputType.isDerivedFrom(SoMField::getClassTypeId())) {
	input = (SoMField *)inputType.createInstance();
    } else {
	input = NULL;
    }
    if (input == NULL) {
#ifdef DEBUG
	SoDebugError::post("SoGate::setup",
		   "Couldn't create field of type %s",
			   inputType.getName().getString());
#endif
	conversionCase = BAD_TYPE;
    } else {

	input->setContainer(this);

	// Pass in the static field data as the parent field data for
	// the per-instance field data:
	myInputData->addField(this, "input", input);
    
	// Construct the output:
	output = new SoEngineOutput;
	output->setContainer(this);
	myOutputData->addOutput(this, "output", output, inputType);
	
// This handy macro sets up conversionCase, which is used to quickly
// decide what type we're hooked up to at evaluate() time:

#define DECIDE(class) \
	(inputType == SO__CONCAT(SoMF,class)::getClassTypeId()) { \
	     conversionCase = class; \
	}			     

	// Set up for which switch to use in evaluate() routine:
	if DECIDE(BitMask)
	else if DECIDE(Bool)
	else if DECIDE(Color)
	else if DECIDE(Enum)
	else if DECIDE(Float)
	else if DECIDE(Int32)
	else if DECIDE(Matrix)
	else if DECIDE(Name)
	else if DECIDE(Node)
	else if DECIDE(Path)
	else if DECIDE(Plane)
	else if DECIDE(Rotation)
	else if DECIDE(Short)
	else if DECIDE(String)
	else if DECIDE(Time)
	else if DECIDE(UInt32)
	else if DECIDE(UShort)
	else if DECIDE(Vec2f)
	else if DECIDE(Vec3f)
	else if DECIDE(Vec4f)
#undef DECIDE
	else {
#ifdef DEBUG
	    SoDebugError::post("SoGate::setup",
			"Can't gate field of type %s",
			inputType.getName().getString());
#endif
	    conversionCase = BAD_TYPE;
	}
    }
}    
Ejemplo n.º 10
0
void
SoUnknownNode::copyContents(const SoFieldContainer *fromFC,
			    SbBool copyConnections)
//
////////////////////////////////////////////////////////////////////////
{
    // Make sure the copy has the correct class name
    const SoUnknownNode *fromUnk = (const SoUnknownNode *) fromFC;
    setClassName(fromUnk->className);

    // For each field in the original node, create a new field and add
    // it to the new node

    // NOTE: We can't use SoNode::copyContents() to copy the field
    // data, since that uses SoFieldData::overlay(), which assumes the
    // fields have the same offsets in both nodes. Instead, we just
    // copy the field values ourselves.

    const SoFieldData *fromData = fromUnk->getFieldData();
    SoFieldData  *toData	= (SoFieldData *) getFieldData();

    int i;
    for (i = 0; i < fromData->getNumFields(); i++) {

	SoField      *fromField	= fromData->getField(fromUnk, i);
        const SbName fieldName	= fromData->getFieldName(i);
        SoType       fieldType	= fromField->getTypeId();
        SoField      *toField	= (SoField *) (fieldType.createInstance());

        toField->enableNotify(FALSE);
        toField->setContainer(this);
        toField->setDefault(TRUE);
        toField->enableNotify(TRUE);

        toData->addField(this, fieldName.getString(), toField);

	toField->setContainer(this);
	toField->copyFrom(*fromField);
	toField->setIgnored(fromField->isIgnored());
	toField->setDefault(fromField->isDefault());
	toField->fixCopy(copyConnections);
	if (fromField->isConnected() && copyConnections)
	    toField->copyConnection(fromField);
    }

    // Copy the kids
    for (i = 0; i < fromUnk->hiddenChildren.getLength(); i++) {

	// If this node is being copied, it must be "inside" (see
	// SoNode::copy() for details.) Therefore, all of its children
	// must be inside, as well, since our addToCopyDict() takes
	// care of that.
	SoNode *fromKid = fromUnk->getChild(i);
	SoNode *kidCopy = (SoNode *) findCopy(fromKid, copyConnections);

#ifdef DEBUG
	if (kidCopy == NULL)
	    SoDebugError::post("(internal) SoUnknownNode::copyContents",
			       "Child %d has not been copied yet", i);
#endif /* DEBUG */

	hiddenChildren.append(kidCopy);
    }

    // No need to copy the override flag, since this flag will have no
    // effect on an unknown node, and it is not read from or written
    // to files.
}
Ejemplo n.º 11
0
// The common create function, used for both 2D and 3D cuts of the
// volume.
CvrTextureObject *
CvrTextureObject::create(const SoGLRenderAction * action,
                         const CvrCLUT * clut,
                         /* common: */ const SbVec3s & texsize,
                         /* 3D only: */ const SbBox3s & cutcube,
                         /* 2D only: */ const SbBox2s & cutslice, 
                         const unsigned int axisidx, 
                         const int pageidx)
{
  const CvrVoxelBlockElement * vbelem = CvrVoxelBlockElement::getInstance(action->getState());
  assert(vbelem != NULL);

  const SbBool paletted = CvrCLUT::usePaletteTextures(action);
  const SbBool is2d = (axisidx != UINT_MAX);

  const CvrLightingElement * lightelem = CvrLightingElement::getInstance(action->getState());
  assert(lightelem != NULL);
  const SbBool lighting = lightelem->useLighting(action->getState());

  SoType createtype;
  if (is2d && paletted) { 
    createtype = Cvr2DPaletteTexture::getClassTypeId(); 
  }
  else if (is2d) { 
    createtype = Cvr2DRGBATexture::getClassTypeId(); 
  }
  else if (paletted && lighting) { 
    // FIXME: I believe this next may also depend on the presence of
    // support for fragment programs..? Investigate. 20050628 mortene.
    createtype = Cvr3DPaletteGradientTexture::getClassTypeId(); 
  }
  else if (paletted) { 
    createtype = Cvr3DPaletteTexture::getClassTypeId(); 
  }
  else { 
    createtype = Cvr3DRGBATexture::getClassTypeId(); 
  }

  struct CvrTextureObject::EqualityComparison incoming;
  incoming.sovolumedata_id = vbelem->getNodeId();
  incoming.cutcube = cutcube; // For 3D tex
  incoming.cutslice = cutslice; // For 2D tex
  incoming.axisidx = axisidx; // For 2D tex
  incoming.pageidx = pageidx; // For 2D tex

  CvrTextureObject * obj =
    CvrTextureObject::findInstanceMatch(createtype, incoming);
  if (obj) { 
    return obj; 
  }
  
  const SbVec3s & voxdims = vbelem->getVoxelCubeDimensions();
  const void * dataptr = vbelem->getVoxels();

  // FIXME: improve buildSubPage() interface to fix this roundabout
  // way of calling it. 20021206 mortene.
  CvrVoxelChunk * input =
    new CvrVoxelChunk(voxdims, vbelem->getBytesPrVoxel(), dataptr);
  CvrVoxelChunk * cubechunk;
  if (is2d) { 
    cubechunk = input->buildSubPage(axisidx, pageidx, cutslice); 
  }
  else { 
    cubechunk = input->buildSubCube(cutcube); 
  }
  delete input;

  CvrTextureObject * newtexobj = (CvrTextureObject *)
    createtype.createInstance();

  // The actual dimensions of the GL texture must be values that are
  // power-of-two's:
  for (unsigned int i=0; i < 3; i++) {
    // SbMax(4, ...) to work around a crash bug in older NVidia
    // drivers when a lot of 1x- or 2x-dimensions textures are
    // allocated. 20090812 mortene.
    
    newtexobj->dimensions[i] =
      SbMax((uint32_t)4, coin_geq_power_of_two(texsize[i]));
    
  }

  if (is2d) {
    // code in many other spots adds the extra +2 to make room for
    // borders in 2D textures.
    //
    // FIXME: need to audit and figure out exactly why it can't /
    // shouldn't be done here. as it is now, the extra allocations
    // are spread out in a lot of places, which seems to me to be
    // somewhat unfortunate, as there are suddenly a lot of possible
    // points of failure for (often) hard to detect errors.
    //
    // 20090813 mortene.
    
    //    newtexobj->dimensions[0] += 2;
    //    newtexobj->dimensions[1] += 2;
    newtexobj->dimensions[2] = 1;
  }
  

  SbBool invisible = FALSE;
  cubechunk->transfer(action, clut, newtexobj, invisible);
  delete cubechunk;

  // If completely transparent, and not in palette mode, we need not
  // bother with a texture object for this slice/brick at all:
  if (invisible && !paletted) {
    // FIXME: we get grave mem-leaks by just returning here, I
    // believe. Audit code in this function. 20041029 mortene.
    return NULL;
  }

  // Must clear unused texture area to prevent artifacts due to
  // floating point inaccuracies when calculating texture coords.
  newtexobj->blankUnused(texsize);

  // We'll self-destruct when the SoVolumeData node is changed.
  //
  // FIXME: need to implement the self-destruction mechanism. Should
  // attach an SoNodeSensor to the SoVolumeData-node, have a
  // "about-to-be-destroyed" callback for the owners/auditors of
  // newtexobj, etc etc. 20040721 mortene.
  //
  // UPDATE: ..or is this already taken care of higher up in the
  // call-chain? I think it may be. Investigate. 20040722 mortene.
  newtexobj->eqcmp = incoming;

  const unsigned long key = newtexobj->hashKey();
  void * ptr;
  const SbBool ok = CvrTextureObject::instancedict->find(key, ptr);
  SbList<CvrTextureObject *> * l;
  if (ok) {
    l = (SbList<CvrTextureObject *> *)ptr;
  }
  else {
    l = new SbList<CvrTextureObject *>;
    const SbBool newentry = CvrTextureObject::instancedict->enter(key, l);
    assert(newentry);
  }
  l->append(newtexobj);

  return newtexobj;
}