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; }
// 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; }
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; } } }