TSeparatorKit* ComponentHeliostatField::OpenHeliostatComponent( QString fileName )
{
	if ( fileName.isEmpty() ) return 0;

	SoInput componentInput;
	if ( !componentInput.openFile( fileName.toLatin1().constData() ) )
	{
        QMessageBox::warning( 0, QString( "Scene Graph Structure" ),
        		QString( "Cannot open file %1:\n." ).arg( fileName ) );
		return 0;
	}

	SoSeparator* componentSeparator = SoDB::readAll( &componentInput );
	componentInput.closeFile();

	if ( !componentSeparator )
	{
        QMessageBox::warning( 0, QString( "Scene Graph Structure" ),
        		QString( "Error reading file %1:\n%2." )
                             .arg( fileName ) );
		return 0;
	}

	TSeparatorKit* componentRoot = static_cast< TSeparatorKit* >( componentSeparator->getChild(0) );
	componentRoot->ref();


   return componentRoot;

}
void SimDynamicsWindow::updateComVisu()
{
    if (!robot)
    {
        return;
    }

    std::vector<RobotNodePtr> n = robot->getRobotNodes();
    std::map< VirtualRobot::RobotNodePtr, SoSeparator* >::iterator i = comVisuMap.begin();

    while (i != comVisuMap.end())
    {
        SoSeparator* sep = i->second;
        SoMatrixTransform* m = dynamic_cast<SoMatrixTransform*>(sep->getChild(0));

        if (m)
        {
            Eigen::Matrix4f ma = dynamicsRobot->getComGlobal(i->first);
            ma.block(0, 3, 3, 1) *= 0.001f;
            m->matrix.setValue(CoinVisualizationFactory::getSbMatrix(ma));
        }

        i++;
    }
}
Exemple #3
0
/*!
 * Reads the scene saved on the file with given \a filename and return a pointer to the scene.
 *
 * Returns null on any error.
 */
