SoXipDrawClipPlane::SoXipDrawClipPlane() {
	SO_NODE_CONSTRUCTOR(SoXipDrawClipPlane);

	SO_NODE_ADD_FIELD(plane, (SbPlane(SbVec3f(0, 0, 1), 0)));
  	SO_NODE_ADD_FIELD(on, (TRUE));
	SO_NODE_ADD_FIELD(boundingBox, (SbMatrix::identity()));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
//    Set up the highlighting, projector, and the initial hit on
//    the dragger
//
// Use: private
//
void
SoTranslate2Dragger::dragStart()
//
////////////////////////////////////////////////////////////////////////
{
    // Set the switches to 1...
    setSwitchValue( translatorSwitch.getValue(), 1 );
    setSwitchValue( feedbackSwitch.getValue(), 1 );

    // Set the axis feedback switch to display both.
    // They're displayed while dragging
    setSwitchValue( axisFeedbackSwitch.getValue(), SO_SWITCH_ALL );

    // There is no constrained direction...
    translateDir = -1;

    // Make a note of which modifier keys are down.
    shftDown = getEvent()->wasShiftDown();

    // This is the point we'll use if a metaKey callback makes us re-start.
	worldRestartPt = getWorldStartingPoint();

    // Establish the projector plane in working space.
    // Working space is space at end of motion matrix.
    // Plane normal is defined relative to the translatorPart, so 
    // use z-axis to construct the projector plane.
	SbVec3f startLocalHitPt = getLocalStartingPoint();
	planeProj->setPlane( SbPlane(SbVec3f(0,0,1), startLocalHitPt ) );
}
Exemple #3
0
// doc in parent
SbBool
SoVRMLPlaneSensor::dragStart(void)
{
  SbVec3f thehitpt = this->getLocalStartingPoint();
  this->planeproj->setPlane(SbPlane(SbVec3f(0.0f, 0.0f, 1.0f), thehitpt));
  this->translation_changed = this->offset.getValue();

  return TRUE;
}
Exemple #4
0
// Read SbPlane from input stream, return TRUE if successful.  Used
// from SoSFPlane and SoMFPlane.
SbBool
sosfplane_read_value(SoInput * in, SbPlane & p)
{
  float f[4];
  for (int i = 0; i < 4; i++) {
    if (!in->read(f[i])) return FALSE;
  }
  p = SbPlane(SbVec3f(f[0], f[1], f[2]), f[3]);
  return TRUE;
}
Exemple #5
0
void
InvComposePlane::evaluate()
{
    // Compute the product of the input fields
    SbPlane p = SbPlane(normal.getValue(), point.getValue());

    // "Send" the value to the output. In effect, we are setting
    // the value in all fields to which this output is connected.
    SO_ENGINE_OUTPUT(plane, SoSFPlane, setValue(p));
}
SoXipWidgetCamera::SoXipWidgetCamera()
{
	SO_NODE_CONSTRUCTOR( SoXipWidgetCamera );

	SO_XIP_KIT_ADD_TYPE_ENTRY( mCamera, SoOrthographicCamera, this );
	SO_XIP_KIT_ADD_TYPE_ENTRY(  mScale,              SoScale, this );

	mPlaneProj = new SbPlaneProjector( FALSE );
	mPlaneProj->setPlane( SbPlane( SbVec3f(0, 0, 1), 0 ) );
}
Exemple #7
0
/*! \COININTERNAL
  Called when dragger is selected (picked) by the user.
*/
void
SoScale2Dragger::dragStart(void)
{
  SoSwitch *sw;
  sw = SO_GET_ANY_PART(this, "scalerSwitch", SoSwitch);
  SoInteractionKit::setSwitchValue(sw, 1);
  sw = SO_GET_ANY_PART(this, "feedbackSwitch", SoSwitch);
  SoInteractionKit::setSwitchValue(sw, 1);

  SbVec3f hitPt = this->getLocalStartingPoint();
  this->planeProj->setPlane(SbPlane(SbVec3f(0.0f, 0.0f, 1.0f), hitPt));
}
////////////////////////////////////////////////////////////////////////
//
// Description:
//  Sets up the tolerance plane.
//
// Use: protected
void
SbSphereSectionProjector::setupTolerance()
//
////////////////////////////////////////////////////////////////////////
{
    // Find the intersection point on the tolerance plane.
    // The plane may either be in working space, or always
    // oriented towards the eye.

    // find orientation of the tolerance plane, in working space
    if (orientToEye) {
	if (viewVol.getProjectionType() == SbViewVolume::PERSPECTIVE) {
	    // find the projection point in working space coords
	    SbVec3f workingProjPoint;
	    worldToWorking.multVecMatrix(
		viewVol.getProjectionPoint(), workingProjPoint);

	    planeDir = workingProjPoint - sphere.getCenter();
	}
	else {
	    // Use the projection direction in an orthographic
	    // view vol
	    worldToWorking.multDirMatrix(viewVol.zVector(), planeDir);
	}	 
	planeDir.normalize();
    }
    else {
	planeDir.setValue(0,0,1);
    }

    // distance from planePoint to edge of tolerance ring
    tolDist = sphere.getRadius() * tolerance;

    // find disntance from the center of the sphere to the tolerance
    // plane
    planeDist =
	sqrtf((sphere.getRadius()*sphere.getRadius()) -
	      (tolDist * tolDist));

    // If we are intersecting with the back half of the sphere, then
    // face the plane the other way.
    if ( intersectFront == FALSE )
	planeDir *= -1.0;

    // plane given direction and point to pass through
    planePoint = sphere.getCenter() + planeDist*planeDir;

    tolPlane = SbPlane(planeDir, planePoint);

    needSetup = FALSE;
}
bool ObjectSimpleViewer::
parseClipPlane(
  const QDomElement &element)
{
  float distance=0;
  SbVec3f pos;
  SbVec3f normal;
  SbVec3f scale(1.0f, 1.0f, 1.0f);

  QDomNode child = element.firstChild();
  while(!child.isNull())
  {
    const QDomElement &element = child.toElement();
    if(element.tagName() == "Distance")
    {
      distance = element.text().toFloat();
    }
    else if(element.tagName() == "Position")
    {
      pos = parseSbVec3f(element);
    }
    else if(element.tagName() == "Normal")
    {
      normal = parseSbVec3f(element);
    }
    else if(element.tagName() == "Scalefactor")
    {
      scale = parseSbVec3f(element);
    }
    child = child.nextSibling();
  }
  if(!m_clipPlaneManip)
  {
    //create at first use
    m_clipPlaneManip = new SoClipPlaneManip;
    m_clipPlaneManip->ref();
    m_clipPlaneManip->plane.setValue(SbPlane(normal, distance));
    m_clipPlaneManip->draggerPosition = pos;
    SoDragger *dragger = m_clipPlaneManip->getDragger();
    if(dragger && dragger->isOfType(SoJackDragger::getClassTypeId()))
    {
      SoJackDragger *jd = (SoJackDragger*)dragger;
      jd->scaleFactor.setValue(scale);
    }
  }
  return(true);
}
////////////////////////////////////////////////////////////////////////
//
// Description:
//    Rotate the rotateDiscDragger based on mouse motion.
//
// Use: private
//
void
SoRotateDiscDragger::dragStart()
//
////////////////////////////////////////////////////////////////////////
{
    // Set the switches to 1...
    setSwitchValue( rotatorSwitch.getValue(), 1 );
    setSwitchValue( feedbackSwitch.getValue(), 1 );

    // Establish the projector plane in working space.
    // Working space is space at end of motion matrix.
    // The plane used should be the x-y plane.
	SbVec3f startLocalHitPt = getLocalStartingPoint();
	SbLine  workSpaceAxis( SbVec3f(0,0,0), SbVec3f(0,0,1) );
	SbVec3f planeOrigin = workSpaceAxis.getClosestPoint(startLocalHitPt);
	planeProj->setPlane(SbPlane(SbVec3f(0,0,1), planeOrigin));
}
void ObjectSimpleViewer::
stateChanged(
  ClipPlaneButton::statetype state)
{
  switch(state)
  {
    case ClipPlaneButton::ClipOn:
      {
	if(!m_clipPlaneManip)
	{
	  //create at first use
	  m_clipPlaneManip = new SoClipPlaneManip;
	  m_clipPlaneManip->ref();
	  SoGetBoundingBoxAction ba(m_viewer->getViewportRegion());
	  ba.apply(blinker_root);
	  SbBox3f box = ba.getBoundingBox();
	  m_clipPlaneManip->setValue(box, SbVec3f(1.0f, 0.0f, 0.0f), 1.00f);
	}
	SbPlane plane = m_clipPlaneManip->plane.getValue();
	m_clipPlaneManip->plane.setValue(SbPlane(-plane.getNormal(),
	    -plane.getDistanceFromOrigin()));
	emit addedClipPlane(m_clipPlaneManip);  //remove ortho slices
      }
      break;
    case ClipPlaneButton::ClipOff:
      emit addedClipPlane(NULL);  //remove ortho slices
      break;
    case ClipPlaneButton::ClipOnly:
      if(!m_clipPlane)
      {
        //create at first use
	if(!m_clipPlaneManip)
	{
	  //create at first use
	  m_clipPlaneManip = new SoClipPlaneManip;
	  m_clipPlaneManip->ref();
	}
	m_clipPlane = new SoClipPlane;
	m_clipPlane->ref();
	m_clipPlane->plane.connectFrom(&(m_clipPlaneManip->plane));
      }
      emit addedClipPlane(m_clipPlane);  //remove ortho slices
      break;
  }
}
Exemple #12
0
void getScreenPixelVectors(SoGLRenderAction *action, const SbVec3f position, SbVec3f &xPixelVec, SbVec3f &yPixelVec) 
{
	// To compute correct offset in world space we project width of text onto a plane parallel
	// to the near plane of the camera that goes through the current translation of the model matrix.
	SoState *state = action->getState();
	SbPlaneProjector planeProj(FALSE);
	SbViewVolume viewVolume = SoViewVolumeElement::get(state);
	SbViewportRegion viewport = SoViewportRegionElement::get(state);

	planeProj.setViewVolume(viewVolume);
	planeProj.setPlane(SbPlane(viewVolume.getPlane(0.f).getNormal(), position));

	float pixelWidth = 1.f / (float) viewport.getViewportSizePixels()[0];
	float pixelHeight = 1.f / (float) viewport.getViewportSizePixels()[1];

	SbVec3f p1 = planeProj.project(SbVec2f(0, 0));
	SbVec3f p2 = planeProj.project(SbVec2f(pixelWidth, 0));
	xPixelVec = (p2 - p1);

	p2 = planeProj.project(SbVec2f(0, pixelHeight));
	yPixelVec = (p2 - p1);
}
SoXipComposeVec6::SoXipComposeVec6()
{
	SO_ENGINE_CONSTRUCTOR( SoXipComposeVec6 );

	SO_ENGINE_ADD_INPUT(      plane,  (SbPlane(SbVec3f(1.0, 0.0, 0.0), 0.0)));
    
	SO_ENGINE_ADD_INPUT(      image,  (0) );

	SO_ENGINE_ADD_INPUT( sliceIndex, (-1) );
	SO_ENGINE_ADD_INPUT( xmin, (-1) );
	SO_ENGINE_ADD_INPUT( xmax, (-1) );
	SO_ENGINE_ADD_INPUT( ymin, (-1) );
	SO_ENGINE_ADD_INPUT( ymax, (-1) );
	SO_ENGINE_ADD_INPUT( zmin, (-1) );
	SO_ENGINE_ADD_INPUT( zmax, (-1) );

	SO_ENGINE_ADD_OUTPUT( output, SoXipSFDataImage );
	SO_ENGINE_ADD_OUTPUT( numSlices, SoSFShort );
	SO_ENGINE_ADD_OUTPUT( outSliceIndex, SoSFShort );
	SO_ENGINE_ADD_OUTPUT( outVOI, SoMFInt32 );

	mImageData = 0;
}
Exemple #14
0
// Find the plane definition.
SbPlane
SoOrthoSliceP::getSliceAsPlane(SoAction * action) const
{
  const CvrVoxelBlockElement * vbelem =
    CvrVoxelBlockElement::getInstance(action->getState());

  const int axis = PUBLIC(this)->axis.getValue();

  // Finding the plane normal is straight forward -- it's the same as
  // the SoOrthoSlice axis:

  SbVec3f planenormal(axis == SoOrthoSlice::X ? 1.0f : 0.0f,
                      axis == SoOrthoSlice::Y ? 1.0f : 0.0f,
                      axis == SoOrthoSlice::Z ? 1.0f : 0.0f);

  if (PUBLIC(this)->clippingSide.getValue() == SoOrthoSlice::FRONT) {
    planenormal.negate();
  }

  // Finding a point in the plane:

  const SbBox3f & spacesize = vbelem->getUnitDimensionsBox();
  SbVec3f spacemin, spacemax;
  spacesize.getBounds(spacemin, spacemax);

  SbVec3f origo = spacesize.getCenter();

  const SbVec3s & dimensions = vbelem->getVoxelCubeDimensions();
  const float depthprslice = (spacemax[axis] - spacemin[axis]) / dimensions[axis];
  const float depth = spacemin[axis] + PUBLIC(this)->sliceNumber.getValue() * depthprslice;
  origo[axis] = depth;

  // Return local unit coordinate system plane:

  return SbPlane(planenormal, origo);
}
SoXipMenuBase::SoXipMenuBase()
{
	SO_NODE_CONSTRUCTOR( SoXipMenuBase );

	SO_XIP_KIT_ADD_TYPE_ENTRY(    mMenuSwitch,      SoSwitch, this );
	SO_XIP_KIT_ADD_TYPE_ENTRY( mMenuSeparator,   SoSeparator, mMenuSwitch );
	SO_XIP_KIT_ADD_TYPE_ENTRY(    mMenuOffset, SoTranslation, mMenuSeparator );
    
	SO_NODE_ADD_FIELD(           on, (FALSE) );
	SO_NODE_ADD_FIELD(     position, (0, 0) );
	SO_NODE_ADD_FIELD(  itemFocused, (-1) );
	SO_NODE_ADD_FIELD(  itemClicked, (-1) );

	mActionNode			= 0;
	mIsSubMenu			= FALSE;

	mFieldSensors[0]	= new SoFieldSensor( fieldSensorCB, this );
	mFieldSensors[0]->attach( &on );
	mFieldSensors[1]	= new SoFieldSensor( fieldSensorCB, this );
	mFieldSensors[1]->attach( &position );

	mPlaneProj			= new SbPlaneProjector;
	mPlaneProj->setPlane( SbPlane( SbVec3f(0, 0, 1), 0 ) );
}
void
SoDragPointDragger::metaKeyChangeCB( void *, SoDragger *inDragger )
//
////////////////////////////////////////////////////////////////////////
{
    SoDragPointDragger *dp = (SoDragPointDragger *) inDragger;

    SoHandleEventAction *ha = dp->getHandleEventAction();

    // We care if the shift key is down for drawing feedback.
	const SoEvent *event = dp->getEvent();
        dp->shftDown = event->wasShiftDown();

    // Don't check for grabber yet.
    // CONTROL key press overrides if the grabber is a childDragger.

    // [1] We only respond to CONTROL key press events.
	if ( !SO_KEY_PRESS_EVENT(event,  LEFT_CONTROL) &&
	     !SO_KEY_PRESS_EVENT(event, RIGHT_CONTROL))
	     return;

    //[2] Should we return?
    //    Stay here if there's no grabber and the mouse is over us,
    //         or over a surrogate part.
    //    Stay here if we are the grabber.
    //    Stay here if our currentDragger is grabbing events.
    //    Return if anyone else is grabbing.
	SbBool takeIt = FALSE;
	if ( ha->getGrabber() == NULL  ) {

	    // grabber is NULL...
	    const SoPickedPoint *p = ha->getPickedPoint();

	    if ( p && p->getPath()) {

		// Are we on the pickPath?
		// Or is the path a surrogate path for us or any draggers 
		// contained within us?
	        if (  p->getPath()->containsNode(dp) ||
		     dp->isPathSurrogateInMySubgraph(p->getPath()) )
		        takeIt = TRUE;
	    }
	}
	else if ( ha->getGrabber() == dp )
	    takeIt = TRUE;
	else if ( ha->getGrabber() == dp->currentDragger )
	    takeIt = TRUE;
	else 
	    takeIt = FALSE;

	if ( !takeIt )
	    return;

    //[3] Now, switch the set of visible draggers...
	dp->showNextDraggerSet();

    //[4] If a child is grabbing, release events and hand it all over to 
    //    the next one...
	SoDragger *oldDragger = dp->currentDragger;
	if (oldDragger) {

	    // Ref the oldDragger.
		oldDragger->ref();

	    // Release the grabber. This will call grabEventsCleanUp() if 
	    // the grabber is a dragger.
		ha->releaseGrabber();

	    // If there was an oldDragger, 
	    // [a] select a new dragger to grab events.
	    // [b] Set up a plane or line projector oriented like newDragger.
	    // [c] Find out where current mouse position intersects that new 
	    //     plane or line. The new gesture will continue from there.
		SoDragger *newDragger;
		SbVec3f    projPt;
		SbLineProjector  lp;
		SbPlaneProjector pp;
		lp.setViewVolume( dp->getViewVolume() );
		pp.setViewVolume( dp->getViewVolume() );
		lp.setWorkingSpace( dp->getLocalToWorldMatrix() );
		pp.setWorkingSpace( dp->getLocalToWorldMatrix() );

		if (      oldDragger == dp->xTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->yTranslator.getValue();
		    lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(0,1,0)));
		    projPt = lp.project(dp->getNormalizedLocaterPosition());
		}
		else if ( oldDragger == dp->yTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->zTranslator.getValue();
		    lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(0,0,1)));
		    projPt = lp.project(dp->getNormalizedLocaterPosition());
		}
		else if ( oldDragger == dp->zTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->xTranslator.getValue();
		    lp.setLine( SbLine( SbVec3f(0,0,0), SbVec3f(1,0,0)));
		    projPt = lp.project(dp->getNormalizedLocaterPosition());
		}
		else if ( oldDragger == dp->yzTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->xzTranslator.getValue();
		    pp.setPlane( SbPlane( SbVec3f(0,1,0), SbVec3f(0,0,0)));
		    projPt = pp.project(dp->getNormalizedLocaterPosition());
		}
		else if ( oldDragger == dp->xzTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->xyTranslator.getValue();
		    pp.setPlane( SbPlane( SbVec3f(0,0,1), SbVec3f(0,0,0)));
		    projPt = pp.project(dp->getNormalizedLocaterPosition());
		}
		else if ( oldDragger == dp->xyTranslator.getValue() ) {
		    newDragger = (SoDragger *) dp->yzTranslator.getValue();
		    pp.setPlane( SbPlane( SbVec3f(1,0,0), SbVec3f(0,0,0)));
		    projPt = pp.project(dp->getNormalizedLocaterPosition());
		}

	    // unref oldDragger. We don't need it any more.
		oldDragger->unref();

	    // Give newDragger our handleEvent action. 
		newDragger->setHandleEventAction(ha);

	    // Cast the projPt into world space for the new starting point.
		dp->getLocalToWorldMatrix().multVecMatrix(projPt,projPt);
		newDragger->setStartingPoint( projPt );

	    // Give the newDragger a path to itself
		SoPath *pathToDragger;

		    // We must ref() & unref() dpThisPath to dispose of it.
		    SoPath *dpThisPath = dp->createPathToThis();
		    if (dpThisPath) dpThisPath->ref();
		    pathToDragger = dp->createPathToPart(
			dp->getPartString(newDragger), TRUE, dpThisPath );
		    if (dpThisPath) dpThisPath->unref();

		if (pathToDragger)
		    pathToDragger->ref();
		newDragger->setTempPathToThis( pathToDragger );
		if (pathToDragger)
		    pathToDragger->unref();

	    // Give the newDragger our viewing information.
		newDragger->setViewVolume(dp->getViewVolume());
		newDragger->setViewportRegion(dp->getViewportRegion());

	    // Set the grabber. This will call starting callbacks on the new
	    // grabber, as well as it's registered parent, moi!
		ha->setGrabber( newDragger );
	}

    //[5] set handled
	ha->setHandled();
}
Exemple #17
0
/*! \COININTERNAL
  Called when dragger is selected (picked) by the user.
*/
void
SoHandleBoxDragger::dragStart(void)
{
  SoHandleBoxDragger_invalidate_surroundscale(this);

  static const char translatorname[] = "translator";
  static const char extrudername[] = "extruder";
  static const char uniformname[] = "uniform";

  const SoPath *pickpath = this->getPickPath();

  SbBool found = FALSE;
  this->whatkind = WHATKIND_NONE;
  this->whatnum = 0;

  int i;
  SbString str;
  if (!found) {
    for (i = 1; i <= 6; i++) {
      str.sprintf("%s%d", translatorname, i);
      if (pickpath->findNode(this->getNodeFieldNode(str.getString())) >= 0||
          this->getSurrogatePartPickedName() == str.getString()) break;
    }
    if (i <= 6) {
      found = TRUE;
      this->whatkind = WHATKIND_TRANSLATOR;
      this->whatnum = i;
    }
  }

  if (!found) {
    for (i = 1; i <= 6; i++) {
      str.sprintf("%s%d", extrudername, i);
      if (pickpath->findNode(this->getNodeFieldNode(str.getString()))>= 0 ||
          this->getSurrogatePartPickedName() == str.getString()) break;
    }
    if (i <= 6) {
      found = TRUE;
      this->whatkind = WHATKIND_EXTRUDER;
      this->whatnum = i;
    }
  }
  if (!found) {
    for (i = 1; i <= 8; i++) {
      str.sprintf("%s%d", uniformname, i);
      if (pickpath->findNode(this->getNodeFieldNode(str.getString()))>= 0 ||
          this->getSurrogatePartPickedName() == str.getString()) break;
    }
    if (i <= 8) {
      found = TRUE;
      this->whatkind = WHATKIND_UNIFORM;
      this->whatnum = i;
    }
  }
  assert(found);
  if (!found) return;

  SbVec3f startPt = this->getLocalStartingPoint();

  switch(this->whatkind) {
  case WHATKIND_TRANSLATOR:
    {
      SbVec3f n;
      if (this->whatnum <= 2) {
        n = SbVec3f(0.0f, 1.0f, 0.0f);
      }
      else if (this->whatnum <= 4) {
        n = SbVec3f(1.0f, 0.0f, 0.0f);
      }
      else {
        n = SbVec3f(0.0f, 0.0f, 1.0f);
      }
      SbVec3f localPt;
      {
        SbMatrix mat, inv;
        this->getSurroundScaleMatrices(mat, inv);
        inv.multVecMatrix(startPt, localPt);
      }
      this->planeProj->setPlane(SbPlane(n, startPt));
      SbLine myline(SbVec3f(0.0f, 0.0f, 0.0f), n);
      SoTranslation *t = SO_GET_ANY_PART(this, "arrowTranslation", SoTranslation);
      t->translation = myline.getClosestPoint(localPt);
      if (this->getEvent()->wasShiftDown()) {
        this->getLocalToWorldMatrix().multVecMatrix(startPt, this->worldRestartPt);
        this->constraintState = CONSTRAINT_WAIT;
      }
    }
    break;
  case WHATKIND_EXTRUDER:
    this->lineProj->setLine(SbLine(this->getDraggerCenter(), startPt));
    this->ctrlOffset = this->calcCtrlOffset(startPt);
    break;
  case WHATKIND_UNIFORM:
    this->lineProj->setLine(SbLine(this->getDraggerCenter(), startPt));
    this->ctrlOffset = this->calcCtrlOffset(startPt);
    break;
  }
  this->ctrlDown = this->getEvent()->wasCtrlDown();
  this->updateSwitches();
}
void
CvrIndexedSetRenderBaseP::GLRender(SoGLRenderAction * action,
                                   const float offset,
                                   const SbBool clipGeometry)
{


  // FIXME: Support for 'offset' must be implemented. (20040628
  // handegar)
  if (offset != 0) {
    static SbBool flag = FALSE;
    if (!flag) {
      SoDebugError::postWarning("CvrIndexedSetRenderBaseP::GLRender",
                                "Support for offset > 0 not implemented yet.");
      flag = TRUE;
    }
  }

  const cc_glglue * glue = cc_glglue_instance(action->getCacheContext());
  if (!cc_glglue_has_3d_textures(glue)) {
    static SbBool flag = FALSE;
    if (!flag) {
      SoDebugError::postWarning("CvrIndexedSetRenderBaseP::GLRender",
                                "Your OpenGL driver does not support 3D "
                                "textures, which is needed for rendering "
                                "SoVolumeIndexedFaceSet and "
                                "SoVolumeIndexedTriangleStripSet "
                                "nodes");
      flag = TRUE;
    }
    return;
  }

  SoState * state = action->getState();

  const CvrVoxelBlockElement * vbelem = CvrVoxelBlockElement::getInstance(state);
  if (vbelem == NULL) { return; }

  // This must be done, as we want to control stuff in the GL state
  // machine. Without it, state changes could trigger outside our
  // control.
  state->push();

  SbMatrix volumetransform;
  CvrUtil::getTransformFromVolumeBoxDimensions(vbelem, volumetransform);
  SoModelMatrixElement::mult(state, this->master, volumetransform);

  const SbVec3s & dims = vbelem->getVoxelCubeDimensions();
  SbVec3f origo(-((float) dims[0]) / 2.0f, -((float) dims[1]) / 2.0f, -((float) dims[2]) / 2.0f);

  // This must be done, as we want to control stuff in the GL state
  // machine. Without it, state changes could trigger outside our
  // control.
  SoGLLazyElement::getInstance(state)->send(state, SoLazyElement::ALL_MASK);

  glPushAttrib(GL_ALL_ATTRIB_BITS);
  glEnable(GL_TEXTURE_3D);
  glEnable(GL_DEPTH_TEST);

  // FIXME: Should there be support for other blending methods aswell? (20040630 handegar)
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  if (!this->cube) { this->cube = new Cvr3DTexCube(action); }

  const SoTransferFunctionElement * tfelement = SoTransferFunctionElement::getInstance(state);
  const CvrCLUT * c = CvrVoxelChunk::getCLUT(tfelement, CvrCLUT::ALPHA_AS_IS);
  if (this->clut != c) {
    this->cube->setPalette(c);
    this->clut = c;
  }

  // Fetch texture quality
  float texturequality = SoTextureQualityElement::get(state);
  GLenum interp;
  if (texturequality >= 0.1f) { interp = GL_LINEAR; }
  else { interp = GL_NEAREST; }
  CvrGLInterpolationElement::set(state, interp);

  // Fetch vertices and normals from the stack
  const SoCoordinateElement * coords;
  const SbVec3f * normals;
  const int32_t * cindices;
  int numindices;
  const int32_t * nindices;
  const int32_t * tindices;
  const int32_t * mindices;
  SbBool doTextures;
  SbBool normalCacheUsed;

  doTextures = FALSE; // No need for texture coordinates
  SbBool sendNormals = FALSE; // No need for normals

  this->getVertexData(state, coords, normals, cindices,
                      nindices, tindices, mindices, numindices,
                      sendNormals, normalCacheUsed);

  const SbVec3f * vertexarray;
  SoVertexProperty * vertprop = (SoVertexProperty *) this->master->vertexProperty.getValue();
  if (vertprop != NULL) {
    vertexarray = vertprop->vertex.getValues(0);
  }
  else vertexarray = coords->getArrayPtr3();

  if (normals == NULL) glDisable(GL_LIGHTING);

  const Cvr3DTexCube::IndexedSetType type = ((this->type == FACESET) ?
                                             Cvr3DTexCube::INDEXEDFACE_SET :
                                             Cvr3DTexCube::INDEXEDTRIANGLESTRIP_SET);

  this->cube->renderIndexedSet(action, vertexarray, cindices, numindices, type);

  glPopAttrib();


  // 'un-Transform' model matrix before rendering clip geometry.
  state->pop();


  // Render the geometry which are outside the volume cube as polygons.
  if (clipGeometry) {

    // Is there a clipplane left for us to use?
    GLint maxclipplanes = 0;
    glGetIntegerv(GL_MAX_CLIP_PLANES, &maxclipplanes);
    const SoClipPlaneElement * elem = SoClipPlaneElement::getInstance(state);
    if (elem->getNum() > (maxclipplanes-1)) {
      static SbBool flag = FALSE;
      if (!flag) {
        flag = TRUE;
        SoDebugError::postWarning("CvrIndexedSetRenderBaseP::GLRender",
                                  "\"clipGeometry TRUE\": Not enough clip planes available. (max=%d)",
                                  maxclipplanes);
      }
      return;
    }

    if (this->parentnodeid != this->master->getNodeId()) { // Changed recently?
      SoVertexProperty * vertprop = (SoVertexProperty *) this->master->vertexProperty.getValue();
      if (vertprop != NULL) this->clipgeometryshape->vertexProperty.setValue(vertprop);

      this->clipgeometryshape->coordIndex.setNum(this->master->coordIndex.getNum());
      this->clipgeometryshape->materialIndex.setNum(this->master->materialIndex.getNum());

      int32_t * idst = this->clipgeometryshape->coordIndex.startEditing();
      int32_t * mdst = this->clipgeometryshape->materialIndex.startEditing();

      int i=0;
      for (i=0;i<this->master->coordIndex.getNum();++i)
        *idst++ = this->master->coordIndex[i];
      for (i=0;i<this->master->materialIndex.getNum();++i)
        *mdst++ = this->master->materialIndex[i];
      // No need to copy texture coords as the face set shall always be untextured.

      this->parentnodeid = this->master->getNodeId();
      this->clipgeometryshape->coordIndex.finishEditing();
      this->clipgeometryshape->materialIndex.finishEditing();
    }

    SbPlane cubeplanes[6];
    SbVec3f a, b, c;

    // FIXME: Its really not necessary to calculate the clip planes
    // for each frame unless the volume has changed. This should be
    // optimized somehow.(20040629 handegar)
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, dims[1], 0.0f)), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, dims[1], dims[2])), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], dims[1], 0.0f)), c);
    cubeplanes[0] = SbPlane(a, b, c); // Top

    volumetransform.multVecMatrix(SbVec3f(origo), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], 0.0f, 0.0f)), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, 0.0f, dims[2])), c);
    cubeplanes[1] = SbPlane(a, b, c); // Bottom
   
    volumetransform.multVecMatrix(SbVec3f(origo), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, dims[1], 0.0f)), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], 0.0f, 0.0f)), c);
    cubeplanes[2] = SbPlane(a, b, c); // Back

    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, 0.0f, dims[2])), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], 0.0f, dims[2])), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, dims[1], dims[2])), c);
    cubeplanes[3] = SbPlane(a, b, c); // Front

    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], 0.0f, 0.0f)), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], dims[1], 0.0f)), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(dims[0], 0.0f, dims[2])), c);
    cubeplanes[4] = SbPlane(a, b, c); // Right

    volumetransform.multVecMatrix(SbVec3f(origo), a);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, 0.0f, dims[2])), b);
    volumetransform.multVecMatrix(SbVec3f(origo + SbVec3f(0.0f, dims[1], 0.0f)), c);
    cubeplanes[5] = SbPlane(a, b, c); // Left
    
    for (int i=0;i<6;++i) {
      state->push();
      // FIXME: It would have been nice to have a 'remove' or a 'replace'
      // method in the SoClipPlaneElement so that we wouldn't have to
      // push and pop the state. (20040630 handegar)
      SoClipPlaneElement::add(state, this->master, cubeplanes[i]);            
      this->clipgeometryshape->GLRender(action);
      state->pop();
    }
    
  }
}
SoXipDicomExaminer::SoXipDicomExaminer()
{
	SO_NODE_CONSTRUCTOR( SoXipDicomExaminer );

	SO_XIP_KIT_ADD_ENTRY( mCamera, SoOrthographicCamera, this );
	SO_XIP_KIT_ADD_ENTRY( mImageSwitch, SoSwitch, this );
	SO_XIP_KIT_ADD_ENTRY( mImage, SoXipImage, mImageSwitch );

	SO_NODE_DEFINE_ENUM_VALUE( ModeType, NONE );
	SO_NODE_DEFINE_ENUM_VALUE( ModeType, PANZOOM );
	SO_NODE_DEFINE_ENUM_VALUE( ModeType, SHIFT );
	SO_NODE_DEFINE_ENUM_VALUE( ModeType, SCROLL );
	SO_NODE_DEFINE_ENUM_VALUE( ModeType, SHIFTSCROLL );
	SO_NODE_SET_SF_ENUM_TYPE( mode, ModeType );

	SO_NODE_ADD_FIELD(       drawImage, (TRUE) );
	SO_NODE_ADD_FIELD(          images, (0) );
	SO_NODE_ADD_FIELD(      imageIndex, (0) );
	SO_NODE_ADD_FIELD(   previousImage, () );
	SO_NODE_ADD_FIELD(       nextImage, () );
	SO_NODE_ADD_FIELD(      sliceIndex, (-1) );
	SO_NODE_ADD_FIELD(   previousSlice, () );
	SO_NODE_ADD_FIELD(       nextSlice, () );
	SO_NODE_ADD_FIELD(         viewAll, () );
	SO_NODE_ADD_FIELD(    viewAllScale, (0.8) );
	SO_NODE_ADD_FIELD(            mode, (NONE) );
	SO_NODE_ADD_FIELD(     boundingBox, (SbMatrix::identity()) );
	SO_NODE_ADD_FIELD( viewBoundingBox, ());
	SO_NODE_ADD_FIELD( planeSlice, (SbPlane(SbVec3f(1, 0, 0), 0)));

	SoField* fields[8] = { &viewAll, &viewBoundingBox, &nextImage, &previousImage, &nextSlice, &previousSlice, &images, &mode };
	for( int i = 0; i < 8; ++ i )
	{
		mFieldSensors[i] = new SoFieldSensor( &fieldSensorCB, this );
		mFieldSensors[i]->attach( fields[i] );
	}

	mSelectionEngine = new SoXipConvertMFDicomToSFDicom;
	mSelectionEngine->ref();

	mDicomExtract = new SoXipDicomExtractSlice;
	mDicomExtract->ref();

	mSelectionEngine->input.connectFrom(&images);
	mSelectionEngine->index.connectFrom(&imageIndex);

	mDicomExtract->image.connectFrom(&mSelectionEngine->output);
	mDicomExtract->sliceIndex.connectFrom(&sliceIndex);
	numSlices.connectFrom( &mDicomExtract->numSlices );

	((SoXipSFDataImage *)mImage->getField(SbName("image")))->connectFrom(&mDicomExtract->output);

	// Create a field sensor on the internal image to update the camera
	mImageSensor = new SoFieldSensor( &fieldSensorCB, this );
	mImageSensor->attach( (SoXipSFDataImage *)mImage->getField(SbName("image")) );
	mImageSensor->setPriority(0);

	// Initialize the animation members to null
	mAnimate = FALSE;
	mAnimateHStep = 0;
	mAnimateHPosition = 0;
	mAnimateVStep = 0;
	mAnimateVPosition = 0;
	mAnimateChange = 0;
	mAnimationSensor = 0;

	mViewAll = TRUE;
	mPan = FALSE;
	mViewBoundingBox = FALSE;
}
SoField *
SoBuiltinFieldConverter::getInput(SoType type)
//
////////////////////////////////////////////////////////////////////////
{
    input = (SoField *)type.createInstance();
    
#define DECIDEIN(class,defaultValue) \
    (type == SO__CONCAT(So,class)::getClassTypeId()) { \
	inType = class; \
	((SO__CONCAT(So,class) *)input)->setValue defaultValue ; \
    }
    
    if DECIDEIN(MFBitMask,(0))
    else if DECIDEIN(MFBool,(FALSE))
    else if DECIDEIN(MFColor,(0,0,0))
    else if DECIDEIN(MFEnum,(0))
    else if DECIDEIN(MFFloat,(0))
    else if DECIDEIN(MFInt32,(0))
    else if DECIDEIN(MFMatrix,(SbMatrix::identity()))
    else if DECIDEIN(MFName,(""))
    else if DECIDEIN(MFNode,(NULL))
    else if DECIDEIN(MFPath,(NULL))
    else if DECIDEIN(MFPlane,(SbPlane(SbVec3f(0,0,0),0)))
    else if DECIDEIN(MFRotation,(SbRotation()))
    else if DECIDEIN(MFShort,(0))
    else if DECIDEIN(MFString,(""))
    else if DECIDEIN(MFTime,(SbTime::zero()))
    else if DECIDEIN(MFUInt32,(0))
    else if DECIDEIN(MFUShort,(0))
    else if DECIDEIN(MFVec2f,(0,0))
    else if DECIDEIN(MFVec3f,(0,0,0))
    else if DECIDEIN(MFVec4f,(0,0,0,0))
    else if DECIDEIN(SFBitMask,(0))
    else if DECIDEIN(SFBool,(FALSE))
    else if DECIDEIN(SFColor,(0,0,0))
    else if DECIDEIN(SFEnum,(0))
    else if DECIDEIN(SFFloat,(0))
    else if DECIDEIN(SFInt32,(0))
    else if DECIDEIN(SFMatrix,(SbMatrix::identity()))
    else if DECIDEIN(SFName,(""))
    else if DECIDEIN(SFNode,(NULL))
    else if DECIDEIN(SFPath,(NULL))
    else if DECIDEIN(SFPlane,(SbPlane(SbVec3f(0,0,0),0)))
    else if DECIDEIN(SFRotation,(SbRotation()))
    else if DECIDEIN(SFShort,(0))
    else if DECIDEIN(SFString,(""))
    else if DECIDEIN(SFTime,(SbTime::zero()))
    else if DECIDEIN(SFUInt32,(0))
    else if DECIDEIN(SFUShort,(0))
    else if DECIDEIN(SFVec2f,(0,0))
    else if DECIDEIN(SFVec3f,(0,0,0))
    else if DECIDEIN(SFVec4f,(0,0,0,0))
#undef DECIDEIN
#ifdef DEBUG	
    else {
	SoDebugError::post("(internal) SoBuiltinFieldConverter::getInput",
		       "no input for type '%s'", type.getName().getString());
    }
#endif    

    input->setContainer(this);
    myInputData->addField(this, "input", input);

    return input;
}