Ejemplo n.º 1
0
void
IfReplacer::replaceMaterials(SoNode *sceneRoot, const SoType &typeToReplace)
{
    // Find all nodes of the given type
    SoSearchAction sa;
    sa.setType(typeToReplace);
    sa.setInterest(SoSearchAction::ALL);
    sa.apply(sceneRoot);

    // Replace the tail of each path with a material. To do this, we
    // need to apply an SoCallbackAction to the path to gather the
    // material components.
    for (int i = 0; i < sa.getPaths().getLength(); i++) {

	// Cast the path to a full path, just in case
	SoFullPath *path = (SoFullPath *) sa.getPaths()[i];
	ASSERT(path->getTail()->isOfType(typeToReplace));

	// The path better have at least one group above the material
	if (path->getLength() < 2 ||
	    ! path->getNodeFromTail(1)->isOfType(SoGroup::getClassTypeId()))
	    continue;

	// Create a material node that represents the material in
	// effect at the tail of the path
	SoMaterial *newMaterial = createMaterialForPath(path);
	newMaterial->ref();
	
	// Replace the tail node with that material
	SoGroup *parent = (SoGroup *) path->getNodeFromTail(1);
	parent->replaceChild(path->getTail(), newMaterial);
	       
	newMaterial->unref();
    }
}
Ejemplo n.º 2
0
void
SoBoxHighlightRenderAction::drawBoxes(SoPath * pathtothis, const SoPathList * pathlist)
{
  int i;
  int thispos = reclassify_cast<SoFullPath *>(pathtothis)->getLength()-1;
  assert(thispos >= 0);
  PRIVATE(this)->postprocpath->setHead(pathtothis->getHead()); // reset

  for (i = 1; i < thispos; i++) {
    PRIVATE(this)->postprocpath->append(pathtothis->getIndex(i));
  }

  // we need to disable accumulation buffer antialiasing while
  // rendering selected objects
  int oldnumpasses = this->getNumPasses();
  this->setNumPasses(1);

  SoState * thestate = this->getState();
  thestate->push();

  for (i = 0; i < pathlist->getLength(); i++) {
    SoFullPath * path = reclassify_cast<SoFullPath *>((*pathlist)[i]);
    PRIVATE(this)->postprocpath->append(path->getHead());
    for (int j = 1; j < path->getLength(); j++) {
      PRIVATE(this)->postprocpath->append(path->getIndex(j));
    }

    // Previously SoGLRenderAction was used to draw the bounding boxes
    // of shapes in selection paths, by overriding renderstyle state
    // elements to lines drawstyle and simply doing:
    //
    //   SoGLRenderAction::apply(PRIVATE(this)->postprocpath); // Bug
    //
    // This could have the unwanted side effect of rendering
    // non-selected shapes, as they could be part of the path (due to
    // being placed below SoGroup nodes (instead of SoSeparator
    // nodes)) up to the selected shape.
    //
    //
    // A better approach turned out to be to soup up and draw only the
    // bounding boxes of the selected shapes:
    PRIVATE(this)->drawHighlightBox(PRIVATE(this)->postprocpath);

    // Remove temporary path from path buffer
    PRIVATE(this)->postprocpath->truncate(thispos);
  }

  this->setNumPasses(oldnumpasses);
  thestate->pop();
}
Ejemplo n.º 3
0
//////////////////////////////////////////////////////////////////////////////
//
//  beginTraversal - have the base class render the passed scene graph,
//  then render highlights for our selection node.
//
void
SoLineHighlightRenderAction::apply(SoNode *node)
//
//////////////////////////////////////////////////////////////////////////////
{
    // Render the scene
    SoGLRenderAction::apply(node);

    // Render the highlight?
    if (! hlVisible) return;

    // Add the rendering localRoot beneath our local scene graph localRoot
    // so that we can find a path from localRoot to the selection node 
    // which is under the render root.
    localRoot->addChild(node);
    
    // Find the selection node under the local root
    static SoSearchAction *sa = NULL;
    if (sa == NULL)
	sa = new SoSearchAction;
    else
	sa->reset();
    sa->setFind(SoSearchAction::TYPE);
    sa->setInterest(SoSearchAction::FIRST);
    sa->setType(SoSelection::getClassTypeId());
    sa->apply(localRoot);
    
    SoPath *hlPath = sa->getPath();
    if (hlPath != NULL) {
	hlPath = hlPath->copy();
	hlPath->ref();
	
	// Make sure something is selected
	SoSelection *sel = (SoSelection *) hlPath->getTail();
	if (sel->getNumSelected() > 0) {
	    // Keep the length from the root to the selection
	    // as an optimization so we can reuse this data
	    int reusablePathLength = hlPath->getLength();
    
	    // For each selection path, create a new path rooted under our localRoot
	    for (int j = 0; j < sel->getNumSelected(); j++) {
		// Continue the path down to the selected object.
		// No need to deal with p[0] since that is the sel node.
		SoFullPath *p = (SoFullPath *) sel->getPath(j);
		SoNode *pathTail = p->getTail();

		if ( pathTail->isOfType(SoBaseKit::getClassTypeId())) {
		    // Find the last nodekit on the path.
		    SoNode *kitTail = ((SoNodeKitPath *)p)->getTail();

		    // Extend the selectionPath until it reaches this last kit.
		    SoFullPath *fp = (SoFullPath *) p;
		    int k = 0;
		    do {
			hlPath->append(fp->getIndex(++k));
		    } 
		    while ( fp->getNode(k) != kitTail );
		}
		else {
		    for (int k = 1; k < p->getLength(); k++)
			hlPath->append(p->getIndex(k));
		}
	
		// Render the shape with the local draw style to make the highlight
		SoGLRenderAction::apply(hlPath);
			
		// Restore hlPath for reuse
		hlPath->truncate(reusablePathLength);
	    }
	}
	
	hlPath->unref();
    }
    
    // Remove the rendering localRoot from our local scene graph
    localRoot->removeChild(node);
}    
Ejemplo n.º 4
0
// doc from parent
void
SoFCSelection::handleEvent(SoHandleEventAction * action)
{
    static char buf[513];
    HighlightModes mymode = (HighlightModes) this->highlightMode.getValue();
    const SoEvent * event = action->getEvent();
#ifdef NO_FRONTBUFFER
    // mouse move events for preselection
    if (event->isOfType(SoLocation2Event::getClassTypeId())) {
        // NOTE: If preselection is off then we do not check for a picked point because otherwise this search may slow
        // down extremely the system on really big data sets. In this case we just check for a picked point if the data
        // set has been selected.
        if (mymode == AUTO || mymode == ON) {
            const SoPickedPoint * pp = this->getPickedPoint(action);
            if (pp && pp->getPath()->containsPath(action->getCurPath())) {
                if (!highlighted) {
                    if (Gui::Selection().setPreselect(documentName.getValue().getString()
                                           ,objectName.getValue().getString()
                                           ,subElementName.getValue().getString()
                                           ,pp->getPoint()[0]
                                           ,pp->getPoint()[1]
                                           ,pp->getPoint()[2])){
                        SoFCSelection::turnoffcurrent(action);
                        SoFCSelection::currenthighlight = (SoFullPath*)action->getCurPath()->copy();
                        SoFCSelection::currenthighlight->ref();
                        highlighted = TRUE;
                        this->touch(); // force scene redraw
                        this->redrawHighlighted(action, TRUE);
                    }
                }
                
                snprintf(buf,512,"Preselected: %s.%s.%s (%f,%f,%f)",documentName.getValue().getString()
                                           ,objectName.getValue().getString()
                                           ,subElementName.getValue().getString()
                                           ,pp->getPoint()[0]
                                           ,pp->getPoint()[1]
                                           ,pp->getPoint()[2]);

                getMainWindow()->showMessage(QString::fromAscii(buf),3000);
            }
            else { // picked point
                if (highlighted) {
                    if (mymode == AUTO)
                        SoFCSelection::turnoffcurrent(action);
                    //FIXME: I think we should set 'highlighted' to false whenever no point is picked
                    //else
                    highlighted = FALSE;
                    Gui::Selection().rmvPreselect();
                }
            }
        }
    } // key press events
    else if (event->isOfType(SoKeyboardEvent ::getClassTypeId())) {
        SoKeyboardEvent  * const e = (SoKeyboardEvent  *) event;
        if (SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::LEFT_SHIFT)     ||
            SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::RIGHT_SHIFT)     )
            bShift = true;
        if (SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::LEFT_SHIFT)   ||
            SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::RIGHT_SHIFT)   )
            bShift = false;
        if (SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::LEFT_CONTROL)   ||
            SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::RIGHT_CONTROL)   )
            bCtrl = true;
        if (SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::LEFT_CONTROL) ||
            SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::RIGHT_CONTROL) )
            bCtrl = false;
    } // mouse press events for (de)selection
    else if (event->isOfType(SoMouseButtonEvent::getClassTypeId())) {
        SoMouseButtonEvent * const e = (SoMouseButtonEvent *) event;
        if (SoMouseButtonEvent::isButtonReleaseEvent(e,SoMouseButtonEvent::BUTTON1)) {
            //FIXME: Shouldn't we remove the preselection for newly selected objects?
            //       Otherwise the tree signals that an object is preselected even though it is hidden. (Werner)
            const SoPickedPoint * pp = this->getPickedPoint(action);
            if (pp && pp->getPath()->containsPath(action->getCurPath())) {
                if (bCtrl) {
                    if (Gui::Selection().isSelected(documentName.getValue().getString()
                                         ,objectName.getValue().getString()
                                         ,subElementName.getValue().getString())) {
                        Gui::Selection().rmvSelection(documentName.getValue().getString()
                                          ,objectName.getValue().getString()
                                          ,subElementName.getValue().getString());
                    } else {
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                          ,objectName.getValue().getString()
                                          ,subElementName.getValue().getString()
                                          ,pp->getPoint()[0]
                                          ,pp->getPoint()[1]
                                          ,pp->getPoint()[2]);

                        if (mymode == OFF) {
                            snprintf(buf,512,"Selected: %s.%s.%s (%f,%f,%f)",documentName.getValue().getString()
                                                       ,objectName.getValue().getString()
                                                       ,subElementName.getValue().getString()
                                                       ,pp->getPoint()[0]
                                                       ,pp->getPoint()[1]
                                                       ,pp->getPoint()[2]);

                            getMainWindow()->showMessage(QString::fromAscii(buf),3000);
                        }
                    }
                }
                else { // Ctrl
                    if (!Gui::Selection().isSelected(documentName.getValue().getString()
                                         ,objectName.getValue().getString()
                                         ,subElementName.getValue().getString())) {
                        Gui::Selection().clearSelection(documentName.getValue().getString());
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                              ,objectName.getValue().getString()
                                              ,subElementName.getValue().getString()
                                              ,pp->getPoint()[0]
                                              ,pp->getPoint()[1]
                                              ,pp->getPoint()[2]);
                    }
                    else {
                        Gui::Selection().clearSelection(documentName.getValue().getString());
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                              ,objectName.getValue().getString()
                                              ,0
                                              ,pp->getPoint()[0]
                                              ,pp->getPoint()[1]
                                              ,pp->getPoint()[2]);
                    }

                    if (mymode == OFF) {
                        snprintf(buf,512,"Selected: %s.%s.%s (%f,%f,%f)",documentName.getValue().getString()
                                                   ,objectName.getValue().getString()
                                                   ,subElementName.getValue().getString()
                                                   ,pp->getPoint()[0]
                                                   ,pp->getPoint()[1]
                                                   ,pp->getPoint()[2]);

                        getMainWindow()->showMessage(QString::fromAscii(buf),3000);
                    }
                }

                action->setHandled(); 
            } // picked point
        } // mouse release
    }

    inherited::handleEvent(action);
