void SoXipGetCameraProperties::GLRender(SoGLRenderAction* action)
{
    /*
	SbMatrix mMV = SoModelMatrixElement::get(action->getState()) * SoViewingMatrixElement::get(action->getState());
    SbMatrix mv = mMV.transpose();
    mv = mv.inverse();
    SbVec3f cc(0.0,0.0,0.0);
    SbVec3f wc;
    mv.multMatrixVec(cc, wc);
    */
    SbViewVolume vv = SoViewVolumeElement::get( action->getState() );

    mCamPos = vv.getSightPoint(0.0);
    if (mCamPos != camPos.getValue())
        camPos.setValue( mCamPos );

    mCamDir = vv.getSightPoint(1.0) - vv.getSightPoint(0.0);
    if (mCamDir != camDir.getValue() )
        camDir.setValue( mCamDir );

    SbViewportRegion vpr = SoViewportRegionElement::get( action->getState() );
    SbVec2s orig = vpr.getViewportOriginPixels();
    SbVec2s wh = vpr.getViewportSizePixels();
    SbVec4f vp = SbVec4f( (float)orig[0], (float)orig[1], (float)wh[0], (float)wh[1] );

    mViewport = vp;
    if (mViewport != viewport.getValue())
        viewport.setValue( mViewport );
}
float SoZoomTranslation::getScaleFactor(SoAction* action) const
{
    // Dividing by 5 seems to work well
    SbViewVolume vv = SoViewVolumeElement::get(action->getState());
    float aspectRatio = SoViewportRegionElement::get(action->getState()).getViewportAspectRatio();
    float scale = vv.getWorldToScreenScale(SbVec3f(0.f, 0.f, 0.f), 0.1f) / (5*aspectRatio);
    return scale;
}
Example #3
0
void ViewProviderStructured::cut(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer)
{
    // create the polygon from the picked points
    Base::Polygon2D cPoly;
    for (std::vector<SbVec2f>::const_iterator it = picked.begin(); it != picked.end(); ++it) {
        cPoly.Add(Base::Vector2D((*it)[0],(*it)[1]));
    }

    // get a reference to the point feature
    Points::Feature* fea = static_cast<Points::Feature*>(pcObject);
    const Points::PointKernel& points = fea->Points.getValue();

    SoCamera* pCam = Viewer.getSoRenderManager()->getCamera();
    SbViewVolume  vol = pCam->getViewVolume();

    // search for all points inside/outside the polygon
    Points::PointKernel newKernel;
    newKernel.reserve(points.size());

    bool invalidatePoints = false;
    double nan = std::numeric_limits<double>::quiet_NaN();
    for (Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt) {
        // valid point?
        Base::Vector3d vec(*jt);
        if (!(boost::math::isnan(jt->x) || boost::math::isnan(jt->y) || boost::math::isnan(jt->z))) {
            SbVec3f pt(jt->x,jt->y,jt->z);

            // project from 3d to 2d
            vol.projectToScreen(pt, pt);
            if (cPoly.Contains(Base::Vector2D(pt[0],pt[1]))) {
                invalidatePoints = true;
                vec.Set(nan, nan, nan);
            }
        }

        newKernel.push_back(vec);
    }

    if (invalidatePoints) {
        //Remove the points from the cloud and open a transaction object for the undo/redo stuff
        Gui::Application::Instance->activeDocument()->openCommand("Cut points");

        // sets the points outside the polygon to update the Inventor node
        fea->Points.setValue(newKernel);

        // unset the modified flag because we don't need the features' execute() to be called
        Gui::Application::Instance->activeDocument()->commitCommand();
        fea->purgeTouched();
    }
}
Example #4
0
// Doc in superclass.
SbViewVolume
SoOrthographicCamera::getViewVolume(float useaspectratio) const
{
  SbViewVolume volume;

  if (useaspectratio == 0.0f) useaspectratio = this->aspectRatio.getValue();
  float halfheight = this->height.getValue() * 0.5f;
  float halfwidth = halfheight * useaspectratio;
  volume.ortho(-halfwidth, halfwidth,
               -halfheight, halfheight,
               this->nearDistance.getValue(), this->farDistance.getValue());
  
  volume.rotateCamera(this->orientation.getValue());
  volume.translateCamera(this->position.getValue());
  return volume;
}
Example #5
0
void 
SoXipMarkerSet::GLRender( SoGLRenderAction* action )
{
	if (mCoord && mFaceSet && mScale && mTranslation && mRotation)
	{
		float pointSize = SoPointSizeElement::get(action->getState());
		SbViewportRegion vp = SoViewportRegionElement::get(action->getState());
		SbViewVolume vVol = SoViewVolumeElement::get(action->getState());

		// world to pixel scale
		float scaleFactorY = pointSize * vVol.getHeight() / (float) vp.getViewportSizePixels()[1];
		float scaleFactorX = pointSize * vVol.getWidth() / (float) vp.getViewportSizePixels()[0];
		mScale->scaleFactor.setValue(0.5f * scaleFactorX, 0.5f * scaleFactorY, 1);

		// world to screen rotation
		SbMatrix affine, proj;
		vVol.getMatrices(affine, proj);
		SbVec3f t, s;
		SbRotation rot, so;
		affine.inverse().getTransform(t, rot, s, so);
		mRotation->rotation.setValue(rot);

		// number of coordinates
		const SoCoordinateElement	*ce = (const SoCoordinateElement *) SoCoordinateElement::getInstance(action->getState());
		int numPts = 0;
		if (ce)
		{
			numPts = ce->getNum();
		}

		SbXipMarkerShapes::getVertices(marker.getValue(), mCoord->point);
		SbXipMarkerShapes::getNumVertices(marker.getValue(), mFaceSet->numVertices);

		for (int i = 0; i < numPts; i++)
		{
			mTranslation->translation.setValue(ce->get3(i));

			action->getState()->push();
			action->traverse(mTranslation);
			action->traverse(mRotation);
			action->traverse(mScale);
			action->traverse(mCoord);
			action->traverse(mFaceSet);
			action->getState()->pop();
		}
	}
}
void SoFCCSysDragger::idleCB(void *data, SoSensor *)
{
    SoFCCSysDragger *sudoThis = reinterpret_cast<SoFCCSysDragger *>(data);
    assert(sudoThis->camera);

    SbMatrix localToWorld = sudoThis->getLocalToWorldMatrix();
    SbVec3f origin;
    localToWorld.multVecMatrix(SbVec3f(0.0, 0.0, 0.0), origin);

    SbViewVolume viewVolume = sudoThis->camera->getViewVolume();
    float radius = sudoThis->draggerSize.getValue() / 2.0;
    float localScale = viewVolume.getWorldToScreenScale(origin, radius);
    SbVec3f scaleVector(localScale, localScale, localScale);
    SoScale *localScaleNode = SO_GET_ANY_PART(sudoThis, "scaleNode", SoScale);
    localScaleNode->scaleFactor.setValue(scaleVector);
    sudoThis->autoScaleResult.setValue(localScale);
}
void ViewProviderPoints::cut(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer)
{
    // create the polygon from the picked points
    Base::Polygon2D cPoly;
    for (std::vector<SbVec2f>::const_iterator it = picked.begin(); it != picked.end(); ++it) {
        cPoly.Add(Base::Vector2D((*it)[0],(*it)[1]));
    }

    // get a reference to the point feature
    Points::Feature* fea = (Points::Feature*)pcObject;
    const Points::PointKernel& points = fea->Points.getValue();

    SoCamera* pCam = Viewer.getSoRenderManager()->getCamera();  
    SbViewVolume  vol = pCam->getViewVolume(); 

    // search for all points inside/outside the polygon
    Points::PointKernel newKernel;
    for ( Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt ) {
        SbVec3f pt(jt->x,jt->y,jt->z);

        // project from 3d to 2d
        vol.projectToScreen(pt, pt);
        if (!cPoly.Contains(Base::Vector2D(pt[0],pt[1])))
            newKernel.push_back(*jt);
    }

    if (newKernel.size() == points.size())
        return; // nothing needs to be done

    //Remove the points from the cloud and open a transaction object for the undo/redo stuff
    Gui::Application::Instance->activeDocument()->openCommand("Cut points");

    // sets the points outside the polygon to update the Inventor node
    fea->Points.setValue(newKernel);

    // unset the modified flag because we don't need the features' execute() to be called
    Gui::Application::Instance->activeDocument()->commitCommand();
    fea->purgeTouched();
}
Example #8
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);
}
Example #9
0
void GLFlagWindow::paintGL()
{
    // draw lines for the flags
    if (_flagLayout) {
        // it can happen that the GL widget gets replaced internally (SoQt only, not with quarter) which
        // causes to destroy the FlagLayout instance
        int ct = _flagLayout->count();
        const SbViewportRegion vp = _viewer->getSoRenderManager()->getViewportRegion();
        SbVec2s size = vp.getViewportSizePixels();
        float aspectratio = float(size[0])/float(size[1]);
        SbViewVolume vv = _viewer->getSoRenderManager()->getCamera()->getViewVolume(aspectratio);
        for (int i=0; i<ct;i++) {
            Flag* flag = qobject_cast<Flag*>(_flagLayout->itemAt(i)->widget());
            if (flag) {
                SbVec3f pt = flag->getOrigin();
                vv.projectToScreen(pt, pt);
                int tox = (int)(pt[0] * size[0]);
                int toy = (int)((1.0f-pt[1]) * size[1]);
                flag->drawLine(_viewer, tox, toy);
            }
        }
    }
}
Example #10
0
// doc from superclass.
void
SoNurbsProfile::getVertices(SoState * state, int32_t & numvertices,
                            SbVec2f * & vertices)
{
  // FIXME: optimize by detecting when the previously calculated
  // vertices can be returned. pederb, 20000922
  int32_t numpoints;
  float * points;
  int floatspervec;
  int32_t numknots;
  float * knotvector;
  this->getTrimCurve(state, numpoints, points, floatspervec, numknots, knotvector);
  if (numpoints == 0 || numknots == 0) {
    numvertices = 0;
    vertices = NULL;
    return;
  }

  SbList <float> * coordListNurbsProfile =
    so_nurbsprofile_get_coordlist(FALSE);

  SbList <float> * nurbsProfileTempList =
    so_nurbsprofile_get_coordlist(TRUE);

  nurbsProfileTempList->truncate(0);
  for (int i = 0; i < numpoints; i++) {
    nurbsProfileTempList->append(points[i*floatspervec]);
    nurbsProfileTempList->append(points[i*floatspervec+1]);
    if (GLUWrapper()->available &&
        GLUWrapper()->versionMatchesAtLeast(1, 3, 0)) {
      nurbsProfileTempList->append(0.0f); // gluNurbs needs 3D coordinates
    }
  }
  if (GLUWrapper()->available &&
      GLUWrapper()->versionMatchesAtLeast(1, 3, 0)) {
    // we will write into this array in the GLU callback
    coordListNurbsProfile->truncate(0);

    if (this->nurbsrenderer == NULL) {
      this->nurbsrenderer = GLUWrapper()->gluNewNurbsRenderer();
      GLUWrapper()->gluNurbsCallback(this->nurbsrenderer, (GLenum) GLU_NURBS_VERTEX,
                                     (gluNurbsCallback_cb_t)nurbsprofile_tess_vertex);
      GLUWrapper()->gluNurbsProperty(this->nurbsrenderer, (GLenum) GLU_NURBS_MODE, GLU_NURBS_TESSELLATOR);
      GLUWrapper()->gluNurbsProperty(this->nurbsrenderer, (GLenum) GLU_AUTO_LOAD_MATRIX, FALSE);
      GLUWrapper()->gluNurbsProperty(this->nurbsrenderer, (GLenum) GLU_DISPLAY_MODE, GLU_POINT);
      GLUWrapper()->gluNurbsProperty(this->nurbsrenderer, (GLenum) GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE);
    }

    // this looks pretty good
    float cmplx = SoComplexityElement::get(state);
    cmplx += 1.0f;
    cmplx = cmplx * cmplx * cmplx;
    GLUWrapper()->gluNurbsProperty(this->nurbsrenderer, (GLenum) GLU_U_STEP, float(numpoints)*cmplx);

    // these values are not important as we're not using screen-space
    // complexity (yet)
    SbMatrix modelmatrix = SbMatrix::identity();
    SbMatrix affine, proj;
    SbViewVolume vv;
    vv.ortho(0.0f, 1.0f,
             0.0f, 1.0f,
             -1.0f, 1.0f);
    vv.getMatrices(affine, proj);
    GLint viewport[4];
    viewport[0] = 0;
    viewport[1] = 0;
    viewport[2] = 256;
    viewport[3] = 256;
    GLUWrapper()->gluLoadSamplingMatrices(this->nurbsrenderer,
                                          modelmatrix[0],
                                          proj[0],
                                          viewport);

    // generate curve
    GLUWrapper()->gluBeginCurve(this->nurbsrenderer);
    GLUWrapper()->gluNurbsCurve(this->nurbsrenderer,
                                numknots,
                                (float*)knotvector,
                                3,
                                (float*)nurbsProfileTempList->getArrayPtr(),
                                numknots - numpoints,
                                GL_MAP1_VERTEX_3);
    GLUWrapper()->gluEndCurve(this->nurbsrenderer);

    // when we get here, the GLU callback should have added the
    // points to the list
    numvertices = coordListNurbsProfile->getLength() / 2;
    vertices = (SbVec2f*) coordListNurbsProfile->getArrayPtr();
  }
  else {
    // just send the control points when GLU v1.3 is not available
    numvertices = numpoints;
    vertices = (SbVec2f*) nurbsProfileTempList->getArrayPtr();
  }
}
Example #11
0
void ViewProviderScattered::cut(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer)
{
    // create the polygon from the picked points
    Base::Polygon2D cPoly;
    for (std::vector<SbVec2f>::const_iterator it = picked.begin(); it != picked.end(); ++it) {
        cPoly.Add(Base::Vector2D((*it)[0],(*it)[1]));
    }

    // get a reference to the point feature
    Points::Feature* fea = static_cast<Points::Feature*>(pcObject);
    const Points::PointKernel& points = fea->Points.getValue();

    SoCamera* pCam = Viewer.getSoRenderManager()->getCamera();
    SbViewVolume  vol = pCam->getViewVolume();

    // search for all points inside/outside the polygon
    std::vector<unsigned long> removeIndices;
    removeIndices.reserve(points.size());

    unsigned long index = 0;
    for (Points::PointKernel::const_iterator jt = points.begin(); jt != points.end(); ++jt, ++index) {
        SbVec3f pt(jt->x,jt->y,jt->z);

        // project from 3d to 2d
        vol.projectToScreen(pt, pt);
        if (cPoly.Contains(Base::Vector2D(pt[0],pt[1])))
            removeIndices.push_back(index);
    }

    if (removeIndices.empty())
        return; // nothing needs to be done

    //Remove the points from the cloud and open a transaction object for the undo/redo stuff
    Gui::Application::Instance->activeDocument()->openCommand("Cut points");

    // sets the points outside the polygon to update the Inventor node
    fea->Points.removeIndices(removeIndices);

    std::map<std::string,App::Property*> Map;
    pcObject->getPropertyMap(Map);

    for (std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it) {
        Base::Type type = it->second->getTypeId();
        if (type == Points::PropertyNormalList::getClassTypeId()) {
            static_cast<Points::PropertyNormalList*>(it->second)->removeIndices(removeIndices);
        }
        else if (type == Points::PropertyGreyValueList::getClassTypeId()) {
            static_cast<Points::PropertyGreyValueList*>(it->second)->removeIndices(removeIndices);
        }
        else if (type == App::PropertyColorList::getClassTypeId()) {
            //static_cast<App::PropertyColorList*>(it->second)->removeIndices(removeIndices);
            const std::vector<App::Color>& colors = static_cast<App::PropertyColorList*>(it->second)->getValues();

            if (removeIndices.size() > colors.size())
                break;

            std::vector<App::Color> remainValue;
            remainValue.reserve(colors.size() - removeIndices.size());

            std::vector<unsigned long>::iterator pos = removeIndices.begin();
            for (std::vector<App::Color>::const_iterator jt = colors.begin(); jt != colors.end(); ++jt) {
                unsigned long index = jt - colors.begin();
                if (pos == removeIndices.end())
                    remainValue.push_back( *jt );
                else if (index != *pos)
                    remainValue.push_back( *jt );
                else 
                    ++pos;
            }

            static_cast<App::PropertyColorList*>(it->second)->setValues(remainValue);
        }
    }

    // unset the modified flag because we don't need the features' execute() to be called
    Gui::Application::Instance->activeDocument()->commitCommand();
    fea->purgeTouched();
}
Example #12
0
void
SmTextureText2::renderString(const SmTextureFontBundle & bundle,
                             const SbString * s,
                             const int numstring,
                             const SbVec3f & pos,
                             const SbViewVolume & vv,
                             const SbViewportRegion & vp,
                             const SbMatrix & projmatrix,
                             const SbMatrix & modelmatrix,
                             const SbMatrix & invmodelmatrix,
                             const float rotation)
{
  // get distance from pos to camera plane
  SbVec3f tmp;
  modelmatrix.multVecMatrix(pos, tmp);
  float dist = -vv.getPlane(0.0f).getDistance(tmp);
  if (dist <= vv.getNearDist()) return;
  if (dist > (vv.getNearDist() + vv.getDepth())) return;

  float maxr = this->maxRange.getValue();
  if (maxr > 0.0f && dist > maxr) return;

  int i;
  SbVec2s vpsize = vp.getViewportSizePixels();

  SbVec3f screenpoint;
  projmatrix.multVecMatrix(pos, screenpoint);

  int xmin = 0;
  int ymax = bundle.getAscent();
  int ymin = ymax - numstring * (bundle.height() + bundle.getLeading());
  ymin += bundle.getLeading();

  short h = ymax - ymin;
  short halfh = h / 2;

  switch (this->verticalJustification.getValue()) {
  case SmTextureText2::BOTTOM:
    break;
  case SmTextureText2::TOP:
    ymin -= bundle.getAscent();
    ymax -= bundle.getAscent();
    break;
  case SmTextureText2::VCENTER:
    ymin -= halfh;
    ymax -= halfh;
    break;
  default:
    assert(0 && "unknown alignment");
    break;
  }
  SbList <int> widthlist;

  for (i = 0; i < numstring; i++) {
    widthlist.append(bundle.stringWidth(s[i]));
  }

  for (i = 0; i < numstring; i++) {

    int len = s[i].getLength();
    if (len == 0) continue;

    SbVec2s sp;
    if (!get_screenpoint_pixels(screenpoint, vpsize, sp)) continue;

    SbVec2s n0 = SbVec2s(sp[0] + xmin,
                         sp[1] + ymax - (i+1)*bundle.height());

    short w = static_cast<short>(widthlist[i]);
    short halfw = w / 2;

    switch (this->justification.getValue()) {
    case SmTextureText2::LEFT:
      break;
    case SmTextureText2::RIGHT:
      n0[0] -= w;
      break;
    case SmTextureText2::CENTER:
      n0[0] -= halfw;
      break;
    default:
      assert(0 && "unknown alignment");
      break;
    }

    if (rotation != 0) {
      float x = static_cast<float>(sp[0]);
      float y = static_cast<float>(sp[1]);
      glPushMatrix();
      glTranslatef(x, y, 0);
      glRotatef(rotation * static_cast<float>(180 / M_PI), 0, 0, 1);
      glTranslatef(-x, -y, 0);
    }
    
    bundle.begin();
    bundle.renderString(s[i], SbVec3f(n0[0], n0[1], screenpoint[2]));
    bundle.end();

    if (rotation != 0) glPopMatrix();
  }
}
Example #13
0
//======================================================================
//
// Description:
//	projection of telepointer
//
//
// Use: private
//======================================================================
void TPHandler::projectTelePointer(TelePointer *, const SbVec3f pos, float aspectRatio,
                                   SbVec3f &intersection, InvExaminerViewer *viewer)
{
    const int xOffset = 61;
    const int yOffset = 33;

    float xs, ys, zs; // normalized screen coordinates
    SbVec3f screen;

    SbVec2s size = viewer->getSize();
    if (viewer->isDecoration())
    {
        // !! Attention: SoXtRenderArea with offset
        size[0] = size[0] - xOffset;
        size[1] = size[1] - yOffset;
    }
    float aspRat = size[0] / (float)size[1];

    // set aspect ratio explicitely
    tp_camera->aspectRatio.setValue(aspRat);
    // default setting
    tp_camera->height.setValue(2.0);
    // scale height
    tp_camera->scaleHeight(1 / aspRat);

    /*
   float h = tp_camera->height.getValue();
   fprintf(stderr, "Height Camera: %.6f\n", h);
   */

    // get the view volume -> rectangular box
    SbViewVolume viewVolume = tp_camera->getViewVolume();
    // determine mouse position
    viewVolume.projectToScreen(pos, screen);
    screen.getValue(xs, ys, zs);
    /*
   cerr << "xs: " << xs << endl;
   cerr << "ys: " << ys << endl;
   */

    // project the mouse point to a line
    SbVec3f p0, p1;
    viewVolume.projectPointToLine(SbVec2f(xs, ys), p0, p1);

    // take the midpoint of the line as telepointer position
    intersection = (p0 + p1) / 2.0f;

    // adapt telepointer position to the aspect ratio
    if (aspectRatio > 1.0)
    {
        intersection[0] = intersection[0] * aspectRatio / aspRat;
        intersection[1] = intersection[1] * aspectRatio / aspRat;
    }

    if (aspectRatio < 1.0)
    {
        // in this case the aspect ratio submitted to the function
        // and belonging to the delivered position leads to wrong projection point
        // => local correction for x-, y-value
        intersection[0] = intersection[0] / aspRat;
        intersection[1] = intersection[1] / aspRat;
    }

    /*
   float fx,fy,fz;
   intersection.getValue(fx,fy,fz);
   cerr << "TP: (" << fx << "," << fy << "," << fz << ")" << endl;
   */
}
void SoXipCPUMprRender::GLRender(SoGLRenderAction * action)
{
	SoState *state = action->getState();
	SbViewportRegion vpRegion = SoViewportRegionElement::get(state);
	SbVec2s vpSize = vpRegion.getViewportSizePixels();

	// Don't do anything if 0 size
	if (!vpSize[0] || !vpSize[1])
		return;

	// Bind texture to available texture stage
	if (!mMPRTexId)
		glGenTextures(1, &mMPRTexId);

	int texUnit = SoXipMultiTextureElement::getFreeUnit(state);
	SoXipMultiTextureElement::setUnit(state, texUnit);
	SoXipMultiTextureElement::bindTexture(state, GL_TEXTURE_2D, mMPRTexId);

	// Check the size against min/max
	SbVec2s minmax = minMaxSize.getValue();
	int which = (vpSize[0] > vpSize[1]) ? 0 : 1;
	float ratio = (float) vpSize[which] / (float) vpSize[1 - which];
	// If smallest dim is < min
	if (vpSize[1 - which] < minmax[0])
	{
		// Clamp to min and change biggest dim according to aspect ratio
		vpSize[1 - which] = minmax[0];
		vpSize[which] = (short) (ratio * vpSize[1 - which]);
	}
	// If biggest dim is > max
	if (vpSize[which] > minmax[1])
	{
		// Clamp to max and change smallest dim according to aspect ratio
		vpSize[which] = minmax[1];
		vpSize[1 - which] = (short) (vpSize[which] / ratio);
	}

	// Ready the buffers
	readyBuffers(state);

	if (vpSize[0] == 0 || vpSize[1] == 0)
		return;

	// Check if mpr texture must be resized
	if (mMPRSize != vpSize)
	{
		resizeBuffers(vpSize);
		mUpdateFlag |= UPDATE_MPRCACHE;
    }
    
    // Exit if unsupported image type
    if (mTexInternalFormat == 0 ||
        mTexType == 0)
        return;

	// Check if orientation has changed
	SbVec3f	corners[4];
	SbViewVolume viewVolume = SoViewVolumeElement::get(state);
	float dist = viewVolume.getNearDist() + viewVolume.getDepth() * 0.5f;
	corners[0] = viewVolume.getPlanePoint(dist, SbVec2f(0, 1));
	corners[1] = viewVolume.getPlanePoint(dist, SbVec2f(1, 1));
	corners[2] = viewVolume.getPlanePoint(dist, SbVec2f(1, 0));
	corners[3] = viewVolume.getPlanePoint(dist, SbVec2f(0, 0));
	if (corners[0] != mCorners[0] ||
		corners[1] != mCorners[1] ||
		corners[2] != mCorners[2] ||
		corners[3] != mCorners[3])
	{
		mCorners[0] = corners[0];
		mCorners[1] = corners[1];
		mCorners[2] = corners[2];
		mCorners[3] = corners[3];
		mUpdateFlag |= UPDATE_MPRCACHE;
	}

	
	//
	if (mUpdateFlag & UPDATE_MPRCACHE)
	{
		// Compute new cache table and mpr
		switch (mVolDataType)
		{
		case SbXipImage::UNSIGNED_BYTE:
			mLutBuf ? computeMPRCacheLUT(this, (unsigned char*)mVolBuf, state) : computeMPRCache(this, (unsigned char*)mVolBuf, state);
			break;
		case SbXipImage::BYTE:
			mLutBuf ? computeMPRCacheLUT(this, (char*)mVolBuf, state) : computeMPRCache(this, (char*)mVolBuf, state);
			break;
		case SbXipImage::UNSIGNED_SHORT:
			mLutBuf ? computeMPRCacheLUT(this, (unsigned short*)mVolBuf, state) : computeMPRCache(this, (unsigned short*)mVolBuf, state);
			break;
		case SbXipImage::SHORT:
			mLutBuf ? computeMPRCacheLUT(this, (short*)mVolBuf, state) : computeMPRCache(this, (short*)mVolBuf, state);
			break;
		case SbXipImage::UNSIGNED_INT:
			mLutBuf ? computeMPRCacheLUT(this, (unsigned int*)mVolBuf, state) : computeMPRCache(this, (unsigned int*)mVolBuf, state);
			break;
		case SbXipImage::INT:
			mLutBuf ? computeMPRCacheLUT(this, (int*)mVolBuf, state) : computeMPRCache(this, (int*)mVolBuf, state);
			break;
		case SbXipImage::FLOAT:
			mLutBuf ? computeMPRCacheLUT(this, (float*)mVolBuf, state) : computeMPRCache(this, (float*)mVolBuf, state);
			break;
		case SbXipImage::DOUBLE:
			mLutBuf ? computeMPRCacheLUT(this, (double*)mVolBuf, state) : computeMPRCache(this, (double*)mVolBuf, state);
			break;
		default:
            // will never come here cause we already checked for it in resize
			break;	
		}
		// Update mpr texture
		updateTexture();
	}
	else if (mUpdateFlag & UPDATE_MPR)
	{
		// Compute new mpr
		switch (mVolDataType)
		{
		case SbXipImage::UNSIGNED_BYTE:
			mLutBuf ? computeMPRLUT(this, (unsigned char*)mVolBuf) : computeMPR(this, (unsigned char*)mVolBuf);
			break;
		case SbXipImage::BYTE:
			mLutBuf ? computeMPRLUT(this, (char*)mVolBuf) : computeMPR(this, (char*)mVolBuf);
			break;
		case SbXipImage::UNSIGNED_SHORT:
			mLutBuf ? computeMPRLUT(this, (unsigned short*)mVolBuf) : computeMPR(this, (unsigned short*)mVolBuf);
			break;
		case SbXipImage::SHORT:
			mLutBuf ? computeMPRLUT(this, (short*)mVolBuf) : computeMPR(this, (short*)mVolBuf);
			break;
		case SbXipImage::UNSIGNED_INT:
			mLutBuf ? computeMPRLUT(this, (unsigned int*)mVolBuf) : computeMPR(this, (unsigned int*)mVolBuf);
			break;
		case SbXipImage::INT:
			mLutBuf ? computeMPRLUT(this, (int*)mVolBuf) : computeMPR(this, (int*)mVolBuf);
			break;
		case SbXipImage::FLOAT:
			mLutBuf ? computeMPRLUT(this, (float*)mVolBuf) : computeMPR(this, (float*)mVolBuf);
			break;
		case SbXipImage::DOUBLE:
			mLutBuf ? computeMPRLUT(this, (double*)mVolBuf) : computeMPR(this, (double*)mVolBuf);
			break;
		default:
            // will never come here cause we already checked for it in resize
			break;	
		}
		// Update mpr texture
		updateTexture();
	}

	// Render mpr to a quad
	renderMPR(texUnit);

	// Reset update flag
	mUpdateFlag = 0;
}
Example #15
0
/**
 * Renders the label.
 */
