// 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 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; } } }
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(); }
/** * 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 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(); }
// 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; }
// 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(); }
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; }
// Execute full set of intersection detection operations on all the // primitives that has been souped up from the scene graph. void SoIntersectionDetectionAction::PImpl::doIntersectionTesting(void) { if (this->callbacks.empty()) { SoDebugError::postWarning("SoIntersectionDetectionAction::PImpl::doIntersectionTesting", "intersection testing invoked, but no callbacks set up"); return; } delete this->traverser; this->traverser = NULL; if (ida_debug()) { SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doIntersectionTesting", "total number of shapedata items == %d", this->shapedata.getLength()); } const SbOctTreeFuncs funcs = { NULL /* ptinsidefunc */, shapeinsideboxfunc, NULL /* insidespherefunc */, NULL /* insideplanesfunc */ }; SbBox3f b = this->fullxfbbox.project(); // 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. 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); SbOctTree shapetree(b, funcs); for (int k = 0; k < this->shapedata.getLength(); k++) { ShapeData * shape = this->shapedata[k]; if (shape->xfbbox.isEmpty()) { continue; } shapetree.addItem(shape); } if (ida_debug()) { shapetree.debugTree(stderr); } // For debugging. unsigned int nrshapeshapeisects = 0; unsigned int nrselfisects = 0; const float theepsilon = this->getEpsilon(); for (int i = 0; i < this->shapedata.getLength(); i++) { ShapeData * shape1 = this->shapedata[i]; // If the shape has no geometry, immediately skip to next // iteration of for-loop. if (shape1->xfbbox.isEmpty()) { continue; } // Remove shapes from octtree as we iterate over the full set, to // avoid self-intersection and to avoid checks against other // shapes happening both ways. shapetree.removeItem(shape1); // FIXME: shouldn't we also invoke the filter-callback here? 20030403 mortene. if (this->internalsenabled) { nrselfisects++; SbBool cont; this->doInternalPrimitiveIntersectionTesting(shape1->getPrimitives(), cont); if (!cont) { goto done; } } SbBox3f shapebbox = shape1->xfbbox.project(); if (theepsilon > 0.0f) { const SbVec3f e(theepsilon, theepsilon, theepsilon); // Extend bbox in all 6 directions with the epsilon value. shapebbox.getMin() -= e; shapebbox.getMax() += e; } SbList<void*> candidateshapes; shapetree.findItems(shapebbox, candidateshapes); if (ida_debug()) { SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doIntersectionTesting", "shape %d intersects %d other shapes", i, candidateshapes.getLength()); // debug, dump to .iv-file the "master" shape bbox given by i, // plus ditto for all intersected shapes #if 0 if (i == 4) { SoSeparator * root = new SoSeparator; root->ref(); root->addChild(make_scene_graph(shape1->xfbbox, "mastershape")); for (int j = 0; j < candidateshapes.getLength(); j++) { ShapeData * s = (ShapeData * )candidateshapes[j]; SbString str; str.sprintf("%d", j); root->addChild(make_scene_graph(s->xfbbox, str.getString())); } SoOutput out; SbBool ok = out.openFile("/tmp/shapechk.iv"); assert(ok); SoWriteAction wa(&out); wa.apply(root); root->unref(); } #endif // debug } SbXfBox3f xfboxchk; if (theepsilon > 0.0f) { xfboxchk = expand_SbXfBox3f(shape1->xfbbox, theepsilon); } else { xfboxchk = shape1->xfbbox; } for (int j = 0; j < candidateshapes.getLength(); j++) { ShapeData * shape2 = static_cast<ShapeData *>(candidateshapes[j]); if (!xfboxchk.intersect(shape2->xfbbox)) { if (ida_debug()) { SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doIntersectionTesting", "shape %d intersecting %d is a miss when tried with SbXfBox3f::intersect(SbXfBox3f)", i, j); } continue; } if (!this->filtercb || this->filtercb(this->filterclosure, shape1->path, shape2->path)) { nrshapeshapeisects++; SbBool cont; this->doPrimitiveIntersectionTesting(shape1->getPrimitives(), shape2->getPrimitives(), cont); if (!cont) { goto done; } } } } done: if (ida_debug()) { SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doIntersectionTesting", "shape-shape intersections: %d, shape self-intersections: %d", nrshapeshapeisects, nrselfisects); } }