#else
    // If we don't need to pick for locate highlighting,
    // then just behave as separator and return.
    // NOTE: we still have to pick for ON even though we don't have
    // to re-render, because the app needs to be notified as the mouse
    // goes over locate highlight nodes.
    //if (highlightMode.getValue() == OFF) {
    //    inherited::handleEvent( action );
    //    return;
    //}

    
    //
    // If this is a mouseMotion event, then check for locate highlighting
    //
    if (event->isOfType(SoLocation2Event::getClassTypeId())) {
        // check to see if the mouse is over our geometry...
        SbBool underTheMouse = FALSE;
        const SoPickedPoint * pp = this->getPickedPoint(action);
        SoFullPath *pPath = (pp != NULL) ? (SoFullPath *) pp->getPath() : NULL;
        if (pPath && pPath->containsPath(action->getCurPath())) {
            // Make sure I'm the lowest LocHL in the pick path!
            underTheMouse = TRUE;
            for (int i = 0; i < pPath->getLength(); i++) {
                SoNode *node = pPath->getNodeFromTail(i);
                if (node->isOfType(SoFCSelection::getClassTypeId())) {
                    if (node != this)
                    underTheMouse = FALSE;
                    break; // found the lowest LocHL - look no further
                }
            }
        }
        // Am I currently highlighted?
        if (isHighlighted(action)) {
            if (! underTheMouse) {
                // re-draw the object with it's normal color
                //if(mymode != OFF)
                redrawHighlighted(action, FALSE);
                Gui::Selection().rmvPreselect();
            }
            else {
                action->setHandled();
                //const SoPickedPoint * pp = action->getPickedPoint();
                Gui::Selection().setPreselectCoord(pp->getPoint()[0]
                                                 ,pp->getPoint()[1]
                                                 ,pp->getPoint()[2]);
            }
        }
        // Else I am not currently highlighted
        else {
            // If under the mouse, then highlight!
            if (underTheMouse) {
                // draw this object highlighted
                if (mymode != OFF)
                    redrawHighlighted(action, TRUE);
                //const SoPickedPoint * pp = action->getPickedPoint();
                Gui::Selection().setPreselect(documentName.getValue().getString()
                                                 ,objectName.getValue().getString()
                                                 ,subElementName.getValue().getString()
                                                 ,pp->getPoint()[0]
                                                 ,pp->getPoint()[1]
                                                 ,pp->getPoint()[2]);
            }
        }
        //if(selected == SELECTED){
        //    redrawHighlighted(action, TRUE);
        //}
        //if(selectionCleared ){
        //    redrawHighlighted(action, FALSE);
        //    selectionCleared = false;
        //}
    }
    // key press events
    else if (event->isOfType(SoKeyboardEvent ::getClassTypeId())) {
        SoKeyboardEvent  * const e = (SoKeyboardEvent  *) event;
        if (SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::LEFT_SHIFT)     ||
            SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::RIGHT_SHIFT)     )
            bShift = true;
        if (SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::LEFT_SHIFT)   ||
            SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::RIGHT_SHIFT)   )
            bShift = false;
        if (SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::LEFT_CONTROL)   ||
            SoKeyboardEvent::isKeyPressEvent(e,SoKeyboardEvent::RIGHT_CONTROL)   )
            bCtrl = true;
        if (SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::LEFT_CONTROL) ||
            SoKeyboardEvent::isKeyReleaseEvent(e,SoKeyboardEvent::RIGHT_CONTROL) )
            bCtrl = false;
    }
    // mouse press events for (de)selection (only if selection is enabled on this node)
    else if (event->isOfType(SoMouseButtonEvent::getClassTypeId()) && 
             selectionMode.getValue() == SoFCSelection::SEL_ON) {
        SoMouseButtonEvent * const e = (SoMouseButtonEvent *) event;
        if (SoMouseButtonEvent::isButtonReleaseEvent(e,SoMouseButtonEvent::BUTTON1)) {
            //FIXME: Shouldn't we remove the preselection for newly selected objects?
            //       Otherwise the tree signals that an object is preselected even though it is hidden. (Werner)
            const SoPickedPoint * pp = this->getPickedPoint(action);
            if (pp && pp->getPath()->containsPath(action->getCurPath())) {
                if (bCtrl) {
                    if (Gui::Selection().isSelected(documentName.getValue().getString()
                                         ,objectName.getValue().getString()
                                         ,subElementName.getValue().getString())) {
                        Gui::Selection().rmvSelection(documentName.getValue().getString()
                                          ,objectName.getValue().getString()
                                          ,subElementName.getValue().getString());
                    }
                    else {
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                          ,objectName.getValue().getString()
                                          ,subElementName.getValue().getString()
                                          ,pp->getPoint()[0]
                                          ,pp->getPoint()[1]
                                          ,pp->getPoint()[2]);

                        if (mymode == OFF) {
                            snprintf(buf,512,"Selected: %s.%s.%s (%f,%f,%f)",documentName.getValue().getString()
                                                       ,objectName.getValue().getString()
                                                       ,subElementName.getValue().getString()
                                                       ,pp->getPoint()[0]
                                                       ,pp->getPoint()[1]
                                                       ,pp->getPoint()[2]);

                            getMainWindow()->statusBar()->showMessage(QString::fromAscii(buf),3000);
                        }
                    }
                }
                else { // Ctrl
                    if (!Gui::Selection().isSelected(documentName.getValue().getString()
                                         ,objectName.getValue().getString()
                                         ,subElementName.getValue().getString())) {
                        Gui::Selection().clearSelection(documentName.getValue().getString());
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                              ,objectName.getValue().getString()
                                              ,subElementName.getValue().getString()
                                              ,pp->getPoint()[0]
                                              ,pp->getPoint()[1]
                                              ,pp->getPoint()[2]);
                    }
                    else {
                        Gui::Selection().clearSelection(documentName.getValue().getString());
                        Gui::Selection().addSelection(documentName.getValue().getString()
                                              ,objectName.getValue().getString()
                                              ,0
                                              ,pp->getPoint()[0]
                                              ,pp->getPoint()[1]
                                              ,pp->getPoint()[2]);
                    }
 
                    if (mymode == OFF) {
                        snprintf(buf,512,"Selected: %s.%s.%s (%f,%f,%f)",documentName.getValue().getString()
                                                   ,objectName.getValue().getString()
                                                   ,subElementName.getValue().getString()
                                                   ,pp->getPoint()[0]
                                                   ,pp->getPoint()[1]
                                                   ,pp->getPoint()[2]);

                        getMainWindow()->statusBar()->showMessage(QString::fromAscii(buf),3000);
                    }
                }

                action->setHandled(); 
            } // picked point
        } // mouse release
    }

    // Let the base class traverse the children.
    if (action->getGrabber() != this)
        inherited::handleEvent(action);