void SoTextLabel::GLRender(SoGLRenderAction *action)
{
    if (!this->shouldGLRender(action)) return;

    // only draw text without background
    if (!this->background.getValue()) {
        inherited::GLRender(action);
        return;
    }

    SoState * state = action->getState();

    state->push();
    SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);

    SbBox3f box;
    SbVec3f center;
    this->computeBBox(action, box, center);

    if (!SoCullElement::cullTest(state, box, TRUE)) {
        SoMaterialBundle mb(action);
        mb.sendFirst();
        const SbMatrix & mat = SoModelMatrixElement::get(state);
        //const SbViewVolume & vv = SoViewVolumeElement::get(state);
        const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
                                       SoProjectionMatrixElement::get(state));
        const SbViewportRegion & vp = SoViewportRegionElement::get(state);
        SbVec2s vpsize = vp.getViewportSizePixels();

        // font stuff
        //float space = this->spacing.getValue();
        //float fontsize = SoFontSizeElement::get(state);
        SbName fontname = SoFontNameElement::get(state);
        int lines = this->string.getNum();

        // get left bottom corner of the label
        SbVec3f nilpoint(0.0f, 0.0f, 0.0f);
        projmatrix.multVecMatrix(nilpoint, nilpoint);
        nilpoint[0] = (nilpoint[0] + 1.0f) * 0.5f * vpsize[0];
        nilpoint[1] = (nilpoint[1] + 1.0f) * 0.5f * vpsize[1];

