// Doc in parent void SoVRMLCone::computeBBox(SoAction * COIN_UNUSED_ARG(action), SbBox3f & box, SbVec3f & center) { float r = this->bottomRadius.getValue(); float h = this->height.getValue(); // Allow negative values. if (h < 0.0f) h = -h; if (r < 0.0f) r = -r; float half_height = h * 0.5f; // The SIDES are present, so just find the middle point and enclose // everything. if (this->side.getValue()) { center.setValue(0.0f, 0.0f, 0.0f); box.setBounds(SbVec3f(-r, -half_height, -r), SbVec3f(r, half_height, r)); } // ..no SIDES, but we've still got the bottom (NB: OIV misses this case). else if (this->bottom.getValue()) { center.setValue(0.0f, -half_height, 0.0f); box.setBounds(SbVec3f(-r, -half_height, -r), SbVec3f(r, -half_height, r)); } // ..no parts present. My confidence is shot -- I feel very small. else { center.setValue(0.0f, 0.0f, 0.0f); box.setBounds(SbVec3f(0.0f, 0.0f, 0.0f), SbVec3f(0.0f, 0.0f, 0.0f)); } }
// This is a helper function for debugging purposes: it sets up an // SoCoordinate3 + SoIndexedLineSet pair of nodes exposing the // geometry of the SbBox3f input argument. static void make_scene_graph(const SbBox3f & box, SoCoordinate3 *& coord3, SoIndexedLineSet *& ils) { const SbVec3f & vmin = box.getMin(); const SbVec3f & vmax = box.getMax(); const SbVec3f corners[] = { // back face SbVec3f(vmin[0], vmin[1], vmin[2]), SbVec3f(vmax[0], vmin[1], vmin[2]), SbVec3f(vmax[0], vmax[1], vmin[2]), SbVec3f(vmin[0], vmax[1], vmin[2]), // front face SbVec3f(vmin[0], vmin[1], vmax[2]), SbVec3f(vmax[0], vmin[1], vmax[2]), SbVec3f(vmax[0], vmax[1], vmax[2]), SbVec3f(vmin[0], vmax[1], vmax[2]) }; const int32_t indices[] = { 0, 1, 2, 3, 0, -1, // back face 4, 5, 6, 7, 4, -1, // front face 0, 4, -1, 1, 5, -1, 2, 6, -1, 3, 7, -1 // "crossover" lines }; coord3 = new SoCoordinate3; coord3->point.setValues(0, sizeof(corners) / sizeof(corners[0]), corners); ils = new SoIndexedLineSet; ils->coordIndex.setValues(0, sizeof(indices) / sizeof(indices[0]), indices); }
// doc in super void SoOrthoSlice::computeBBox(SoAction * action, SbBox3f & box, SbVec3f & center) { SoState * state = action->getState(); if (!PRIVATE(this)->confirmValidInContext(state)) { return; } const CvrVoxelBlockElement * vbelem = CvrVoxelBlockElement::getInstance(state); if (vbelem == NULL) return; SbBox3f vdbox = vbelem->getUnitDimensionsBox(); SbVec3f bmin, bmax; vdbox.getBounds(bmin, bmax); const SbVec3s & dimensions = vbelem->getVoxelCubeDimensions(); const int axisidx = (int)axis.getValue(); const int slice = this->sliceNumber.getValue(); const float depth = (float)fabs(bmax[axisidx] - bmin[axisidx]); bmin[axisidx] = bmax[axisidx] = (bmin[axisidx] + (depth / dimensions[axisidx]) * slice); vdbox.setBounds(bmin, bmax); box.extendBy(vdbox); center = vdbox.getCenter(); }
void SoCylinder::computeBBox(SoAction *, SbBox3f &box, SbVec3f ¢er) // //////////////////////////////////////////////////////////////////////// { int curParts = (parts.isIgnored() ? ALL : parts.getValue()); if (curParts == 0) // No parts at all! box.setBounds(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); else { float r, h; SbVec3f min, max; getSize(r, h); if (HAS_PART(curParts, SIDES | TOP)) max.setValue( r, h, r); else max.setValue( r, -h, r); if (HAS_PART(curParts, SIDES | BOTTOM)) min.setValue(-r, -h, -r); else min.setValue(-r, h, -r); box.setBounds(min, max); } center.setValue(0.0, 0.0, 0.0); }
/** * Sets the bounding box of the mesh to \a box and its center to \a center. */ void SoPolygon::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) { SoState* state = action->getState(); const SoCoordinateElement * coords = SoCoordinateElement::getInstance(state); if (!coords) return; const SbVec3f * points = coords->getArrayPtr3(); if (!points) return; float maxX=-FLT_MAX, minX=FLT_MAX, maxY=-FLT_MAX, minY=FLT_MAX, maxZ=-FLT_MAX, minZ=FLT_MAX; int32_t len = coords->getNum(); int32_t beg = startIndex.getValue(); int32_t cnt = numVertices.getValue(); int32_t end = beg + cnt; if (end <= len) { for (int32_t i=beg; i<end; i++) { maxX = std::max<float>(maxX,points[i][0]); minX = std::min<float>(minX,points[i][0]); maxY = std::max<float>(maxY,points[i][1]); minY = std::min<float>(minY,points[i][1]); maxZ = std::max<float>(maxZ,points[i][2]); minZ = std::min<float>(minZ,points[i][2]); } box.setBounds(minX,minY,minZ,maxX,maxY,maxZ); center.setValue(0.5f*(minX+maxX),0.5f*(minY+maxY),0.5f*(minZ+maxZ)); } else { box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0)); center.setValue(0.0f,0.0f,0.0f); } }
SbBox3f ViewProviderDatum::getRelevantBoundBox () const { std::vector<App::DocumentObject *> objs; // Probe body first PartDesign::Body* body = PartDesign::Body::findBodyOf ( this->getObject() ); if (body) { objs = body->getFullModel (); } else { // Probe if we belongs to some group App::DocumentObjectGroup* group = App::DocumentObjectGroup::getGroupOfObject ( this->getObject () ); if(group) { objs = group->getObjects (); } else { // Fallback to whole document objs = this->getObject ()->getDocument ()->getObjects (); } } Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(this->getActiveView())->getViewer(); SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion()); SbBox3f bbox = getRelevantBoundBox (bboxAction, objs); if ( bbox.getVolume () < Precision::Confusion() ) { bbox.extendBy ( defaultBoundBox () ); } return bbox; }
// Expand SbXfBox3f in all directions with an epsilon value. static SbXfBox3f expand_SbXfBox3f(const SbXfBox3f & box, float epsilon) { assert(epsilon > 0.0f); // FIXME: quality check the calculation for the epsilon-extended // bbox. It needs to be correct _and_ not adding on too much // fat. 20030331 mortene. // This invokes the copy constructor (and not the SbXfBox3f(SbBox3f) // constructor), so the transformation matrix is also copied. SbXfBox3f extbox(box); SbVec3f epsilonvec(epsilon, epsilon, epsilon); // Move epsilon to object space. box.getTransform().multDirMatrix(epsilonvec, epsilonvec); const float localepsilon = epsilonvec.length(); // yes, it's a bit large... epsilonvec = SbVec3f(localepsilon, localepsilon, localepsilon); // Get superclass-pointer, so we can modify the box corners // directly. SbBox3f * extboxp = static_cast<SbBox3f *>(&extbox); extboxp->getMin() -= epsilonvec; extboxp->getMax() += epsilonvec; return extbox; }
void SbSphere::circumscribe(const SbBox3f &box) // ////////////////////////////////////////////////////////////////////////////// { center = 0.5 * (box.getMin() + box.getMax()); radius = (box.getMax() - center).length(); }
void SoNurbsSurface::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) // //////////////////////////////////////////////////////////////////////// { const SoCoordinateElement *ce = SoCoordinateElement::getInstance(action->getState()); int32_t nCoords, numSurfCoords; int j, curCoord; SbVec3f tmpCoord; // // Loop through coordinates, keeping max bounding box and sum of coords // If the coordinates are rational, divide the first three values by // the fourth value before extending the bounding box. // numSurfCoords = numUControlPoints.getValue() * numVControlPoints.getValue(); nCoords = ce->getNum(); // Check for a degenerate surface if ((numSurfCoords == 0) || (nCoords == 0)) return; curCoord = 0; center.setValue(0.0, 0.0, 0.0); if (ce->is3D()) { for (j = 0; j < numSurfCoords; j++) { // // Wrap around if necessary // if (curCoord >= nCoords) curCoord = 0; const SbVec3f &coord = ce->get3(curCoord); box.extendBy(coord); center += coord; curCoord++; } } else { for (j = 0; j < numSurfCoords; j++) { // // Wrap around if necessary // if (curCoord >= nCoords) curCoord = 0; const SbVec4f &coord = ce->get4(curCoord); coord.getReal (tmpCoord); box.extendBy (tmpCoord); center += tmpCoord; curCoord++; } } center /= (float) numSurfCoords; }
void IvDragger::_GetBounds(SoSeparator *subtree, AABB& ab) { SoGetBoundingBoxAction bbox(_viewer.lock()->GetViewer()->getViewportRegion()); bbox.apply(subtree); SbBox3f box = bbox.getBoundingBox(); RaveVector<float> vmin, vmax; box.getBounds(vmin.x,vmin.y,vmin.z,vmax.x,vmax.y,vmax.z); ab.pos = 0.5*(vmin+vmax); ab.extents = 0.5*(vmax-vmin); }
void ShapeBezierSurface::computeBBox(SoAction*, SbBox3f& box, SbVec3f& /*center*/ ) { box.makeEmpty(); for (int i = 0; i < m_surfacesVector.size(); i++) { BBox pBox = m_surfacesVector[i]->GetComputeBBox(); SbVec3f pMin( pBox.pMin[0], pBox.pMin[1], pBox.pMin[2] ); box.extendBy( pMin ); SbVec3f pMax( pBox.pMax[0], pBox.pMax[1], pBox.pMax[2] ); box.extendBy( pMax ); } }
void SoVtkAssembly::getBoundingBox(SoGetBoundingBoxAction *action) { SbBox3f bbox; SbVec3f center; if (mAssembly) { const double *bounds = mAssembly->GetBounds(); SbBox3f bbox(bounds[0], bounds[2], bounds[4], bounds[1], bounds[3], bounds[5]); action->extendBy(bbox); action->setCenter(bbox.getCenter(), FALSE); } }
void SoXipMarkerSet::computeBBox( SoAction* action, SbBox3f& box, SbVec3f& center ) { const SoCoordinateElement* ce = (const SoCoordinateElement *) SoCoordinateElement::getInstance( action->getState() ); if( ce ) { for( int i = 0; i < ce->getNum(); ++ i ) box.extendBy( ce->get3(i) ); } center = box.getCenter(); }
// set scale void InvAnnoManager::setSize(const SbBox3f &bb) { float dx = fabs(bb.getMin()[0] - bb.getMax()[0]); float dy = fabs(bb.getMin()[1] - bb.getMax()[1]); float dz = fabs(bb.getMin()[2] - bb.getMax()[2]); float hsc = max(dx, dy); hsc = max(hsc, dz); hsc *= 0.2; scale_ = hsc; }
/** * Sets the bounding box of the probe to \a box and its center to \a center. */ void SoRegPoint::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) { root->doAction(action); if (action->getTypeId().isDerivedFrom(SoGetBoundingBoxAction::getClassTypeId())) static_cast<SoGetBoundingBoxAction*>(action)->resetCenter(); SbVec3f p1 = base.getValue(); SbVec3f p2 = p1 + normal.getValue() * length.getValue(); box.extendBy(p1); box.extendBy(p2); center = box.getCenter(); }
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; }
// compute object space ray and test for intersection static SbBool ray_intersect(SoRayPickAction * action, const SbBox3f & box) { if (box.isEmpty()) return FALSE; action->setObjectSpace(); return action->intersect(box, TRUE); }
// set scale void InvPlaneMover::setSize(const SbBox3f &bb) { float dx = fabs(bb.getMin()[0] - bb.getMax()[0]); float dy = fabs(bb.getMin()[1] - bb.getMax()[1]); float dz = fabs(bb.getMin()[2] - bb.getMax()[2]); float hsc = qMax(dx, dy); hsc = qMax(hsc, dz); hsc *= 0.3f; SbVec3f s(hsc, hsc, hsc); scale_->scaleFactor.setValue(s); }
void SoXipMenuBase::GLRender( SoGLRenderAction* action ) { if( on.getValue() == FALSE ) return ; // Compute the 3D position of the menu, given the mouse 2D position saveViewInformation( action ); mMenuOffset->translation.setValue( mPlaneProj->project( position.getValue() ) ); SoGetBoundingBoxAction bba( action->getViewportRegion() ); bba.apply( mMenuSeparator ); SbBox3f bbox = bba.getBoundingBox(); bbox.transform( mModelMatrix ); float viewportAR = mViewport.getViewportAspectRatio(); SbVec3f screenOffset(0, 0, 0); if( viewportAR < 1. ) { screenOffset[0] = bbox.getMax()[0] - 1.; screenOffset[1] = bbox.getMax()[1] - 1. / viewportAR; } else { screenOffset[0] = bbox.getMax()[0] - viewportAR; screenOffset[1] = bbox.getMax()[1] - 1; } if( screenOffset[0] < 0 ) screenOffset[0] = 0; if( screenOffset[1] < 0 ) screenOffset[1] = 0; SbVec3f worldOffset; mModelMatrix.inverse().multVecMatrix( screenOffset, worldOffset ); mMenuOffset->translation.setValue( mMenuOffset->translation.getValue() - worldOffset ); glPushAttrib( GL_ENABLE_BIT ); glDisable( GL_DEPTH_TEST ); SoXipKit::GLRender( action ); glPopAttrib(); }
void SoWidgetShape::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) { // ignore if node is empty if (this->image.isNull()) return; SbVec3f v0, v1, v2, v3; // this will cause a cache dependency on the view volume, // model matrix and viewport. this->getQuad(action->getState(), v0, v1, v2, v3); box.makeEmpty(); box.extendBy(v0); box.extendBy(v1); box.extendBy(v2); box.extendBy(v3); center = box.getCenter(); }
// Render 3D box. // // FIXME: should make bbox debug rendering part of SoSeparator / // SoGroup. 20030305 mortene. void SoOrthoSliceP::renderBox(SoGLRenderAction * action, SbBox3f box) { SbVec3f bmin, bmax; box.getBounds(bmin, bmax); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glColor4ub(0xff, 0xff, 0xff, 0xff); glLineStipple(1, 0xffff); glLineWidth(2); glBegin(GL_LINES); glVertex3f(bmin[0], bmin[1], bmin[2]); glVertex3f(bmin[0], bmin[1], bmax[2]); glVertex3f(bmax[0], bmin[1], bmin[2]); glVertex3f(bmax[0], bmin[1], bmax[2]); glVertex3f(bmax[0], bmax[1], bmin[2]); glVertex3f(bmax[0], bmax[1], bmax[2]); glVertex3f(bmin[0], bmax[1], bmin[2]); glVertex3f(bmin[0], bmax[1], bmax[2]); glVertex3f(bmin[0], bmin[1], bmin[2]); glVertex3f(bmax[0], bmin[1], bmin[2]); glVertex3f(bmin[0], bmin[1], bmax[2]); glVertex3f(bmax[0], bmin[1], bmax[2]); glVertex3f(bmin[0], bmax[1], bmax[2]); glVertex3f(bmax[0], bmax[1], bmax[2]); glVertex3f(bmin[0], bmax[1], bmin[2]); glVertex3f(bmax[0], bmax[1], bmin[2]); glVertex3f(bmin[0], bmin[1], bmin[2]); glVertex3f(bmin[0], bmax[1], bmin[2]); glVertex3f(bmin[0], bmin[1], bmax[2]); glVertex3f(bmin[0], bmax[1], bmax[2]); glVertex3f(bmax[0], bmin[1], bmax[2]); glVertex3f(bmax[0], bmax[1], bmax[2]); glVertex3f(bmax[0], bmin[1], bmin[2]); glVertex3f(bmax[0], bmax[1], bmin[2]); glEnd(); glPopAttrib(); }
SbBool SoXipPolygon::isConsistent() const { // check if the contour size is greater than the minimum size. const SbVec3f* pointPtr = point.getValues(0); SbBox3f bbox; for( int i = 0; i < point.getNum(); ++ i ) bbox.extendBy( pointPtr[i] ); SbVec3f bbSize; bbox.getSize(bbSize[0], bbSize[1], bbSize[2]); float screenScale = mViewVolume.getHeight() / mViewport.getViewportSizePixels()[1]; float bbLengthPix = bbSize.length() / screenScale; return ( bbLengthPix >= (2 * CLOSING_MIN_PIXEL_DISTANCE) ); }
// 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 ShapeParabolicRectangle::computeBBox( SoAction*, SbBox3f& box, SbVec3f& /*center*/ ) { BBox bBox = GetBBox(); // These points define the min and max extents of the box. SbVec3f min, max; min.setValue( bBox.pMin.x, bBox.pMin.y, bBox.pMin.z ); max.setValue( bBox.pMax.x, bBox.pMax.y, bBox.pMax.z );; // Set the box to bound the two extreme points. box.setBounds(min, max); }
// doc from parent void SmTextureText2::computeBBox(SoAction * action, SbBox3f & box, SbVec3f & center) { SoState * state = action->getState(); // never cull this node. We do quick culling in the render method SoCacheElement::invalidate(state); // this boundingbox will _not_ be 100% correct. We just supply an // estimate to avoid using lots of processing for calculating the // boundingbox. FIXME: make it configurable if the bbox should be // accurate or not const SbVec3f * positions; const int numpositions = this->getPositions(state, positions); const SbVec3f & offset = this->offset.getValue(); for (int i = 0; i < numpositions; i++) { box.extendBy(positions[i] + offset); } center = box.getCenter(); }
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; } } }
const SbOctTree * getOctTree(void) { if (this->octtree == NULL) { const SbOctTreeFuncs funcs = { NULL /* ptinsidefunc */, PrimitiveData::insideboxfunc, NULL /* insidespherefunc */, NULL /* insideplanesfunc */ }; SbBox3f b = this->getBoundingBox(); // Add a 1% slack to the bounding box, to avoid problems in // SbOctTree due to floating point inaccuracies (see assert() in // SbOctTree::addItem()). // // This may be just a temporary hack -- see the FIXME at the // same place as mentioned above. SbMatrix m; m.setTransform(SbVec3f(0, 0, 0), // translation SbRotation::identity(), // rotation SbVec3f(1.01f, 1.01f, 1.01f), // scalefactor SbRotation::identity(), // scaleorientation SbVec3f(b.getCenter())); // center b.transform(m); this->octtree = new SbOctTree(b, funcs); if (ida_debug()) { SoDebugError::postInfo("PrimitiveData::getOctTree", "made new octtree for PrimitiveData %p", this); } for (unsigned int k = 0; k < this->numTriangles(); k++) { SbTri3f * t = this->getTriangle(k); this->octtree->addItem(t); } } return this->octtree; }
SoCallbackAction::Response SoIntersectionDetectionAction::PImpl::shape(SoCallbackAction * action, SoShape * shape) { SbBox3f bbox; SbVec3f center; const SoBoundingBoxCache * bboxcache = shape->getBoundingBoxCache(); if (bboxcache && bboxcache->isValid(action->getState())) { bbox = bboxcache->getProjectedBox(); if (bboxcache->isCenterSet()) center = bboxcache->getCenter(); else center = bbox.getCenter(); } else { shape->computeBBox(action, bbox, center); } ShapeData * data = new ShapeData; data->path = new SoPath(*(action->getCurPath())); data->path->ref(); data->xfbbox = bbox; data->xfbbox.setTransform(action->getModelMatrix()); this->shapedata.append(data); return SoCallbackAction::CONTINUE; }
// Doc in parent void SoVRMLCylinder::computeBBox(SoAction * COIN_UNUSED_ARG(action), SbBox3f & box, SbVec3f & center) { float r = this->radius.getValue(); float h = this->height.getValue(); // Allow negative values. if (r < 0.0f) r = -r; if (h < 0.0f) h = -h; // Either the SIDES are present, or we've at least got both the TOP // and BOTTOM caps -- so just find the middle point and enclose // everything. if (this->side.getValue() || (this->bottom.getValue() && this->top.getValue())) { center.setValue(0.0f, 0.0f, 0.0f); box.setBounds(SbVec3f(-r, -h/2.0f, -r), SbVec3f(r, h/2.0f, r)); } // ..not a "full" cylinder, but we've got the BOTTOM cap. else if (this->bottom.getValue()) { center.setValue(0.0f, -h/2.0f, 0.0f); box.setBounds(SbVec3f(-r, -h/2.0f, -r), SbVec3f(r, -h/2.0f, r)); } // ..not a "full" cylinder, but we've got the TOP cap. else if (this->top.getValue()) { center.setValue(0.0f, h/2.0f, 0.0f); box.setBounds(SbVec3f(-r, h/2.0f, -r), SbVec3f(r, h/2.0f, r)); } // ..no parts present. My confidence is shot -- I feel very small. else { center.setValue(0.0f, 0.0f, 0.0f); box.setBounds(SbVec3f(0.0f, 0.0f, 0.0f), SbVec3f(0.0f, 0.0f, 0.0f)); } }
/// 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; }