#endif
}
Ejemplo n.º 5
0
void
SoLineHighlightRenderActionP::drawBoxes(SoPath * pathtothis,
                                        const SoPathList * pathlist)
{
  int i;
  int thispos = reclassify_cast<SoFullPath *>(pathtothis)->getLength()-1;
  assert(thispos >= 0);
  this->postprocpath->setHead(pathtothis->getHead()); // reset

  for (i = 1; i < thispos; i++) {
    this->postprocpath->append(pathtothis->getIndex(i));
  }

  SoState * state = PUBLIC(this)->getState();
  state->push();

  // we need to disable accumulation buffer antialiasing while
  // rendering selected objects
  int oldnumpasses = PUBLIC(this)->getNumPasses();
  PUBLIC(this)->setNumPasses(1);

  SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
  
  SoColorPacker ** cptr = static_cast<SoColorPacker **>(this->colorpacker_storage.get());

  SoLazyElement::setDiffuse(state, pathtothis->getHead(), 1, &this->color, *cptr);
  // FIXME: we should check this versus the actual max line width
  // supported by the underlying OpenGL context. 20050610 mortene.
  SoLineWidthElement::set(state, this->linewidth);
  SoLinePatternElement::set(state, this->linepattern);
  SoTextureQualityElement::set(state, 0.0f);
  SoDrawStyleElement::set(state, SoDrawStyleElement::LINES);
  SoPolygonOffsetElement::set(state, NULL, -1.0f, -1.0f, SoPolygonOffsetElement::LINES, TRUE);
  SoMaterialBindingElement::set(state, NULL, SoMaterialBindingElement::OVERALL); 
  SoNormalElement::set(state, NULL, 0, NULL, FALSE);
 
  SoOverrideElement::setNormalVectorOverride(state, NULL, TRUE);
  SoOverrideElement::setMaterialBindingOverride(state, NULL, TRUE);
  SoOverrideElement::setLightModelOverride(state, NULL, TRUE);
  SoOverrideElement::setDiffuseColorOverride(state, NULL, TRUE);
  SoOverrideElement::setLineWidthOverride(state, NULL, TRUE);
  SoOverrideElement::setLinePatternOverride(state, NULL, TRUE);
  SoOverrideElement::setDrawStyleOverride(state, NULL, TRUE);
  SoOverrideElement::setPolygonOffsetOverride(state, NULL, TRUE);
  SoTextureOverrideElement::setQualityOverride(state, TRUE);

  for (i = 0; i < pathlist->getLength(); i++) {
    SoFullPath * path = reclassify_cast<SoFullPath *>((*pathlist)[i]);

    this->postprocpath->append(path->getHead());
    for (int j = 1; j < path->getLength(); j++) {
      this->postprocpath->append(path->getIndex(j));
    }

    PUBLIC(this)->SoGLRenderAction::apply(this->postprocpath);
    this->postprocpath->truncate(thispos);
  }

  PUBLIC(this)->setNumPasses(oldnumpasses);
  state->pop();
}
Ejemplo n.º 6
0
Archivo: Scene.cpp Proyecto: Serge45/rl
		void
		Scene::load(const ::std::string& filename, const bool& doBoundingBoxPoints, const bool& doPoints)
		{
			::rl::xml::DomParser parser;
			
			::rl::xml::Document doc = parser.readFile(filename, "", XML_PARSE_NOENT | XML_PARSE_XINCLUDE);
			
			doc.substitute(XML_PARSE_NOENT | XML_PARSE_XINCLUDE);
			
			::rl::xml::Path path(doc);
			
			::rl::xml::Object scenes = path.eval("//scene");
			
			for (int i = 0; i < ::std::min(1, scenes.getNodeNr()); ++i)
			{
				SoInput input;
				
				if (!input.openFile(scenes.getNodeTab(i).getLocalPath(scenes.getNodeTab(i).getAttribute("href").getValue()).c_str() ,true))
				{
					throw Exception("::rl::sg::Scene::load() - failed to open file");
				}
				
				SoVRMLGroup* root = SoDB::readAllVRML(&input);
				
				if (NULL == root)
				{
					throw Exception("::rl::sg::Scene::load() - failed to read file");
				}
				
				SbViewportRegion viewportRegion;
				
				root->ref();
				
				// model
				
				::rl::xml::Object models = path.eval("model", scenes.getNodeTab(i));
				
				for (int j = 0; j < models.getNodeNr(); ++j)
				{
					SoSearchAction modelSearchAction;
					modelSearchAction.setName(models.getNodeTab(j).getAttribute("name").getValue().c_str());
					modelSearchAction.apply(root);
					
					if (NULL == modelSearchAction.getPath())
					{
						continue;
					}
					
					Model* model = this->create();
					
					model->setName(models.getNodeTab(j).getAttribute("name").getValue());
					
					// body
					
					::rl::xml::Object bodies = path.eval("body", models.getNodeTab(j));
					
					for (int k = 0; k < bodies.getNodeNr(); ++k)
					{
						SoSearchAction bodySearchAction;
						bodySearchAction.setName(bodies.getNodeTab(k).getAttribute("name").getValue().c_str());
						bodySearchAction.apply(static_cast< SoFullPath* >(modelSearchAction.getPath())->getTail());
						
						if (NULL == bodySearchAction.getPath())
						{
							continue;
						}
						
						Body* body = model->create();
						
						body->setName(bodies.getNodeTab(k).getAttribute("name").getValue());
						
						SoSearchAction pathSearchAction;
						pathSearchAction.setNode(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail());
						pathSearchAction.apply(root);
						
						SoGetMatrixAction bodyGetMatrixAction(viewportRegion);
						bodyGetMatrixAction.apply(static_cast< SoFullPath* >(pathSearchAction.getPath()));
						SbMatrix bodyMatrix = bodyGetMatrixAction.getMatrix();
						
						if (!this->isScalingSupported)
						{
							SbVec3f bodyTranslation;
							SbRotation bodyRotation;
							SbVec3f bodyScaleFactor;
							SbRotation bodyScaleOrientation;
							SbVec3f bodyCenter;
							bodyMatrix.getTransform(bodyTranslation, bodyRotation, bodyScaleFactor, bodyScaleOrientation, bodyCenter);
							
							for (int l = 0; l < 3; ++l)
							{
								if (::std::abs(bodyScaleFactor[l] - 1.0f) > 1.0e-6f)
								{
									throw Exception("::rl::sg::Scene::load() - bodyScaleFactor not supported");
								}
							}
						}
						
						::rl::math::Transform frame;
						
						for (int m = 0; m < 4; ++m)
						{
							for (int n = 0; n < 4; ++n)
							{
								frame(m, n) = bodyMatrix[n][m];
							}
						}
						
						body->setFrame(frame);
						
						if (static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail()->isOfType(SoVRMLTransform::getClassTypeId()))
						{
							SoVRMLTransform* bodyVrmlTransform = static_cast< SoVRMLTransform* >(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail());
							
							for (int l = 0; l < 3; ++l)
							{
								body->center(l) = bodyVrmlTransform->center.getValue()[l];
							}
						}
						
						SoPathList pathList;
						
						// shape
						
						SoSearchAction shapeSearchAction;
						shapeSearchAction.setInterest(SoSearchAction::ALL);
						shapeSearchAction.setType(SoVRMLShape::getClassTypeId());
						shapeSearchAction.apply(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail());
						
						for (int l = 0; l < shapeSearchAction.getPaths().getLength(); ++l)
						{
							SoFullPath* path = static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l]);
							
							if (path->getLength() > 1)
							{
								path = static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l]->copy(1, static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l])->getLength() - 1));
							}
							
							pathList.append(path);
							
							SoGetMatrixAction shapeGetMatrixAction(viewportRegion);
							shapeGetMatrixAction.apply(path);
							SbMatrix shapeMatrix = shapeGetMatrixAction.getMatrix();
							
							if (!this->isScalingSupported)
							{
								SbVec3f shapeTranslation;
								SbRotation shapeRotation;
								SbVec3f shapeScaleFactor;
								SbRotation shapeScaleOrientation;
								SbVec3f shapeCenter;
								shapeMatrix.getTransform(shapeTranslation, shapeRotation, shapeScaleFactor, shapeScaleOrientation, shapeCenter);
								
								for (int m = 0; m < 3; ++m)
								{
									if (::std::abs(shapeScaleFactor[m] - 1.0f) > 1.0e-6f)
									{
										throw Exception("::rl::sg::Scene::load() - shapeScaleFactor not supported");
									}
								}
							}
							
							SoVRMLShape* shapeVrmlShape = static_cast< SoVRMLShape* >(static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l])->getTail());
							
							Shape* shape = body->create(shapeVrmlShape);
							
							shape->setName(shapeVrmlShape->getName().getString());
							
							::rl::math::Transform transform;
							
							for (int m = 0; m < 4; ++m)
							{
								for (int n = 0; n < 4; ++n)
								{
									transform(m, n) = shapeMatrix[n][m];
								}
							}
							
							shape->setTransform(transform);
						}
						
						// bounding box
						
						if (doBoundingBoxPoints)
						{
							SoGetBoundingBoxAction getBoundingBoxAction(viewportRegion);
							getBoundingBoxAction.apply(pathList);
							SbBox3f boundingBox = getBoundingBoxAction.getBoundingBox();
							
							for (int l = 0; l < 3; ++l)
							{
								body->max(l) = boundingBox.getMax()[l];
								body->min(l) = boundingBox.getMin()[l];
							}
						}
						
						// convex hull
						
						if (doPoints)
						{
							SoCallbackAction callbackAction;
							callbackAction.addTriangleCallback(SoVRMLGeometry::getClassTypeId(), Scene::triangleCallback, &body->points);
							callbackAction.apply(pathList);
						}
					}
				}
				
				root->unref();
			}
		}
