Ejemplo n.º 1
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.º 2
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.º 3
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.º 4
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);
	}
    }
}