TSceneKit* Document::GetSceneKitFromFile( const QString& fileName )
{
    SoInput sceneInput;
	if ( !sceneInput.openFile( fileName.toLatin1().constData() ) )
	{
		QString message = QString( "Cannot open file %1." ).arg( fileName );
		emit Warning( message );

		return 0;
	}

	if( !sceneInput.isValidFile() )
	{
		QString message = QString( "Error reading file %1.\n" ).arg( fileName );
		emit Warning( message );

		return 0;
	}

	SoSeparator* graphSeparator = SoDB::readAll( &sceneInput );
	sceneInput.closeFile();

	if ( !graphSeparator )
	{
		QString message = QString( "Error reading file %1.\n" ).arg( fileName );
		emit Warning( message );

		return 0;
	}

   return static_cast< TSceneKit* >( graphSeparator->getChild(0) );
	return 0;
}
Exemple #4
0
void
IfWeeder::weedMaterial(SoNode *root, IfWeederMaterialEntry *entry)
{
    // If the material affects no shapes at all, get rid of it. This
    // can happen when vertex property nodes are used.
    if (entry->shapes.getLength() == 0) {
	SoSearchAction sa;
	sa.setNode(entry->material);
	sa.setInterest(SoSearchAction::ALL);
	sa.apply(root);
	for (int i = 0; i < sa.getPaths().getLength(); i++) {
	    SoPath *path = sa.getPaths()[i];
	    SoSeparator *parent = (SoSeparator *) path->getNodeFromTail(1);
	    int index = path->getIndexFromTail(0);
	    ASSERT(parent->isOfType(SoSeparator::getClassTypeId()));
	    ASSERT(parent->getChild(index) == entry->material);
	    parent->removeChild(index);
	}
    }

    // Remove all material values from the material node that are
    // not used by any dependent shapes. Adjust the indices in the
    // dependent shapes accordingly.
    removeDuplicateMaterials(entry);

    // Now remove all material values that are not used by any
    // dependent shapes. Again, adjust the indices in the dependent
    // shapes.
    removeUnusedMaterials(entry);
}
void SoRegPoint::notify(SoNotList * node)
{
    SoField * f = node->getLastField();
    if (f == &this->base || f == &this->normal || f == &this->length) {
        SoTranslation* move = static_cast<SoTranslation*>(root->getChild(0));
        move->translation.setValue(base.getValue() + normal.getValue() * length.getValue());
    }
    else if (f == &this->color) {
        SoSeparator* sub = static_cast<SoSeparator*>(root->getChild(1));
        SoBaseColor* col = static_cast<SoBaseColor*>(sub->getChild(0));
        col->rgb = this->color.getValue();
    }
    else if (f == &this->text) {
        SoSeparator* sub = static_cast<SoSeparator*>(root->getChild(1));
        SoText2* label = static_cast<SoText2*>(sub->getChild(2));
        label->string = this->text.getValue();
    }

    SoShape::notify(node);
}
void ViewProviderTransformed::unsetEdit(int ModNum)
{
    ViewProvider::unsetEdit(ModNum);

    while (pcRejectedRoot->getNumChildren() > 7) {
        SoSeparator* sep = static_cast<SoSeparator*>(pcRejectedRoot->getChild(7));
        SoMultipleCopy* rejectedTrfms = static_cast<SoMultipleCopy*>(sep->getChild(2));
        rejectedTrfms   ->removeAllChildren();
        sep->removeChild(1);
        sep->removeChild(0);
        pcRejectedRoot  ->removeChild(7);
    }
    pcRejectedRoot->removeAllChildren();

    pcRoot->removeChild(pcRejectedRoot);

    pcRejectedRoot->unref();
}
Exemple #7
0
IvObjectDragger::IvObjectDragger(QtCoinViewerPtr viewer, ItemPtr pItem, float draggerScale, bool bAllowRotation)
    : IvDragger(viewer, pItem, draggerScale)
{
    // create a root node for the dragger nodes
    _draggerRoot = new SoSeparator;
    ItemPtr selectedItem = GetSelectedItem();
    selectedItem->GetIvRoot()->insertChild(_draggerRoot, 0);

    // create and size a transform box dragger and then add it to the scene graph
    _transformBox = new SoTransformBoxDragger;

    _transformBox->scaleFactor.setValue(_ab.extents.x * _scale, _ab.extents.y * _scale, _ab.extents.z * _scale);
    _transformBox->translation.setValue(_ab.pos.x, _ab.pos.y, _ab.pos.z);
    _toffset = selectedItem->GetTransform();

    _draggerRoot->addChild(_transformBox);

    // disable the scaling part of the transform box
    _transformBox->setPart("scaler", NULL);

    // disable the rotation around the X and Z axes
    if (!bAllowRotation) {
        const char *rotators[2] = { "rotator1", "rotator3" };
        for (int i = 0; i < 2; i++)
            _transformBox->setPart(rotators[i], NULL);
    }

    // get the material node that governs the color of the dragger and
    // note the dragger's normal color
    if (bAllowRotation) {
        SoRotateCylindricalDragger *rp = (SoRotateCylindricalDragger *)_transformBox->getPart("rotator1", false);
        SoSeparator *s = (SoSeparator *) rp->getPart("rotator", false);
        _draggerMaterial = (SoMaterial *) s->getChild(0);
    }
    else
        _draggerMaterial = new SoMaterial();

    _normalColor = _draggerMaterial->diffuseColor[0];

    // add a motion callback handler for the dragger
    _transformBox->addMotionCallback(_MotionHandler, this);

    UpdateDragger();
}
Exemple #8
0
IvJointDragger::IvJointDragger(QtCoinViewerPtr viewer, ItemPtr pItem, int iSelectedLink, float draggerScale, int iJointIndex, bool bHilitJoint) : IvDragger(viewer, pItem, draggerScale)
{
    KinBodyItemPtr pbody = boost::dynamic_pointer_cast<KinBodyItem>(pItem);
    BOOST_ASSERT( !!pItem );

    _trackball = NULL;
    _draggerRoot = NULL;

    if( !pbody || !pbody->GetBody() ) {
        return;
    }
    if((iSelectedLink < 0)||(iSelectedLink >= (int)pbody->GetBody()->GetLinks().size())) {
        return;
    }
    if((iJointIndex < 0)||(iJointIndex >= (int)pbody->GetBody()->GetJoints().size())) {
        return;
    }

    _iSelectedLink = iSelectedLink;
    _iJointIndex = iJointIndex;
    KinBody::JointConstPtr pjoint = pbody->GetBody()->GetJoints().at(iJointIndex);

    _jointtype = pjoint->GetType();
    _dofindex = pjoint->GetDOFIndex();
    _jointname = pjoint->GetName();
    _jointoffset = 0; //pjoint->GetOffset();
    pjoint->GetLimits(_vlower,_vupper);

    _pLinkNode = pbody->GetIvLink(iSelectedLink);
    if( _pLinkNode == NULL ) {
        RAVELOG_WARN("no link is selected\n");
        return;
    }

    Transform tlink = pbody->GetBody()->GetLinks().at(iSelectedLink)->GetTransform();

    // create a root node for the dragger nodes
    _draggerRoot = new SoSeparator;
    SoTransform* draggertrans = new SoTransform();
    _pLinkNode->insertChild(_draggerRoot, 1); // insert right after transform

    // add a new material to change the color of the nodes being dragged
    _bHilitJoint = bHilitJoint;
    if (_bHilitJoint) {
        _material = new SoMaterial;
        _material->set("diffuseColor 0.8 0.6 0.2");
        _material->setOverride(true);
        _pLinkNode->insertChild(_material, 1);
    }

    Vector vaxes[3];
    for(int i = 0; i < pjoint->GetDOF(); ++i) {
        vaxes[i] = tlink.inverse().rotate(pjoint->GetAxis(i));
    }

    // need to make sure the rotation is pointed towards the joint axis
    Vector vnorm = Vector(1,0,0).cross(vaxes[0]);
    dReal fsinang = RaveSqrt(vnorm.lengthsqr3());
    if( fsinang > 0.0001f ) {
        vnorm /= fsinang;
    }
    else vnorm = Vector(1,0,0);

    Vector vtrans = tlink.inverse()*pjoint->GetAnchor();
    draggertrans->translation.setValue(vtrans.x, vtrans.y, vtrans.z);
    draggertrans->rotation = SbRotation(SbVec3f(vnorm.x, vnorm.y, vnorm.z), atan2f(fsinang,vaxes[0].x));
    _draggerRoot->addChild(draggertrans);

    // construct an Inventor trackball dragger
    float scale = _scale;
    _trackball = new SoTrackballDragger;
    AABB ab;
    _GetBounds(_pLinkNode, ab);
    _trackball->scaleFactor.setValue(ab.extents.x * scale, ab.extents.y * scale, ab.extents.z * scale);
    _trackball->setAnimationEnabled(false);
    _draggerRoot->addChild(_trackball);

    // get the material nodes that govern the color of the dragger and
    // note the dragger's normal color
    const char* rotators[3] = { "XRotator", "YRotator", "ZRotator" };
    const char* rotatorsActive[3] = { "XRotatorActive", "YRotatorActive", "ZRotatorActive" };

    // enable or disable each axis
    for (int i = 0; i < 3; i++) {
        if (i < pjoint->GetDOF()) {
            SoSeparator *s = (SoSeparator *)_trackball->getPart(rotators[i], false);
            _draggerMaterial[i] = (SoMaterial *) s->getChild(0);
            _normalColor = _draggerMaterial[i]->diffuseColor[0];
        }
        else {
            // disable the rotator on this axis
            _trackball->setPart(rotators[i], NULL);
            _trackball->setPart(rotatorsActive[i], NULL);
            _draggerMaterial[i] = NULL;
        }
    }

    // add a motion callback handler for the dragger
    _trackball->addMotionCallback(_MotionHandler, this);

    UpdateDragger();
}
void ViewProviderTransformed::recomputeFeature(void)
{
    PartDesign::Transformed* pcTransformed = static_cast<PartDesign::Transformed*>(getObject());
    pcTransformed->getDocument()->recomputeFeature(pcTransformed);
    const std::vector<App::DocumentObjectExecReturn*> log = pcTransformed->getDocument()->getRecomputeLog();
    PartDesign::Transformed::rejectedMap rejected_trsf = pcTransformed->getRejectedTransformations();
    unsigned rejected = 0;
    for (PartDesign::Transformed::rejectedMap::const_iterator r = rejected_trsf.begin(); r != rejected_trsf.end(); r++)
        rejected += r->second.size();
    QString msg = QString::fromLatin1("%1");
    if (rejected > 0) {
        msg = QString::fromLatin1("<font color='orange'>%1<br/></font>\r\n%2");
        if (rejected == 1)
            msg = msg.arg(QObject::tr("One transformed shape does not intersect support"));
        else {
            msg = msg.arg(QObject::tr("%1 transformed shapes do not intersect support"));
            msg = msg.arg(rejected);
        }
    }
    if (log.size() > 0) {
        msg = msg.arg(QString::fromLatin1("<font color='red'>%1<br/></font>"));
        msg = msg.arg(QString::fromStdString(log.back()->Why));
    } else {
        msg = msg.arg(QString::fromLatin1("<font color='green'>%1<br/></font>"));
        msg = msg.arg(QObject::tr("Transformation succeeded"));
    }
    signalDiagnosis(msg);

    // Clear all the rejected stuff
    while (pcRejectedRoot->getNumChildren() > 7) {
        SoSeparator* sep = static_cast<SoSeparator*>(pcRejectedRoot->getChild(7));
        SoMultipleCopy* rejectedTrfms = static_cast<SoMultipleCopy*>(sep->getChild(2));
        rejectedTrfms   ->removeAllChildren();
        sep->removeChild(1);
        sep->removeChild(0);
        pcRejectedRoot  ->removeChild(7);
    }

    for (PartDesign::Transformed::rejectedMap::const_iterator o = rejected_trsf.begin(); o != rejected_trsf.end(); o++) {
        if (o->second.empty()) continue;

        TopoDS_Shape shape;
        if ((o->first)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) {
            PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(o->first);
            shape = feature->AddSubShape.getShape().getShape();
        }

        if (shape.IsNull()) continue;

        // Display the rejected transformations in red
        TopoDS_Shape cShape(shape);

        try {
            // calculating the deflection value
            Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
            {
                Bnd_Box bounds;
                BRepBndLib::Add(cShape, bounds);
                bounds.SetGap(0.0);
                bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
            }
            Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();

            // create or use the mesh on the data structure
            // Note: This DOES have an effect on cShape
#if OCC_VERSION_HEX >= 0x060600
            Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
            BRepMesh_IncrementalMesh(cShape,deflection,Standard_False,
                                        AngDeflectionRads,Standard_True);
#else
            BRepMesh_IncrementalMesh(cShape,deflection);
#endif
            // We must reset the location here because the transformation data
            // are set in the placement property
            TopLoc_Location aLoc;
            cShape.Location(aLoc);

            // count triangles and nodes in the mesh
            int nbrTriangles=0, nbrNodes=0;
            TopExp_Explorer Ex;
            for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
                Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
                // Note: we must also count empty faces
                if (!mesh.IsNull()) {
                    nbrTriangles += mesh->NbTriangles();
                    nbrNodes     += mesh->NbNodes();
                }
            }

            // create memory for the nodes and indexes
            SoCoordinate3* rejectedCoords = new SoCoordinate3();
            rejectedCoords  ->point      .setNum(nbrNodes);
            SoNormal* rejectedNorms = new SoNormal();
            rejectedNorms   ->vector     .setNum(nbrNodes);
            SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet();
            rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4);

            // get the raw memory for fast fill up
            SbVec3f* verts = rejectedCoords  ->point      .startEditing();
            SbVec3f* norms = rejectedNorms   ->vector     .startEditing();
            int32_t* index = rejectedFaceSet ->coordIndex .startEditing();

            // preset the normal vector with null vector
            for (int i=0; i < nbrNodes; i++)
                norms[i]= SbVec3f(0.0,0.0,0.0);

            int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0;
            for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
                TopLoc_Location aLoc;
                const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
                // get the mesh of the shape
                Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
                if (mesh.IsNull()) continue;

                // getting the transformation of the shape/face
                gp_Trsf myTransf;
                Standard_Boolean identity = true;
                if (!aLoc.IsIdentity()) {
                    identity = false;
                    myTransf = aLoc.Transformation();
                }

                // getting size of node and triangle array of this face
                int nbNodesInFace = mesh->NbNodes();
                int nbTriInFace   = mesh->NbTriangles();
                // check orientation
                TopAbs_Orientation orient = actFace.Orientation();

                // cycling through the poly mesh
                const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
                const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
                for (int g=1; g <= nbTriInFace; g++) {
                    // Get the triangle
                    Standard_Integer N1,N2,N3;
                    Triangles(g).Get(N1,N2,N3);

                    // change orientation of the triangle if the face is reversed
                    if ( orient != TopAbs_FORWARD ) {
                        Standard_Integer tmp = N1;
                        N1 = N2;
                        N2 = tmp;
                    }

                    // get the 3 points of this triangle
                    gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));

                    // transform the vertices to the place of the face
                    if (!identity) {
                        V1.Transform(myTransf);
                        V2.Transform(myTransf);
                        V3.Transform(myTransf);
                    }

                    // calculating per vertex normals
                    // Calculate triangle normal
                    gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
                    gp_Vec Normal = (v2-v1)^(v3-v1);

                    // add the triangle normal to the vertex normal for all points of this triangle
                    norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                    norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                    norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());

                    // set the vertices
                    verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
                    verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
                    verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));

                    // set the index vector with the 3 point indexes and the end delimiter
                    index[FaceTriaOffset*4+4*(g-1)]   = FaceNodeOffset+N1-1;
                    index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1;
                    index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1;
                    index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
                }

                // counting up the per Face offsets
                FaceNodeOffset += nbNodesInFace;
                FaceTriaOffset += nbTriInFace;
            }

            // normalize all normals
            for (int i=0; i < nbrNodes; i++)
                norms[i].normalize();

            // end the editing of the nodes
            rejectedCoords  ->point      .finishEditing();
            rejectedNorms   ->vector     .finishEditing();
            rejectedFaceSet ->coordIndex .finishEditing();

            // fill in the transformation matrices
            SoMultipleCopy* rejectedTrfms = new SoMultipleCopy();
            rejectedTrfms->matrix.setNum((o->second).size());
            SbMatrix* mats = rejectedTrfms->matrix.startEditing();

            std::list<gp_Trsf>::const_iterator trsf = (o->second).begin();
            for (unsigned int i=0; i < (o->second).size(); i++,trsf++) {
                Base::Matrix4D mat;
                Part::TopoShape::convertToMatrix(*trsf,mat);
                mats[i] = convert(mat);
            }
            rejectedTrfms->matrix.finishEditing();
            rejectedTrfms->addChild(rejectedFaceSet);
            SoSeparator* sep = new SoSeparator();
            sep->addChild(rejectedCoords);
            sep->addChild(rejectedNorms);
            sep->addChild(rejectedTrfms);
            pcRejectedRoot->addChild(sep);
        }
        catch (...) {
            Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n",
                                  pcTransformed->getNameInDocument());
        }
    }

}
Exemple #10
0
	IVElement::IVElement(string ivfile, KthReal sc) {
		for(int i=0;i<3;i++){
			position[i]= 0.0f;
			orientation[i]=0.0f;
		}
		orientation[2]=1.0f;
		orientation[3]=0.0f;
		scale=sc;

		trans= new SoTranslation;
		rot = new SoRotation;
		sca = new SoScale();
		color = new SoMaterial;

		posVec = new SoSFVec3f;
		trans->translation.connectFrom(posVec);
		posVec->setValue((float)position[0],(float)position[1],(float)position[2]);

		rotVec = new SoSFRotation;
		rotVec->setValue(SbVec3f((float)orientation[0],(float)orientation[1],
				(float)orientation[2]),(float)orientation[3]);
		rot->rotation.connectFrom(rotVec);

		scaVec= new SoSFVec3f;
		scaVec->setValue((float)scale,(float)scale,(float)scale);
		sca->scaleFactor.connectFrom(scaVec);

		SoInput input;
		ivmodel = new SoSeparator;
		ivmodel->ref();
		ivmodel->addChild(sca);

		if(input.openFile(ivfile.c_str()))
			ivmodel->addChild(SoDB::readAll(&input));
		else
		{
			//ivmodel->addChild(new SoSphere());
			static const char *str[] = { 
				"#VRML V1.0 ascii\n",
				"DEF pointgoal Separator {\n",
				"  Separator {\n",
				"    MaterialBinding { value PER_PART }\n",
				"    Coordinate3 {\n",
				"      point [\n",
				"        0.0 0.0 0.0\n",
				"      ]\n",
				"    }\n",
				"    DrawStyle { pointSize 5 }\n",
				"    PointSet { }\n",
				"   }\n",
				"}\n",
				NULL
			};
			input.setStringArray(str);
			SoSeparator *sep = SoDB::readAll(&input);
			sep->ref();
			while (sep->getNumChildren() > 0)
			{
				ivmodel->addChild(sep->getChild(0));
				sep->removeChild(0);
			}
			sep->unref();
			
		}

		ivmodel->ref();

	}