Ejemplo n.º 7
0
//////////////////////////////////////////////////////////////////////////////
//
//  beginTraversal - have the base class render the passed scene graph,
//  then render highlights for our selection node.
//
void
SoBoxHighlightRenderAction::apply(SoNode *renderRoot)
//
//////////////////////////////////////////////////////////////////////////////
{
    // Render the scene
    SoGLRenderAction::apply(renderRoot);
    
    // Render the highlight?
    if (! hlVisible) return;
    
    // Is our cached path still valid?
    if ((selPath == NULL) ||
	(selPath->getHead() != renderRoot) ||
	(! selPath->getTail()->isOfType(SoSelection::getClassTypeId()))) {

	// Find the selection node under the render root
	static SoSearchAction *sa1 = NULL;
	if (sa1 == NULL)
	    sa1 = new SoSearchAction;
	else
	    sa1->reset();
	sa1->setFind(SoSearchAction::TYPE);
	sa1->setInterest(SoSearchAction::FIRST);
	sa1->setType(SoSelection::getClassTypeId());
	sa1->apply(renderRoot);
	
	// Cache this path
	if (selPath != NULL)
	    selPath->unref();
	selPath = sa1->getPath();
	if (selPath != NULL) {
	    selPath = selPath->copy();
	    selPath->ref();
	}
    }
    
    if (selPath != NULL) {
	// Make sure something is selected
	SoSelection *sel = (SoSelection *) selPath->getTail();
	if (sel->getNumSelected() == 0) return;
	
	// Keep the length from the root to the selection
	// as an optimization so we can reuse this data
	int reusablePathLength = selPath->getLength();

	// For each selection path, create a new path rooted under our
	// localRoot
	for (int j = 0; j < sel->getNumSelected(); j++) {
	    // Continue the path down to the selected object.
	    // No need to deal with p[0] since that is the sel node.
	    SoFullPath *p = (SoFullPath *) sel->getPath(j);	    
	    SoNode *pathTail = p->getTail();

	    if ( pathTail->isOfType(SoBaseKit::getClassTypeId())) {
		// Find the last nodekit on the path.
		SoNode *kitTail = ((SoNodeKitPath *)p)->getTail();

		// Extend the selectionPath until it reaches this last kit.
		SoFullPath *fp = (SoFullPath *) p;
		int k = 0;
		do {
		    selPath->append(fp->getIndex(++k));
		} 
		while ( fp->getNode(k) != kitTail );
	    }
	    else {
		for (int k = 1; k < p->getLength(); k++)
		    selPath->append(p->getIndex(k));
	    }
    
	    // Find the camera used to render the selected object and
	    // insert it into the highlight graph as the first child
	    SoNode *camera;

	    static SoSearchAction *sa2 = NULL;
	    if (sa2 == NULL)
		sa2 = new SoSearchAction;
	    else
		sa2->reset();

	    sa2->setFind(SoSearchAction::TYPE);
	    sa2->setInterest(SoSearchAction::LAST);
	    sa2->setType(SoCamera::getClassTypeId());
	    sa2->apply(selPath);
	    camera =(sa2->getPath() == NULL ? NULL : sa2->getPath()->getTail());
	    if (camera != NULL)
		localRoot->insertChild(camera, 0);
	    
	    // Get the bounding box of the object and update the
	    // local highlight graph
	    updateBbox(selPath);
	    
	    // Make sure the box has some size
	    if ((cube->width.getValue() == 0) &&
		(cube->height.getValue() == 0) &&
		(cube->depth.getValue() == 0)) {
#ifdef DEBUG
		SoDebugError::postWarning("SoBoxHighlightRenderAction::apply",
			"selected object has no bounding box - no highlight rendered");
#endif		    
	    }
	    else {
		// Render the highlight
		SoGLRenderAction::apply(localRoot);
	    }
	    	    
	    // Restore selPath for reuse
	    selPath->truncate(reusablePathLength);

	    // Remove the camera for the next path
	    if (camera != NULL)
		localRoot->removeChild(0);
	}
    }
}