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;
    }
// Doc in superclass.
void
SoOrthographicCamera::viewBoundingBox(const SbBox3f & box,
                                      float aspect, float slack)
{
#if COIN_DEBUG
  if (box.isEmpty()) {
    SoDebugError::postWarning("SoOrthographicCamera::viewBoundingBox",
                              "bounding box empty");
    return;
  }
#endif // COIN_DEBUG

  // Get the radius of the bounding sphere.
  SbSphere bs;
  bs.circumscribe(box);
  float radius = bs.getRadius();

  // We want to move the camera in such a way that it is pointing
  // straight at the center of the scene bounding box -- but without
  // modifiying the rotation value (so we can't use SoCamera::pointAt()),
  // and positioned at the edge of the bounding sphere.
  SbVec3f cameradirection;
  this->orientation.getValue().multVec(SbVec3f(0, 0, -1), cameradirection);
  this->position.setValue(box.getCenter() + cameradirection * -radius);

  // Set up the clipping planes tangent to the bounding sphere of the scene.
  this->nearDistance = radius * ( -slack + 1);
  this->farDistance = radius * ( slack + 1);

  // The focal distance is simply the distance from the camera to the
  // scene midpoint. This field is not used in rendering, its just
  // provided to make it easier for the user to do calculations based
  // on the distance between the camera and the scene.
  this->focalDistance = radius;

  // Make sure that everything will still be inside the viewing volume
  // even if the aspect ratio "favorizes" width over height, and take the
  // slack factor into account.
  if (aspect < 1.0f)
    this->height = 2 * radius / aspect;
  else
    this->height = 2 * radius;
}
Beispiel #3
0
void Command::adjustCameraPosition()
{
    Gui::Document* doc = Gui::Application::Instance->activeDocument();
    if (doc) {
        Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(doc->getActiveView());
        Gui::View3DInventorViewer* viewer = view->getViewer();
        SoCamera* camera = viewer->getSoRenderManager()->getCamera();
        if (!camera || !camera->isOfType(SoOrthographicCamera::getClassTypeId()))
            return;

        // get scene bounding box
        SoGetBoundingBoxAction action(viewer->getSoRenderManager()->getViewportRegion());
        action.apply(viewer->getSceneGraph());
        SbBox3f box = action.getBoundingBox();
        if (box.isEmpty()) return;

        // get cirumscribing sphere and check if camera is inside
        SbVec3f cam_pos = camera->position.getValue();
        SbVec3f box_cnt = box.getCenter();
        SbSphere bs;
        bs.circumscribe(box);
        float radius = bs.getRadius();
        float distance_to_midpoint = (box_cnt-cam_pos).length();
        if (radius >= distance_to_midpoint) {
            // Move the camera to the edge of the bounding sphere, while still
            // pointing at the scene.
            SbVec3f direction = cam_pos - box_cnt;
            (void) direction.normalize(); // we know this is not a null vector
            camera->position.setValue(box_cnt + direction * radius);

            // New distance to mid point
            distance_to_midpoint =
                (camera->position.getValue() - box.getCenter()).length();
            camera->nearDistance = distance_to_midpoint - radius;
            camera->farDistance = distance_to_midpoint + radius;
            camera->focalDistance = distance_to_midpoint;
        }
    }
}
    /// 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;
    }