Ejemplo n.º 1
0
////////////////////////////////////////////////////////////////////////
//
// Update the matrix transform so that our cube fits the bbox of the
// passed path.
//
// Use: protected
//
void
SoBoxHighlightRenderAction::updateBbox(SoPath *p)
//
////////////////////////////////////////////////////////////////////////
{
    static SoGetBoundingBoxAction *bba = NULL;
    if (bba == NULL)
        bba = new SoGetBoundingBoxAction(getViewportRegion());    
    else
        bba->setViewportRegion( getViewportRegion());    
    bba->apply(p);    
    SbXfBox3f &box = bba->getXfBoundingBox();
    
    // Scale the cube to the correct size
    if (box.isEmpty()) {
	cube->width  = 0;
	cube->height = 0;
	cube->depth  = 0;
    }
    else {
	float x, y, z;
	box.getSize(x, y, z);
	cube->width  = x;
	cube->height = y;
	cube->depth  = z;
    }
    
    // Setup the matrix transform
    xform->matrix = box.getTransform();

    // If the bounding box is not centered at the origin, we have to
    // move the cube to the correct place. (To make the check, treat
    // the box as an SbBox3f, since we don't want the transformed
    // center.)
    const SbVec3f &min = ((SbBox3f &) box).getMin();
    const SbVec3f &max = ((SbBox3f &) box).getMax();
    if (min[0] != -max[0] || min[1] != -max[1] || min[2] != -max[2]) {
	xlate->translation.setValue(
	    (min[0] + max[0]) * .5, 
	    (min[1] + max[1]) * .5, 
	    (min[2] + max[2]) * .5);
	xlate->translation.setIgnored(FALSE);
    }
    else {
	// Translation field is not needed - data is centered about 0,0,0
	// and so is the cube.
	xlate->translation.setIgnored(TRUE);
    }
    
}
    void rotateCamera(const SbRotation &rot)
    {
        SoCamera * camera = viewer->getCamera();

        // get center of rotation
        const float radius = camera->focalDistance.getValue();

        SbVec3f forward;
        camera->orientation.getValue().multVec(SbVec3f(0,0,-1), forward);

        const SbVec3f center = camera->position.getValue() + radius * forward;

        // apply new rotation to the camera
        camera->orientation = rot * camera->orientation.getValue();

        // reposition camera to look at pt of interest
        camera->orientation.getValue().multVec(SbVec3f(0,0,-1), forward);
        camera->position = center - radius * forward;

        headlightRot->rotation = camera->orientation.getValue();

        // Adjust clipping planes
        SoGetBoundingBoxAction clipbox_action(getViewportRegion());
        clipbox_action.apply(viewer->getSceneRoot());

        SbBox3f bbox = clipbox_action.getBoundingBox();

        if (bbox.isEmpty())
            return;

        SbSphere bSphere;
        bSphere.circumscribe(bbox);

        float denumerator = forward.length();
        float numerator = (bSphere.getCenter() - camera->position.getValue()).dot(forward);
        float distToCenter = (forward * (numerator / denumerator)).length();

        float farplane = distToCenter + bSphere.getRadius();

        // if scene is behind the camera, don't change the planes
        if (farplane < 0) return;

        float nearplane = distToCenter - bSphere.getRadius();

        if (nearplane < (0.001 * farplane)) nearplane = 0.001 * farplane;

        camera->nearDistance = nearplane;
        camera->farDistance = farplane;
    }
    /// Override original method since it seems to adjust the clipping planes in a weird manner.
    /// Maybe using a screen-space projection or whatever.
    virtual void adjustCameraClippingPlanes()
    {
        SoCamera * camera = getCamera();
        if (!camera)
            return;

        SoGetBoundingBoxAction clipbox_action(getViewportRegion());
        clipbox_action.apply(getSceneRoot());

        SbBox3f bbox = clipbox_action.getBoundingBox();

        if (bbox.isEmpty())
            return;

        SbSphere bSphere;
        bSphere.circumscribe(bbox);

        SbVec3f forward;
        camera->orientation.getValue().multVec(SbVec3f(0,0,-1), forward);

        float denumerator = forward.length();
        float numerator = (bSphere.getCenter() - camera->position.getValue()).dot(forward);
        float distToCenter = (forward * (numerator / denumerator)).length();

        float farplane = distToCenter + bSphere.getRadius();

        // if scene is behind the camera, don't change the planes
        if (farplane < 0) return;

        float nearplane = distToCenter - bSphere.getRadius();

        if (nearplane < (0.001 * farplane)) nearplane = 0.001 * farplane;

        camera->nearDistance = nearplane;
        camera->farDistance = farplane;
    }