#if 1
        // Unfortunately, the size of the label is stored in the pimpl class of
        // SoText2 which cannot be accessed directly. However, there is a trick
        // to get the required information: set model, viewing and projection
        // matrix to the identity matrix and also view volume to some default
        // values. SoText2::computeBBox() then calls SoText2P::getQuad which
        // returns the sizes in form of the bounding box. These values can be
        // reverse-engineered to get width and height.
        state->push();
        SoModelMatrixElement::set(state,this,SbMatrix::identity());
        SoViewingMatrixElement::set(state,this,SbMatrix::identity());
        SoProjectionMatrixElement::set(state,this,SbMatrix::identity());
        SbViewVolume vv;
        vv.ortho(-1,1,-1,1,-1,1);
        SoViewVolumeElement::set(state,this,vv);

        SbBox3f box;
        SbVec3f center;
        this->computeBBox(action, box, center);
        state->pop();

        float xmin,ymin,zmin,xmax,ymax,zmax;
        box.getBounds(xmin,ymin,zmin,xmax,ymax,zmax);
        SbVec3f v0(xmin,ymax,zmax);
        SbVec3f v1(xmax,ymax,zmax);
        SbVec3f v2(xmax,ymin,zmax);
        SbVec3f v3(xmin,ymin,zmax);
        vv.projectToScreen(v0,v0);
        vv.projectToScreen(v1,v1);
        vv.projectToScreen(v2,v2);
        vv.projectToScreen(v3,v3);

        float width,height;
        width  = (v1[0]-v0[0])*vpsize[0];
        height = (v1[1]-v3[1])*vpsize[1];
        switch (this->justification.getValue()) {
        case SoText2::RIGHT:
            nilpoint[0] -= width;
            break;
        case SoText2::CENTER:
            nilpoint[0] -= 0.5f*width;
            break;
        default:
            break;
        }

        if (lines > 1) {
            nilpoint[1] -= (float(lines-1)/(float)lines*height);
        }