SoCamera * 
SoSceneTextureCubeMapP::ensureCamera(void)
{
  if (this->hasSceneChanged == FALSE) return this->cachedCamera;

  this->hasSceneChanged = FALSE;
  SoCamera * camera    = this->findCamera();
  SbBool     hasCamera = (camera != NULL); // does the scene provide a camera?

  if (hasCamera) {
    if (this->cachedCamera != camera) {
      if (this->cachedCamera) this->cachedCamera->unref();
      this->cachedCamera = camera;
      this->cachedCamera->ref();
    }
  }
  else if (this->hadSceneCamera || this->cachedCamera == NULL) {
    // create default camera:
    static int didwarn = 0;
    if (!didwarn) {
      SoDebugError::postWarning("SoSceneTextureCubeMap::ensureCamera",
                                "The scene does not provide a camera. "
                                "A perspective camera at position (0,0,0) "
                                "will be used.");
      didwarn = 1;
    }
    if (this->cachedCamera) this->cachedCamera->unref();
    this->cachedCamera = new SoPerspectiveCamera;
    this->cachedCamera->position = SbVec3f(0, 0, 0);
    this->cachedCamera->nearDistance = 0.1f;
    this->cachedCamera->farDistance = 100;
    ((SoPerspectiveCamera*)this->cachedCamera)->heightAngle =
      (float) (M_PI / 2.0f);
    this->cachedCamera->ref();
  }
  assert(this->cachedCamera);

  SoNode * scene = PUBLIC(this)->scene.getValue();
  if (hasCamera) {
    if (scene != this->cachedScene) {
      if (this->cachedScene) this->cachedScene->unref();
      this->cachedScene = scene;
      this->cachedScene->ref();
    }
  }
  else if (this->cachedScene == NULL || this->hadSceneCamera) {
    if (this->cachedScene) this->cachedScene->unref();
    SoSeparator * root = new SoSeparator();
    root->addChild(this->cachedCamera);
    root->addChild(scene);
    this->cachedScene = (SoNode *)root;
    this->cachedScene->ref();
  }
  else {
    assert(this->cachedScene->isOfType(SoSeparator::getClassTypeId()));
    SoSeparator * root = (SoSeparator*)this->cachedScene;
    assert(root->getNumChildren() == 2);
    if (root->getChild(1) != scene)
      ((SoSeparator *)this->cachedScene)->replaceChild(1, scene);
  }

  this->hadSceneCamera = hasCamera;
  return this->cachedCamera;
}
void SoFCBoundingBox::GLRender (SoGLRenderAction *action)
{
    SbVec3f corner[2], ctr, *vptr;
    SbBool coord, dimension;

    // grab the current state
    //SoState *state = action->getState();

    if (!shouldGLRender(action))
        return;

    // get the latest values from the fields
    corner[0] = minBounds.getValue();
    corner[1] = maxBounds.getValue();
    coord     = coordsOn.getValue();
    dimension = dimensionsOn.getValue();

    // set the coordinates for the LineSet to point to
    vptr = bboxCoords->point.startEditing();
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 3; j++) {
            vptr[i][j] = corner[bBoxVerts[i][j]][j];
        }
    }

    // if coord is true then set the text nodes
    if (coord) {
        ctr = (corner[1] - corner[0]) / 2.0f;
        for (int i = 0; i < 8; i++) {
            // create the string for the text
            std::stringstream str;
            str.precision(2);
            str.setf(std::ios::fixed | std::ios::showpoint);
            str << "(" << vptr[i][0] << "," << vptr[i][1] << "," << vptr[i][2] << ")";

            SoSeparator *sep   = (SoSeparator *)textSep->getChild(i);
            SoTransform *trans = (SoTransform *)sep->getChild(0);

            trans->translation.setValue(vptr[i].getValue());
            SoText2* t = (SoText2 *)sep->getChild(1);
            t->string.setValue(str.str().c_str());
        }

        textSep->ref();
        if (root->findChild(textSep) < 0)
            root->addChild(textSep);
    } else {
        if (root->findChild(textSep) >= 0)
            root->removeChild(textSep);
    }

    // if dimension is true then set the text nodes
    if (dimension) {
        ctr = (corner[1] - corner[0]) / 2.0f;
        for (int i = 0; i < 3; i++) {
            // create the string for the text
            std::stringstream str;
            str.precision(2);
            str.setf(std::ios::fixed | std::ios::showpoint);
            str << (2.0f * ctr[i]);

            SoSeparator *sep   = (SoSeparator *)dimSep->getChild(i);
            SoTransform *trans = (SoTransform *)sep->getChild(0);

            SbVec3f point = corner[0];
            point[i] += ctr[i];
            trans->translation.setValue(point.getValue());
            SoText2* t = (SoText2 *)sep->getChild(1);
            t->string.setValue(str.str().c_str());
        }

        dimSep->ref();
        if (root->findChild(dimSep) < 0)
            root->addChild(dimSep);
    } else {
        if (root->findChild(dimSep) >= 0)
            root->removeChild(dimSep);
    }

    bboxCoords->point.finishEditing();

    // Avoid shading
    SoState * state = action->getState();
    state->push();
    SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
    root->GLRender(action);
    state->pop();
}