Ejemplo n.º 4
0
////////////////////////////////////////////////////////////////////////
//
// Description:
//   This routine sets the limitBox. 
// The limit box is defined in a space aligned and scaled as 
// LOCAL space, but with it's center remaining fixed in WORLD 
// space.
//
// Use: static private
//
void
SoDragPointDragger::updateLimitBoxAndFeedback()
//
////////////////////////////////////////////////////////////////////////
{
    // This gets called in the constructor, while the ref count is still 0.
    // Since there will be some ref'ing and unref'ing done inside here,
    // add a temporary ref and undo it at the end.
    ref();

    if ( xFeedback.getValue() != oldXAxisNode ||
	 yFeedback.getValue() != oldYAxisNode ||
	 zFeedback.getValue() != oldZAxisNode ) {

	oldXAxisNode = SO_GET_ANY_PART(this,"xFeedback",SoSeparator);
	oldYAxisNode = SO_GET_ANY_PART(this,"yFeedback",SoSeparator);
	oldZAxisNode = SO_GET_ANY_PART(this,"zFeedback",SoSeparator);

	// Get the bounds of the axis parts. 
	static SoGetBoundingBoxAction *bba = NULL;
	if (bba == NULL)
	    bba = new SoGetBoundingBoxAction(getViewportRegion());
	else
	    bba->setViewportRegion(getViewportRegion());

	float   xMin, yMin, zMin, xMax, yMax, zMax;
	SbVec3f min, max;

	bba->apply(xFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[0] = xMin;
	max[0] = xMax;

	bba->apply(yFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[1] = yMin; 
	max[1] = yMax; 

	bba->apply(zFeedback.getValue());
	bba->getBoundingBox().getBounds( xMin, yMin, zMin, xMax, yMax, zMax );
	min[2] = zMin;
	max[2] = zMax;

	// The limit box is defined in a space aligned and scaled as 
	// LOCAL space, but with it's center remaining fixed in WORLD 
	// space.

	SbVec3f newDiag = (max - min) / 2.0;

	// Give a default size of 1, in case no axis parts exist.
	for (int i = 0; i < 3; i++) {
	    if (newDiag[i] <= getMinScale())
		newDiag[i] = 1.0;
	}

	SbVec3f oldDiag = limitBox.getMax() - 
			  limitBox.getCenter();

	// If the size of the boundingBox has changed...
	if ( newDiag != oldDiag ) {

	    // curEdit point needs to be the current origin expressed in world
	    // space (i.e., this bizarro space).
	    SbMatrix localToWorld = getLocalToWorldMatrix();

	    SbVec3f zeroPt(0,0,0);
	    localToWorld.multVecMatrix( zeroPt, zeroPt );

	    limitBox.setBounds(zeroPt - newDiag, zeroPt + newDiag );
	}
    }

    setFeedbackGeometry();

    // undo the temporary ref.
    unrefNoDelete();
}
    virtual void apply(SoNode* node)
    {
        if (!headlightRot) {
            SoSearchAction sa;
            sa.setNode(viewer->getHeadlight());
            sa.apply(viewer->getSceneRoot());
            SoFullPath* fullPath = (SoFullPath*) sa.getPath();
            if (fullPath) {
                SoGroup *group = (SoGroup*) fullPath->getNodeFromTail(1);
                headlightRot = (SoRotation*) group->getChild(0);
                if (!headlightRot->isOfType(SoRotation::getClassTypeId()))
                    headlightRot = 0;
            }
        }

        const SbViewportRegion vpr = getViewportRegion();
        const SbVec2s & size = vpr.getViewportSizePixels();

        const int width = size[0];
        const int height = size[1];

        const int vpsize = width / 2;

        SoCamera * camera = viewer->getCamera();

        const SbVec3f position = camera->position.getValue();
        const SbRotation orientation = camera->orientation.getValue();
        const float nearplane = camera->nearDistance.getValue();
        const float farplane = camera->farDistance.getValue();

        camera->enableNotify(false);

        // Front View
        rotateCamera(SbRotation(SbVec3f(0,0,1), M_PI));

        SbViewportRegion vp;
        vp.setViewportPixels(SbVec2s(0, height-width/2), SbVec2s(width, width/2) );
        setViewportRegion(vp);

        SoGLRenderAction::apply(node);

        // Left View
        SbRotation r1(SbVec3f(0,0,1), -M_PI/2);

        rotateCamera(r1*SbRotation(SbVec3f(0,1,0), -M_PI/2));
        
        vp.setViewportPixels(SbVec2s(0, height-width), SbVec2s(width/2, width) );
        setViewportRegion(vp);

        SoGLRenderAction::apply(node);

        // Right View
        rotateCamera(SbRotation(SbVec3f(0,1,0), -M_PI));

        vp.setViewportPixels(SbVec2s(width/2, height-width), SbVec2s(width/2, width) );
        setViewportRegion(vp);

        SoGLRenderAction::apply(node);

        setViewportRegion(vpr);

        camera->position = position;
        camera->orientation = orientation;
        camera->enableNotify(true);

        // Restore original viewport region
        setViewportRegion(vpr);
    }