#else
        // Unfortunately, the required size (in pixels) is stored in a non-accessible way
        // in the subclass SoText2. Thus, we try to get a satisfactory solution with Qt 
        // methods.
        // The font name is of the form "family:style". If 'style' is given it can be
        // 'Bold', 'Italic' or 'Bold Italic'.
        QFont font;
        QString fn = QString::fromAscii(fontname.getString());
        int pos = fn.indexOf(QLatin1Char(':'));
        if (pos > -1) {
            if (fn.indexOf(QLatin1String("Bold"),pos,Qt::CaseInsensitive) > pos)
                font.setBold(true);
            if (fn.indexOf(QLatin1String("Italic"),pos,Qt::CaseInsensitive) > pos)
                font.setItalic(true);
            fn = fn.left(pos);
        }
        font.setFamily(fn);
        font.setPixelSize((int)fontsize);
        QFontMetrics fm(font);

        float width = 0.0f;
        float height = 0.75f*fontsize*lines + (lines-1)*space;//fm.height();
        float hh=0;
        for (int i = 0; i < lines; i++) {
            SbString str = this->string[i];
            float w = fm.width(QLatin1String(this->string[i].getString()));
            width = std::max<float>(width, w);
            hh = fm.height();
        }

        if (lines > 1) {
            nilpoint[1] -= ((lines-1)*fontsize*0.75f+space);
        }
#endif

        SbVec3f toppoint = nilpoint;
        toppoint[0] += width;
        toppoint[1] += height;

        // Set new state.
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrtho(0, vpsize[0], 0, vpsize[1], -1.0f, 1.0f);
        glPixelStorei(GL_UNPACK_ALIGNMENT,1);

        state->push();

        // disable textures for all units
        SoGLTextureEnabledElement::set(state, this, FALSE);
        SoGLTexture3EnabledElement::set(state, this, FALSE);

        glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT);
        glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);

        // color and frame size
        SbColor color = this->backgroundColor.getValue();
        float fs = this->frameSize.getValue();

        // draw background
        glColor3f(color[0], color[1], color[2]);
        glBegin(GL_QUADS);
        glVertex3f(nilpoint[0]-fs,nilpoint[1]-fs,0.0f);
        glVertex3f(toppoint[0]+fs,nilpoint[1]-fs,0.0f);
        glVertex3f(toppoint[0]+fs,toppoint[1]+fs,0.0f);
        glVertex3f(nilpoint[0]-fs,toppoint[1]+fs,0.0f);
        glEnd();

        // pop old state
        glPopClientAttrib();
        glPopAttrib();
        state->pop();
          
        glPixelStorei(GL_UNPACK_ALIGNMENT,4);
        // Pop old GL matrix state.
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    }

    state->pop();

    inherited::GLRender(action);
}
Example #16
0
SbBool CADNavigationStyle::processSoEvent(const SoEvent * const ev)
{
#if 0
    // Events when in "ready-to-seek" mode are ignored, except those
    // which influence the seek mode itself -- these are handled further
    // up the inheritance hierarchy.
    if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
#else
    if (!this->isSeekMode() && this->isViewing())
        this->setViewing(false); // by default disable viewing mode to render the scene
#endif

    const SoType type(ev->getTypeId());

    const SbViewportRegion & vp = viewer->getViewportRegion();
    const SbVec2s size(vp.getViewportSizePixels());
    const SbVec2f prevnormalized = this->lastmouseposition;
    const SbVec2s pos(ev->getPosition());
    const SbVec2f posn((float) pos[0] / (float) SoQtMax((int)(size[0] - 1), 1),
                       (float) pos[1] / (float) SoQtMax((int)(size[1] - 1), 1));

    this->lastmouseposition = posn;

    // Set to TRUE if any event processing happened. Note that it is not
    // necessary to restrict ourselves to only do one "action" for an
    // event, we only need this flag to see if any processing happened
    // at all.
    SbBool processed = FALSE;

    const ViewerMode curmode = this->currentmode;
    ViewerMode newmode = curmode;

    // Mismatches in state of the modifier keys happens if the user
    // presses or releases them outside the viewer window.
    if (this->ctrldown != ev->wasCtrlDown()) {
        this->ctrldown = ev->wasCtrlDown();
    }
    if (this->shiftdown != ev->wasShiftDown()) {
        this->shiftdown = ev->wasShiftDown();
    }
    if (this->altdown != ev->wasAltDown()) {
        this->altdown = ev->wasAltDown();
    }

    // give the nodes in the foreground root the chance to handle events (e.g color bar)
    if (!processed && !viewer->isEditing()) {
        processed = handleEventInForeground(ev);
        if (processed)
            return TRUE;
    }

    // Keyboard handling
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
        const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
        switch (event->getKey()) {
        case SoKeyboardEvent::LEFT_CONTROL:
        case SoKeyboardEvent::RIGHT_CONTROL:
            this->ctrldown = press;
            break;
        case SoKeyboardEvent::LEFT_SHIFT:
        case SoKeyboardEvent::RIGHT_SHIFT:
            this->shiftdown = press;
            break;
        case SoKeyboardEvent::LEFT_ALT:
        case SoKeyboardEvent::RIGHT_ALT:
            this->altdown = press;
            break;
        case SoKeyboardEvent::H:
            processed = TRUE;
            viewer->saveHomePosition();
            break;
        case SoKeyboardEvent::S:
        case SoKeyboardEvent::HOME:
        case SoKeyboardEvent::LEFT_ARROW:
        case SoKeyboardEvent::UP_ARROW:
        case SoKeyboardEvent::RIGHT_ARROW:
        case SoKeyboardEvent::DOWN_ARROW:
            if (!this->isViewing())
                this->setViewing(true);
            break;
        default:
            break;
        }
    }

    // Mouse Button / Spaceball Button handling
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
        const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
        const int button = event->getButton();
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;

        // SoDebugError::postInfo("processSoEvent", "button = %d", button);
        switch (button) {
        case SoMouseButtonEvent::BUTTON1:
            this->lockrecenter = TRUE;
            this->button1down = press;
#if 0 // disable to avoid interferences where this key combination is used, too
            if (press && ev->wasShiftDown() &&
                (this->currentmode != NavigationStyle::SELECTION)) {
                this->centerTime = ev->getTime();
                float ratio = vp.getViewportAspectRatio();
                SbViewVolume vv = viewer->getCamera()->getViewVolume(ratio);
                this->panningplane = vv.getPlane(viewer->getCamera()->focalDistance.getValue());
                this->lockrecenter = FALSE;
            }
            else if (!press && ev->wasShiftDown() &&
                (this->currentmode != NavigationStyle::SELECTION)) {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                // is it just a left click?
                if (tmp.getValue() < dci && !this->lockrecenter) {
                    if (!this->moveToPoint(pos)) {
                        panToCenter(panningplane, posn);
                        this->interactiveCountDec();
                    }
                    processed = TRUE;
                }
            }
            else
#endif
            if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
                newmode = NavigationStyle::SEEK_MODE;
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
                processed = TRUE;
            }
            //else if (press && (this->currentmode == NavigationStyle::IDLE)) {
            //    this->setViewing(true);
            //    processed = TRUE;
            //}
            else if (press && (this->currentmode == NavigationStyle::PANNING ||
                               this->currentmode == NavigationStyle::ZOOMING)) {
                newmode = NavigationStyle::DRAGGING;
                this->centerTime = ev->getTime();
                processed = TRUE;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                if (tmp.getValue() < dci) {
                    newmode = NavigationStyle::ZOOMING;
                }
                processed = TRUE;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                this->setViewing(false);
                processed = TRUE;
            }
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
                processed = TRUE;
            }
            break;
        case SoMouseButtonEvent::BUTTON2:
            // If we are in edit mode then simply ignore the RMB events
            // to pass the event to the base class.
            this->lockrecenter = TRUE;
            if (!viewer->isEditing()) {
                // If we are in zoom or pan mode ignore RMB events otherwise
                // the canvas doesn't get any release events 
                if (this->currentmode != NavigationStyle::ZOOMING && 
                    this->currentmode != NavigationStyle::PANNING &&
                    this->currentmode != NavigationStyle::DRAGGING) {
                    if (this->isPopupMenuEnabled()) {
                        if (!press) { // release right mouse button
                            this->openPopupMenu(event->getPosition());
                        }
                    }
                }
            }
            // Alternative way of rotating & zooming
            if (press && (this->currentmode == NavigationStyle::PANNING ||
                          this->currentmode == NavigationStyle::ZOOMING)) {
                newmode = NavigationStyle::DRAGGING;
                this->centerTime = ev->getTime();
                processed = TRUE;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                if (tmp.getValue() < dci) {
                    newmode = NavigationStyle::ZOOMING;
                }
                processed = TRUE;
            }
            this->button2down = press;
            break;
        case SoMouseButtonEvent::BUTTON3:
            if (press) {
                this->centerTime = ev->getTime();
                float ratio = vp.getViewportAspectRatio();
                SbViewVolume vv = viewer->getCamera()->getViewVolume(ratio);
                this->panningplane = vv.getPlane(viewer->getCamera()->focalDistance.getValue());
                this->lockrecenter = FALSE;
            }
            else {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                // is it just a middle click?
                if (tmp.getValue() < dci && !this->lockrecenter) {
                    if (!this->lookAtPoint(pos)) {
                        panToCenter(panningplane, posn);
                        this->interactiveCountDec();
                    }
                    processed = TRUE;
                }
            }
            this->button3down = press;
            break;
        case SoMouseButtonEvent::BUTTON4:
            doZoom(viewer->getCamera(), TRUE, posn);
            processed = TRUE;
            break;
        case SoMouseButtonEvent::BUTTON5:
            doZoom(viewer->getCamera(), FALSE, posn);
            processed = TRUE;
            break;
        default:
            break;
        }
    }

    // Mouse Movement handling
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
        this->lockrecenter = TRUE;
        const SoLocation2Event * const event = (const SoLocation2Event *) ev;
        if (this->currentmode == NavigationStyle::ZOOMING) {
            this->zoomByCursor(posn, prevnormalized);
            processed = TRUE;
        }
        else if (this->currentmode == NavigationStyle::PANNING) {
            float ratio = vp.getViewportAspectRatio();
            panCamera(viewer->getCamera(), ratio, this->panningplane, posn, prevnormalized);
            processed = TRUE;
        }
        else if (this->currentmode == NavigationStyle::DRAGGING) {
            this->addToLog(event->getPosition(), event->getTime());
            this->spin(posn);
            processed = TRUE;
        }
    }

    // Spaceball & Joystick handling
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
        const SoMotion3Event * const event = static_cast<const SoMotion3Event * const>(ev);
        if (event)
            this->processMotionEvent(event);
        processed = TRUE;
    }

    enum {
        BUTTON1DOWN = 1 << 0,
        BUTTON3DOWN = 1 << 1,
        CTRLDOWN =    1 << 2,
        SHIFTDOWN =   1 << 3,
        BUTTON2DOWN = 1 << 4
    };
    unsigned int combo =
        (this->button1down ? BUTTON1DOWN : 0) |
        (this->button2down ? BUTTON2DOWN : 0) |
        (this->button3down ? BUTTON3DOWN : 0) |
        (this->ctrldown ? CTRLDOWN : 0) |
        (this->shiftdown ? SHIFTDOWN : 0);

    switch (combo) {
    case 0:
        if (curmode == NavigationStyle::SPINNING) { break; }
        newmode = NavigationStyle::IDLE;
        // The left mouse button has been released right now but
        // we want to avoid that the event is procesed elsewhere
        if (this->lockButton1) {
            this->lockButton1 = FALSE;
            processed = TRUE;
        }

        //if (curmode == NavigationStyle::DRAGGING) {
        //    if (doSpin())
        //        newmode = NavigationStyle::SPINNING;
        //}
        break;
    case BUTTON1DOWN:
        // make sure not to change the selection when stopping spinning
        if (curmode == NavigationStyle::SPINNING || this->lockButton1)
            newmode = NavigationStyle::IDLE;
        else
            newmode = NavigationStyle::SELECTION;
        break;
    case BUTTON3DOWN:
        if (curmode == NavigationStyle::SPINNING) { break; }
        else if (newmode == NavigationStyle::ZOOMING) { break; }
        newmode = NavigationStyle::PANNING;

        if (curmode == NavigationStyle::DRAGGING) {
            if (doSpin()) {
                newmode = NavigationStyle::SPINNING;
                break;
            }
        }
        break;
    case CTRLDOWN|BUTTON2DOWN:
        newmode = NavigationStyle::PANNING;
        break;
    case SHIFTDOWN|BUTTON2DOWN:
        newmode = NavigationStyle::DRAGGING;
        break;
    case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
        newmode = NavigationStyle::ZOOMING;
        break;
    //case CTRLDOWN:
    //case CTRLDOWN|BUTTON1DOWN:
    //case CTRLDOWN|SHIFTDOWN:
    //case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
    //    newmode = NavigationStyle::SELECTION;
    //    break;
    //case BUTTON1DOWN|BUTTON3DOWN:
    //case CTRLDOWN|BUTTON3DOWN:
    //    newmode = NavigationStyle::ZOOMING;
    //    break;

        // There are many cases we don't handle that just falls through to
        // the default case, like SHIFTDOWN, CTRLDOWN, CTRLDOWN|SHIFTDOWN,
        // SHIFTDOWN|BUTTON3DOWN, SHIFTDOWN|CTRLDOWN|BUTTON3DOWN, etc.
        // This is a feature, not a bug. :-)
        //
        // mortene.

    default:
        // The default will make a spin stop and otherwise not do
        // anything.
        //if ((curmode != NavigationStyle::SEEK_WAIT_MODE) &&
        //    (curmode != NavigationStyle::SEEK_MODE)) {
        //    newmode = NavigationStyle::IDLE;
        //}
        break;
    }

    if (newmode != curmode) {
        this->setViewingMode(newmode);
    }

    // If for dragging the buttons 1 and 3 are pressed
    // but then button 3 is relaesed we shouldn't switch
    // into selection mode.
    if (this->button1down && this->button3down)
        this->lockButton1 = TRUE;

    // If not handled in this class, pass on upwards in the inheritance
    // hierarchy.
    if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed)
        processed = inherited::processSoEvent(ev);
    else
        return TRUE;

    return processed;
}
SbBool OpenCascadeNavigationStyle::processSoEvent(const SoEvent * const ev)
{
    // Events when in "ready-to-seek" mode are ignored, except those
    // which influence the seek mode itself -- these are handled further
    // up the inheritance hierarchy.
    if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
    // Switch off viewing mode
    if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
        this->setViewing(false); // by default disable viewing mode to render the scene

    const SoType type(ev->getTypeId());

    const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
    const SbVec2s size(vp.getViewportSizePixels());
    const SbVec2f prevnormalized = this->lastmouseposition;
    const SbVec2s pos(ev->getPosition());
    const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1),
                       (float) pos[1] / (float) std::max((int)(size[1] - 1), 1));

    this->lastmouseposition = posn;

    // Set to true if any event processing happened. Note that it is not
    // necessary to restrict ourselves to only do one "action" for an
    // event, we only need this flag to see if any processing happened
    // at all.
    SbBool processed = false;

    const ViewerMode curmode = this->currentmode;
    ViewerMode newmode = curmode;

    // Mismatches in state of the modifier keys happens if the user
    // presses or releases them outside the viewer window.
    if (this->ctrldown != ev->wasCtrlDown()) {
        this->ctrldown = ev->wasCtrlDown();
    }
    if (this->shiftdown != ev->wasShiftDown()) {
        this->shiftdown = ev->wasShiftDown();
    }
    if (this->altdown != ev->wasAltDown()) {
        this->altdown = ev->wasAltDown();
    }

    // give the nodes in the foreground root the chance to handle events (e.g color bar)
    if (!processed && !viewer->isEditing()) {
        processed = handleEventInForeground(ev);
        if (processed)
            return true;
    }

    // Keyboard handling
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
        const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
        switch (event->getKey()) {
        case SoKeyboardEvent::LEFT_CONTROL:
        case SoKeyboardEvent::RIGHT_CONTROL:
            this->ctrldown = press;
            break;
        case SoKeyboardEvent::LEFT_SHIFT:
        case SoKeyboardEvent::RIGHT_SHIFT:
            this->shiftdown = press;
            break;
        case SoKeyboardEvent::LEFT_ALT:
        case SoKeyboardEvent::RIGHT_ALT:
            this->altdown = press;
            break;
        case SoKeyboardEvent::H:
            processed = true;
            viewer->saveHomePosition();
            break;
        case SoKeyboardEvent::S:
        case SoKeyboardEvent::HOME:
        case SoKeyboardEvent::LEFT_ARROW:
        case SoKeyboardEvent::UP_ARROW:
        case SoKeyboardEvent::RIGHT_ARROW:
        case SoKeyboardEvent::DOWN_ARROW:
            if (!this->isViewing())
                this->setViewing(true);
            break;
        default:
            break;
        }
    }

    // Mouse Button / Spaceball Button handling
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
        const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
        const int button = event->getButton();
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;

        switch (button) {
        case SoMouseButtonEvent::BUTTON1:
            this->lockrecenter = true;
            this->button1down = press;
            if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
                newmode = NavigationStyle::SEEK_MODE;
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
                processed = true;
            }
            else if (!press && (this->currentmode == NavigationStyle::ZOOMING)) {
                newmode = NavigationStyle::IDLE;
                processed = true;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                this->setViewing(false);
                processed = true;
            }
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
                processed = true;
            }
            break;
        case SoMouseButtonEvent::BUTTON2:
            // If we are in edit mode then simply ignore the RMB events
            // to pass the event to the base class.
            this->lockrecenter = true;
            if (!viewer->isEditing()) {
                // If we are in zoom or pan mode ignore RMB events otherwise
                // the canvas doesn't get any release events
                if (this->currentmode != NavigationStyle::ZOOMING &&
                    this->currentmode != NavigationStyle::PANNING &&
                    this->currentmode != NavigationStyle::DRAGGING) {
                    if (this->isPopupMenuEnabled()) {
                        if (!press) { // release right mouse button
                            this->openPopupMenu(event->getPosition());
                        }
                    }
                }
            }
            // Alternative way of rotating & zooming
            if (press && (this->currentmode == NavigationStyle::PANNING ||
                          this->currentmode == NavigationStyle::ZOOMING)) {
                newmode = NavigationStyle::DRAGGING;
                saveCursorPosition(ev);
                this->centerTime = ev->getTime();
                processed = true;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                newmode = NavigationStyle::IDLE;
                processed = true;
            }
            this->button2down = press;
            break;
        case SoMouseButtonEvent::BUTTON3:
            if (press) {
                this->centerTime = ev->getTime();
                float ratio = vp.getViewportAspectRatio();
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
                this->lockrecenter = false;
            }
            else if (!press && (this->currentmode == NavigationStyle::PANNING)) {
                newmode = NavigationStyle::IDLE;
                processed = true;
            }
            this->button3down = press;
            break;
        case SoMouseButtonEvent::BUTTON4:
        case SoMouseButtonEvent::BUTTON5:
            doZoom(viewer->getSoRenderManager()->getCamera(), button == SoMouseButtonEvent::BUTTON4, posn);
            processed = true;
            break;
        default:
            break;
        }
    }

    enum {
        BUTTON1DOWN = 1 << 0,
        BUTTON3DOWN = 1 << 1,
        CTRLDOWN =    1 << 2,
        SHIFTDOWN =   1 << 3,
        BUTTON2DOWN = 1 << 4
    };
    unsigned int combo =
        (this->button1down ? BUTTON1DOWN : 0) |
        (this->button2down ? BUTTON2DOWN : 0) |
        (this->button3down ? BUTTON3DOWN : 0) |
        (this->ctrldown ? CTRLDOWN : 0) |
        (this->shiftdown ? SHIFTDOWN : 0);

    // Mouse Movement handling
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
        this->lockrecenter = true;
        const SoLocation2Event * const event = (const SoLocation2Event *) ev;
        if (this->currentmode == NavigationStyle::ZOOMING) {
            // OCCT uses horizontal mouse position, not vertical
            // this->zoomByCursor(posn, prevnormalized);
            float value = (posn[0] - prevnormalized[0]) * 10.0f;
            if (this->invertZoom)
                value = -value;
            zoom(viewer->getSoRenderManager()->getCamera(), value);
            processed = true;
        }
        else if (this->currentmode == NavigationStyle::PANNING) {
            float ratio = vp.getViewportAspectRatio();
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
            processed = true;
        }
        else if (this->currentmode == NavigationStyle::DRAGGING) {
            this->addToLog(event->getPosition(), event->getTime());
            this->spin(posn);
            moveCursorPosition();
            processed = true;
        }
        else if (combo == (CTRLDOWN|BUTTON1DOWN)) {
            newmode = NavigationStyle::ZOOMING;
        }
    }

    // Spaceball & Joystick handling
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
        const SoMotion3Event * const event = static_cast<const SoMotion3Event * const>(ev);
        if (event)
            this->processMotionEvent(event);
        processed = true;
    }

    switch (combo) {
    case 0:
        if (curmode == NavigationStyle::SPINNING) { break; }
        newmode = NavigationStyle::IDLE;
        break;
    case CTRLDOWN|BUTTON1DOWN:
    case BUTTON1DOWN:
        if (newmode != NavigationStyle::ZOOMING)
            newmode = NavigationStyle::SELECTION;
        break;
    case CTRLDOWN|BUTTON3DOWN:
    case BUTTON3DOWN:
        newmode = NavigationStyle::PANNING;
        break;
    case CTRLDOWN|BUTTON2DOWN:
        newmode = NavigationStyle::DRAGGING;
        break;
    case BUTTON2DOWN:
        newmode = NavigationStyle::IDLE;
        break;
    default:
        break;
    }

    if (newmode != curmode) {
        this->setViewingMode(newmode);
    }

    // If not handled in this class, pass on upwards in the inheritance
    // hierarchy.
    if (/*(curmode == NavigationStyle::SELECTION || viewer->isEditing()) && */!processed)
        processed = inherited::processSoEvent(ev);
    else
        return true;

    return processed;
}
SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
{
    // Events when in "ready-to-seek" mode are ignored, except those
    // which influence the seek mode itself -- these are handled further
    // up the inheritance hierarchy.
    if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
    // Switch off viewing mode (Bug #0000911)
    if (!this->isSeekMode()&& !this->isAnimating() && this->isViewing() )
        this->setViewing(false); // by default disable viewing mode to render the scene

    const SoType type(ev->getTypeId());

    const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
    const SbVec2s size(vp.getViewportSizePixels());
    const SbVec2f prevnormalized = this->lastmouseposition;
    const SbVec2s pos(ev->getPosition());
    const SbVec2f posn((float) pos[0] / (float) std::max((int)(size[0] - 1), 1),
                       (float) pos[1] / (float) std::max((int)(size[1] - 1), 1));

    this->lastmouseposition = posn;

    // Set to true if any event processing happened. Note that it is not
    // necessary to restrict ourselves to only do one "action" for an
    // event, we only need this flag to see if any processing happened
    // at all.
    SbBool processed = false;

    const ViewerMode curmode = this->currentmode;
    ViewerMode newmode = curmode;

    // Mismatches in state of the modifier keys happens if the user
    // presses or releases them outside the viewer window.
    if (this->ctrldown != ev->wasCtrlDown()) {
        this->ctrldown = ev->wasCtrlDown();
    }
    if (this->shiftdown != ev->wasShiftDown()) {
        this->shiftdown = ev->wasShiftDown();
    }
    if (this->altdown != ev->wasAltDown()) {
        this->altdown = ev->wasAltDown();
    }

    // give the nodes in the foreground root the chance to handle events (e.g color bar)
    if (!viewer->isEditing()) {
        processed = handleEventInForeground(ev);
        if (processed)
            return true;
    }

    // Keyboard handling
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
        const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
        switch (event->getKey()) {
        case SoKeyboardEvent::LEFT_CONTROL:
        case SoKeyboardEvent::RIGHT_CONTROL:
            this->ctrldown = press;
            break;
        case SoKeyboardEvent::LEFT_SHIFT:
        case SoKeyboardEvent::RIGHT_SHIFT:
            this->shiftdown = press;
            break;
        case SoKeyboardEvent::LEFT_ALT:
        case SoKeyboardEvent::RIGHT_ALT:
            this->altdown = press;
            break;
        case SoKeyboardEvent::H:
            processed = true;
            viewer->saveHomePosition();
            break;
        case SoKeyboardEvent::S:
        case SoKeyboardEvent::HOME:
        case SoKeyboardEvent::LEFT_ARROW:
        case SoKeyboardEvent::UP_ARROW:
        case SoKeyboardEvent::RIGHT_ARROW:
        case SoKeyboardEvent::DOWN_ARROW:
            if (!this->isViewing())
                this->setViewing(true);
            break;
        default:
            break;
        }
    }

    // Mouse Button / Spaceball Button handling
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
        const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
        const int button = event->getButton();
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;

        // SoDebugError::postInfo("processSoEvent", "button = %d", button);
        switch (button) {
        case SoMouseButtonEvent::BUTTON1:
            this->button1down = press;
            if (press && ev->wasShiftDown() &&
                (this->currentmode != NavigationStyle::SELECTION)) {
                this->centerTime = ev->getTime();
                float ratio = vp.getViewportAspectRatio();
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
                this->lockrecenter = false;
            }
            else if (!press && ev->wasShiftDown() &&
                (this->currentmode != NavigationStyle::SELECTION)) {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                // is it just a left click?
                if (tmp.getValue() < dci && !this->lockrecenter) {
                    if (!this->lookAtPoint(pos)) {
                        panToCenter(panningplane, posn);
                        this->interactiveCountDec();
                    }
                    processed = true;
                }
            }
            else if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
                newmode = NavigationStyle::SEEK_MODE;
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
                processed = true;
                this->lockrecenter = true;
            }
            else if (press && (this->currentmode == NavigationStyle::IDLE)) {
                this->setViewing(true);
                processed = true;
                this->lockrecenter = true;
            }
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
                this->setViewing(false);
                processed = true;
                this->lockrecenter = true;
            }
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
                processed = true;
                this->lockrecenter = true;
            }
            // issue #0002433: avoid to swallow the UP event if down the
            // scene graph somewhere a dialog gets opened
            else if (press) {
                SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime());
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                // a double-click?
                if (tmp.getValue() < dci) {
                    mouseDownConsumedEvent = *event;
                    mouseDownConsumedEvent.setTime(ev->getTime());
                    processed = true;
                }
                else {
                    mouseDownConsumedEvent.setTime(ev->getTime());
                    // 'ANY' is used to mark that we don't know yet if it will
                    // be a double-click event.
                    mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY);
                }
            }
            else if (!press) {
                if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) {
                    // now handle the postponed event
                    inherited::processSoEvent(&mouseDownConsumedEvent);
                    mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY);
                }
            }
            break;
        case SoMouseButtonEvent::BUTTON2:
            // If we are in edit mode then simply ignore the RMB events
            // to pass the event to the base class.
            this->lockrecenter = true;
            if (!viewer->isEditing()) {
                // If we are in zoom or pan mode ignore RMB events otherwise
                // the canvas doesn't get any release events 
                if (this->currentmode != NavigationStyle::ZOOMING && 
                    this->currentmode != NavigationStyle::PANNING) {
                    if (this->isPopupMenuEnabled()) {
                        if (!press) { // release right mouse button
                            this->openPopupMenu(event->getPosition());
                        }
                    }
                }
            }
            this->button2down = press;
            break;
        case SoMouseButtonEvent::BUTTON3:
            if (press) {
                this->centerTime = ev->getTime();
                float ratio = vp.getViewportAspectRatio();
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
                this->lockrecenter = false;
            }
            else {
                SbTime tmp = (ev->getTime() - this->centerTime);
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
                // is it just a middle click?
                if (tmp.getValue() < dci && !this->lockrecenter) {
                    if (!this->lookAtPoint(pos)) {
                        panToCenter(panningplane, posn);
                        this->interactiveCountDec();
                    }
                    processed = true;
                }
            }
            this->button3down = press;
            break;
        case SoMouseButtonEvent::BUTTON4:
            doZoom(viewer->getSoRenderManager()->getCamera(), true, posn);
            processed = true;
            break;
        case SoMouseButtonEvent::BUTTON5:
            doZoom(viewer->getSoRenderManager()->getCamera(), false, posn);
            processed = true;
            break;
        default:
            break;
        }
    }

    // Mouse Movement handling
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
        this->lockrecenter = true;
        const SoLocation2Event * const event = (const SoLocation2Event *) ev;
        if (this->currentmode == NavigationStyle::ZOOMING) {
            this->zoomByCursor(posn, prevnormalized);
            processed = true;
        }
        else if (this->currentmode == NavigationStyle::PANNING) {
            float ratio = vp.getViewportAspectRatio();
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
            processed = true;
        }
        else if (this->currentmode == NavigationStyle::DRAGGING) {
            this->addToLog(event->getPosition(), event->getTime());
            this->spin(posn);
            moveCursorPosition();
            processed = true;
        }
    }

    // Spaceball & Joystick handling
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
        const SoMotion3Event * const event = static_cast<const SoMotion3Event *>(ev);
        if (event)
            this->processMotionEvent(event);
        processed = true;
    }

    enum {
        BUTTON1DOWN = 1 << 0,
        BUTTON3DOWN = 1 << 1,
        CTRLDOWN =    1 << 2,
        SHIFTDOWN =   1 << 3,
        BUTTON2DOWN = 1 << 4
    };
    unsigned int combo =
        (this->button1down ? BUTTON1DOWN : 0) |
        (this->button2down ? BUTTON2DOWN : 0) |
        (this->button3down ? BUTTON3DOWN : 0) |
        (this->ctrldown ? CTRLDOWN : 0) |
        (this->shiftdown ? SHIFTDOWN : 0);

    switch (combo) {
    case 0:
        if (curmode == NavigationStyle::SPINNING) { break; }
        newmode = NavigationStyle::IDLE;

        if (curmode == NavigationStyle::DRAGGING) {
            if (doSpin())
                newmode = NavigationStyle::SPINNING;
        }
        break;
    case BUTTON1DOWN:
        if (newmode != NavigationStyle::DRAGGING) {
            saveCursorPosition(ev);
        }
        newmode = NavigationStyle::DRAGGING;
        break;
    case BUTTON3DOWN:
    case CTRLDOWN|SHIFTDOWN:
    case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
        newmode = NavigationStyle::PANNING;
        break;
    case CTRLDOWN:
    case CTRLDOWN|BUTTON1DOWN:
    case SHIFTDOWN:
    case SHIFTDOWN|BUTTON1DOWN:
        newmode = NavigationStyle::SELECTION;
        break;
    case BUTTON1DOWN|BUTTON3DOWN:
    case CTRLDOWN|BUTTON3DOWN:
    case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
        newmode = NavigationStyle::ZOOMING;
        break;

        // There are many cases we don't handle that just falls through to
        // the default case, like SHIFTDOWN, CTRLDOWN, CTRLDOWN|SHIFTDOWN,
        // SHIFTDOWN|BUTTON3DOWN, SHIFTDOWN|CTRLDOWN|BUTTON3DOWN, etc.
        // This is a feature, not a bug. :-)
        //
        // mortene.

    default:
        // The default will make a spin stop and otherwise not do
        // anything.
        if ((curmode != NavigationStyle::SEEK_WAIT_MODE) &&
            (curmode != NavigationStyle::SEEK_MODE)) {
            newmode = NavigationStyle::IDLE;
        }
        break;
    }

    if (newmode != curmode) {
        this->setViewingMode(newmode);
    }

    // If not handled in this class, pass on upwards in the inheritance
    // hierarchy.
    if ((curmode == NavigationStyle::SELECTION ||
         newmode == NavigationStyle::SELECTION ||
         viewer->isEditing()) && !processed)
        processed = inherited::processSoEvent(ev);
    else
        return true;

    return processed;
}