void SbSphere::circumscribe(const SbBox3f &box) // ////////////////////////////////////////////////////////////////////////////// { center = 0.5 * (box.getMin() + box.getMax()); radius = (box.getMax() - center).length(); }
// 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; }
// 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); }
// 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; }
// 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); }
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 ViewProviderDatum::setExtents (const SbBox3f &bbox) { const SbVec3f & min = bbox.getMin (); const SbVec3f & max = bbox.getMax (); setExtents ( Base::BoundBox3d ( min.getValue()[0], min.getValue()[1], min.getValue()[2], max.getValue()[0], max.getValue()[1], max.getValue()[2] ) ); }
void SoSurroundScale::updateMySurroundParams(SoAction *action, const SbMatrix &myInv ) // //////////////////////////////////////////////////////////////////////// { const SoFullPath *curPath = (const SoFullPath *) action->getCurPath(); int curPathLength = curPath->getLength(); // If the container node is out of range, just return. int numUpCon = (int) numNodesUpToContainer.getValue(); if ( (numUpCon <= 0) || (numUpCon > (curPathLength - 1)) ){ cachedScale.setValue(1,1,1); cachedInvScale.setValue(1,1,1); cachedTranslation.setValue(0,0,0); cacheOK = FALSE; return; } // CHECK TO SEE IF OUR CACHED VALUES ARE OKAY // IF SO, JUST RETURN if ( cacheOK ) return; // Find the path to apply the bounding box action to. It should end // 'numUpCon' above this one. SoPath *applyPath = curPath->copy(0, (curPathLength - numUpCon)); applyPath->ref(); // See if there is a node to do a reset at. If so, build a resetPath SoPath *resetPath = NULL; int numUpReset = (int) numNodesUpToReset.getValue(); if (numUpReset >= 0 && (numUpReset < numUpCon) ) { // Build a path ending at the reset node. resetPath = curPath->copy(0, curPathLength - numUpReset ); resetPath->ref(); } SoFullPath *fullResetPath = (SoFullPath *) resetPath; // Create a getBoundingBox action // Set the reset path if we have one. // Apply the bounding box action and find out how big the box was. // Temporarily set the ignoreInBbox flag TRUE, so we don't infinite loop! SbViewportRegion vpRegion(0,0); SoState *state = action->getState(); vpRegion = SoViewportRegionElement::get(state); static SoGetBoundingBoxAction *boundingBoxAction = NULL; if (boundingBoxAction == NULL) boundingBoxAction = new SoGetBoundingBoxAction(vpRegion); else boundingBoxAction->setViewportRegion(vpRegion); if (fullResetPath) boundingBoxAction->setResetPath( fullResetPath, FALSE, SoGetBoundingBoxAction::BBOX); SbBool oldFlag = isIgnoreInBbox(); setIgnoreInBbox( TRUE ); boundingBoxAction->apply( applyPath ); setIgnoreInBbox( oldFlag ); SbXfBox3f &myXfBox = boundingBoxAction->getXfBoundingBox(); // Transform the box into our local space, then project it. myXfBox.transform( myInv ); SbBox3f myBox = myXfBox.project(); // Get the scale for this node to add to the ctm. if (myBox.isEmpty()) { cachedScale.setValue(1,1,1); cachedInvScale.setValue(1,1,1); cachedTranslation.setValue(0,0,0); cacheOK = TRUE; return; } else { float x, y, z; myBox.getSize(x,y,z); cachedScale.setValue( .5*x, .5*y, .5*z ); float minLength = .01 * cachedScale.length(); // Macro defined just before beginning of this method. FUDGE(cachedScale[0],minLength); FUDGE(cachedScale[1],minLength); FUDGE(cachedScale[2],minLength); // Find the inverse values for (int j = 0; j < 3; j++ ) cachedInvScale[j] = 1.0 / cachedScale[j]; } // Get the translation for this node to add to the ctm. // This will get the cube centered about the bbox center. // If the bounding box is not centered at the origin, we have to // move the cube to the correct place. if (doTranslations) cachedTranslation = 0.5 * ( myBox.getMin() + myBox.getMax() ); else cachedTranslation.setValue(0,0,0); // Establish the cached values to save us some time later... cacheOK = TRUE; if (resetPath) resetPath->unref(); if (applyPath) applyPath->unref(); }
/* * Fun flux analysis */ void FluxAnalysis::RunFluxAnalysis( QString nodeURL, QString surfaceSide, unsigned long nOfRays, bool increasePhotonMap, int heightDivisions, int widthDivisions ) { m_surfaceURL = nodeURL; m_surfaceSide = surfaceSide; //Delete a photonCounts if( m_photonCounts && m_photonCounts != 0 ) { for( int h = 0; h < m_heightDivisions; h++ ) { delete[] m_photonCounts[h]; } delete[] m_photonCounts; } m_photonCounts = 0; m_heightDivisions = heightDivisions; m_widthDivisions = widthDivisions; //Check if there is a scene if ( !m_pCurrentScene ) return; //Check if there is a transmissivity defined TTransmissivity* transmissivity = 0; if ( !m_pCurrentScene->getPart( "transmissivity", false ) ) transmissivity = 0; else transmissivity = static_cast< TTransmissivity* > ( m_pCurrentScene->getPart( "transmissivity", false ) ); //Check if there is a rootSeparator InstanceNode if( !m_pRootSeparatorInstance ) return; InstanceNode* sceneInstance = m_pRootSeparatorInstance->GetParent(); if ( !sceneInstance ) return; //Check if there is a light and is properly configured if ( !m_pCurrentScene->getPart( "lightList[0]", false ) )return; TLightKit* lightKit = static_cast< TLightKit* >( m_pCurrentScene->getPart( "lightList[0]", false ) ); InstanceNode* lightInstance = sceneInstance->children[0]; if ( !lightInstance ) return; if( !lightKit->getPart( "tsunshape", false ) ) return; TSunShape* sunShape = static_cast< TSunShape * >( lightKit->getPart( "tsunshape", false ) ); if( !lightKit->getPart( "icon", false ) ) return; TLightShape* raycastingSurface = static_cast< TLightShape * >( lightKit->getPart( "icon", false ) ); if( !lightKit->getPart( "transform" ,false ) ) return; SoTransform* lightTransform = static_cast< SoTransform * >( lightKit->getPart( "transform" ,false ) ); //Check if there is a random generator is defined. if( !m_pRandomDeviate || m_pRandomDeviate== 0 ) return; //Check if the surface and the surface side defined is suitable if( CheckSurface() == false || CheckSurfaceSide() == false ) return; //Create the photon map where photons are going to be stored if( !m_pPhotonMap || !increasePhotonMap ) { if( m_pPhotonMap ) m_pPhotonMap->EndStore( -1 ); delete m_pPhotonMap; m_pPhotonMap = new TPhotonMap(); m_pPhotonMap->SetBufferSize( HUGE_VAL ); m_tracedRays = 0; m_wPhoton = 0; m_totalPower = 0; } QVector< InstanceNode* > exportSuraceList; QModelIndex nodeIndex = m_pCurrentSceneModel->IndexFromNodeUrl( m_surfaceURL ); if( !nodeIndex.isValid() ) return; InstanceNode* surfaceNode = m_pCurrentSceneModel->NodeFromIndex( nodeIndex ); if( !surfaceNode || surfaceNode == 0 ) return; exportSuraceList.push_back( surfaceNode ); //UpdateLightSize(); TSeparatorKit* concentratorRoot = static_cast< TSeparatorKit* >( m_pCurrentScene->getPart( "childList[0]", false ) ); if ( !concentratorRoot ) return; SoGetBoundingBoxAction* bbAction = new SoGetBoundingBoxAction( SbViewportRegion() ) ; concentratorRoot->getBoundingBox( bbAction ); SbBox3f box = bbAction->getXfBoundingBox().project(); delete bbAction; bbAction = 0; BBox sceneBox; if( !box.isEmpty() ) { sceneBox.pMin = Point3D( box.getMin()[0], box.getMin()[1], box.getMin()[2] ); sceneBox.pMax = Point3D( box.getMax()[0], box.getMax()[1], box.getMax()[2] ); if( lightKit ) lightKit->Update( sceneBox ); } m_pCurrentSceneModel->UpdateSceneModel(); //Compute bounding boxes and world to object transforms trf::ComputeSceneTreeMap( m_pRootSeparatorInstance, Transform( new Matrix4x4 ), true ); m_pPhotonMap->SetConcentratorToWorld( m_pRootSeparatorInstance->GetIntersectionTransform() ); QStringList disabledNodes = QString( lightKit->disabledNodes.getValue().getString() ).split( ";", QString::SkipEmptyParts ); QVector< QPair< TShapeKit*, Transform > > surfacesList; trf::ComputeFistStageSurfaceList( m_pRootSeparatorInstance, disabledNodes, &surfacesList ); lightKit->ComputeLightSourceArea( m_sunWidthDivisions, m_sunHeightDivisions, surfacesList ); if( surfacesList.count() < 1 ) return; QVector< long > raysPerThread; int maximumValueProgressScale = 100; unsigned long t1 = nOfRays/ maximumValueProgressScale; for( int progressCount = 0; progressCount < maximumValueProgressScale; ++ progressCount ) raysPerThread<< t1; if( ( t1 * maximumValueProgressScale ) < nOfRays ) raysPerThread<< ( nOfRays - ( t1* maximumValueProgressScale) ); Transform lightToWorld = tgf::TransformFromSoTransform( lightTransform ); lightInstance->SetIntersectionTransform( lightToWorld.GetInverse() ); // Create a progress dialog. QProgressDialog dialog; dialog.setLabelText( QString("Progressing using %1 thread(s)..." ).arg( QThread::idealThreadCount() ) ); // Create a QFutureWatcher and conncect signals and slots. QFutureWatcher< void > futureWatcher; QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); QMutex mutex; QMutex mutexPhotonMap; QFuture< void > photonMap; if( transmissivity ) photonMap = QtConcurrent::map( raysPerThread, RayTracer( m_pRootSeparatorInstance, lightInstance, raycastingSurface, sunShape, lightToWorld, transmissivity, *m_pRandomDeviate, &mutex, m_pPhotonMap, &mutexPhotonMap, exportSuraceList ) ); else photonMap = QtConcurrent::map( raysPerThread, RayTracerNoTr( m_pRootSeparatorInstance, lightInstance, raycastingSurface, sunShape, lightToWorld, *m_pRandomDeviate, &mutex, m_pPhotonMap, &mutexPhotonMap, exportSuraceList ) ); futureWatcher.setFuture( photonMap ); // Display the dialog and start the event loop. dialog.exec(); futureWatcher.waitForFinished(); m_tracedRays += nOfRays; double irradiance = sunShape->GetIrradiance(); double inputAperture = raycastingSurface->GetValidArea(); m_wPhoton = double ( inputAperture * irradiance ) / m_tracedRays; UpdatePhotonCounts(); }
void ViewProviderBody::updateOriginDatumSize () { PartDesign::Body *body = static_cast<PartDesign::Body *> ( getObject() ); // Use different bounding boxes for datums and for origins: Gui::Document* gdoc = Gui::Application::Instance->getDocument(getObject()->getDocument()); if(!gdoc) return; Gui::MDIView* view = gdoc->getViewOfViewProvider(this); if(!view) return; Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer(); SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion()); const auto & model = body->getFullModel (); // BBox for Datums is calculated from all visible objects but treating datums as their basepoints only SbBox3f bboxDatums = ViewProviderDatum::getRelevantBoundBox ( bboxAction, model ); // BBox for origin should take into account datums size also SbBox3f bboxOrigins = bboxDatums; for(App::DocumentObject* obj : model) { if ( obj->isDerivedFrom ( Part::Datum::getClassTypeId () ) ) { ViewProvider *vp = Gui::Application::Instance->getViewProvider(obj); if (!vp) { continue; } ViewProviderDatum *vpDatum = static_cast <ViewProviderDatum *> (vp) ; vpDatum->setExtents ( bboxDatums ); bboxAction.apply ( vp->getRoot () ); bboxOrigins.extendBy ( bboxAction.getBoundingBox () ); } } // get the bounding box values SbVec3f max = bboxOrigins.getMax(); SbVec3f min = bboxOrigins.getMin(); // obtain an Origin and it's ViewProvider App::Origin* origin = 0; Gui::ViewProviderOrigin* vpOrigin = 0; try { origin = body->getOrigin (); assert (origin); Gui::ViewProvider *vp = Gui::Application::Instance->getViewProvider(origin); if (!vp) { throw Base::Exception ("No view provider linked to the Origin"); } assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) ); vpOrigin = static_cast <Gui::ViewProviderOrigin *> ( vp ); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what() ); return; } // calculate the desired origin size Base::Vector3d size; for (uint_fast8_t i=0; i<3; i++) { size[i] = std::max ( fabs ( max[i] ), fabs ( min[i] ) ); if (size[i] < Precision::Confusion() ) { size[i] = Gui::ViewProviderOrigin::defaultSize(); } } vpOrigin->Size.setValue ( size*1.2 ); }
// Intersection testing between primitives of different shapes. void SoIntersectionDetectionAction::PImpl::doPrimitiveIntersectionTesting(PrimitiveData * primitives1, PrimitiveData * primitives2, SbBool & cont) { cont = TRUE; // for debugging if (ida_debug()) { SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doPrimitiveIntersectionTesting", "primitives1 (%p) = %d tris, primitives2 (%p) = %d tris", primitives1, primitives1->numTriangles(), primitives2, primitives2->numTriangles()); } unsigned int nrisectchks = 0; unsigned int nrhits = 0; // Use the majority size shape from an octtree. // // (Some initial investigation indicates that this isn't a clear-cut // choice, by the way -- should investigate further. mortene.) PrimitiveData * octtreeprims = primitives1; PrimitiveData * iterationprims = primitives2; if (primitives1->numTriangles() < primitives2->numTriangles()) { octtreeprims = primitives2; iterationprims = primitives1; } const SbOctTree * octtree = octtreeprims->getOctTree(); const float theepsilon = this->getEpsilon(); const SbVec3f e(theepsilon, theepsilon, theepsilon); for (unsigned int i = 0; i < iterationprims->numTriangles(); i++) { SbTri3f * t1 = static_cast<SbTri3f *>(iterationprims->getTriangle(i)); SbBox3f tribbox = t1->getBoundingBox(); if (theepsilon > 0.0f) { // Extend bbox in all 6 directions with the epsilon value. tribbox.getMin() -= e; tribbox.getMax() += e; } SbList<void*> candidatetris; octtree->findItems(tribbox, candidatetris); for (int j = 0; j < candidatetris.getLength(); j++) { SbTri3f * t2 = static_cast<SbTri3f *>(candidatetris[j]); nrisectchks++; if (t1->intersect(*t2, theepsilon)) { nrhits++; SoIntersectingPrimitive p1; p1.path = iterationprims->getPath(); p1.type = SoIntersectingPrimitive::TRIANGLE; t1->getValue(p1.xf_vertex[0], p1.xf_vertex[1], p1.xf_vertex[2]); iterationprims->invtransform.multVecMatrix(p1.xf_vertex[0], p1.vertex[0]); iterationprims->invtransform.multVecMatrix(p1.xf_vertex[1], p1.vertex[1]); iterationprims->invtransform.multVecMatrix(p1.xf_vertex[2], p1.vertex[2]); SoIntersectingPrimitive p2; p2.path = octtreeprims->getPath(); p2.type = SoIntersectingPrimitive::TRIANGLE; t2->getValue(p2.xf_vertex[0], p2.xf_vertex[1], p2.xf_vertex[2]); octtreeprims->invtransform.multVecMatrix(p2.xf_vertex[0], p2.vertex[0]); octtreeprims->invtransform.multVecMatrix(p2.xf_vertex[1], p2.vertex[1]); octtreeprims->invtransform.multVecMatrix(p2.xf_vertex[2], p2.vertex[2]); std::vector<SoIntersectionCallback>::iterator it = this->callbacks.begin(); while (it != this->callbacks.end()) { switch ( (*it).first((*it).second, &p1, &p2) ) { case SoIntersectionDetectionAction::NEXT_PRIMITIVE: // Break out of the switch, invoke next callback. break; case SoIntersectionDetectionAction::NEXT_SHAPE: // FIXME: remaining callbacks won't be invoked -- should they? 20030328 mortene. cont = TRUE; goto done; case SoIntersectionDetectionAction::ABORT: // FIXME: remaining callbacks won't be invoked -- should they? 20030328 mortene. cont = FALSE; goto done; default: assert(0); } ++it; } } } } done: // for debugging if (ida_debug()) { const unsigned int total = primitives1->numTriangles() + primitives2->numTriangles(); SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doPrimitiveIntersectionTesting", "intersection checks = %d (pr primitive: %f)", nrisectchks, float(nrisectchks) / total); SbString chksprhit; if (nrhits == 0) { chksprhit = "-"; } else { chksprhit.sprintf("%f", float(nrisectchks) / nrhits); } SoDebugError::postInfo("SoIntersectionDetectionAction::PImpl::doPrimitiveIntersectionTesting", "hits = %d (chks pr hit: %s)", nrhits, chksprhit.getString()); } }
// 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); } }
void Scene::load(const ::std::string& filename, const bool& doBoundingBoxPoints, const bool& doPoints) { ::rl::xml::DomParser parser; ::rl::xml::Document doc = parser.readFile(filename, "", XML_PARSE_NOENT | XML_PARSE_XINCLUDE); doc.substitute(XML_PARSE_NOENT | XML_PARSE_XINCLUDE); ::rl::xml::Path path(doc); ::rl::xml::Object scenes = path.eval("//scene"); for (int i = 0; i < ::std::min(1, scenes.getNodeNr()); ++i) { SoInput input; if (!input.openFile(scenes.getNodeTab(i).getLocalPath(scenes.getNodeTab(i).getAttribute("href").getValue()).c_str() ,true)) { throw Exception("::rl::sg::Scene::load() - failed to open file"); } SoVRMLGroup* root = SoDB::readAllVRML(&input); if (NULL == root) { throw Exception("::rl::sg::Scene::load() - failed to read file"); } SbViewportRegion viewportRegion; root->ref(); // model ::rl::xml::Object models = path.eval("model", scenes.getNodeTab(i)); for (int j = 0; j < models.getNodeNr(); ++j) { SoSearchAction modelSearchAction; modelSearchAction.setName(models.getNodeTab(j).getAttribute("name").getValue().c_str()); modelSearchAction.apply(root); if (NULL == modelSearchAction.getPath()) { continue; } Model* model = this->create(); model->setName(models.getNodeTab(j).getAttribute("name").getValue()); // body ::rl::xml::Object bodies = path.eval("body", models.getNodeTab(j)); for (int k = 0; k < bodies.getNodeNr(); ++k) { SoSearchAction bodySearchAction; bodySearchAction.setName(bodies.getNodeTab(k).getAttribute("name").getValue().c_str()); bodySearchAction.apply(static_cast< SoFullPath* >(modelSearchAction.getPath())->getTail()); if (NULL == bodySearchAction.getPath()) { continue; } Body* body = model->create(); body->setName(bodies.getNodeTab(k).getAttribute("name").getValue()); SoSearchAction pathSearchAction; pathSearchAction.setNode(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail()); pathSearchAction.apply(root); SoGetMatrixAction bodyGetMatrixAction(viewportRegion); bodyGetMatrixAction.apply(static_cast< SoFullPath* >(pathSearchAction.getPath())); SbMatrix bodyMatrix = bodyGetMatrixAction.getMatrix(); if (!this->isScalingSupported) { SbVec3f bodyTranslation; SbRotation bodyRotation; SbVec3f bodyScaleFactor; SbRotation bodyScaleOrientation; SbVec3f bodyCenter; bodyMatrix.getTransform(bodyTranslation, bodyRotation, bodyScaleFactor, bodyScaleOrientation, bodyCenter); for (int l = 0; l < 3; ++l) { if (::std::abs(bodyScaleFactor[l] - 1.0f) > 1.0e-6f) { throw Exception("::rl::sg::Scene::load() - bodyScaleFactor not supported"); } } } ::rl::math::Transform frame; for (int m = 0; m < 4; ++m) { for (int n = 0; n < 4; ++n) { frame(m, n) = bodyMatrix[n][m]; } } body->setFrame(frame); if (static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail()->isOfType(SoVRMLTransform::getClassTypeId())) { SoVRMLTransform* bodyVrmlTransform = static_cast< SoVRMLTransform* >(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail()); for (int l = 0; l < 3; ++l) { body->center(l) = bodyVrmlTransform->center.getValue()[l]; } } SoPathList pathList; // shape SoSearchAction shapeSearchAction; shapeSearchAction.setInterest(SoSearchAction::ALL); shapeSearchAction.setType(SoVRMLShape::getClassTypeId()); shapeSearchAction.apply(static_cast< SoFullPath* >(bodySearchAction.getPath())->getTail()); for (int l = 0; l < shapeSearchAction.getPaths().getLength(); ++l) { SoFullPath* path = static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l]); if (path->getLength() > 1) { path = static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l]->copy(1, static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l])->getLength() - 1)); } pathList.append(path); SoGetMatrixAction shapeGetMatrixAction(viewportRegion); shapeGetMatrixAction.apply(path); SbMatrix shapeMatrix = shapeGetMatrixAction.getMatrix(); if (!this->isScalingSupported) { SbVec3f shapeTranslation; SbRotation shapeRotation; SbVec3f shapeScaleFactor; SbRotation shapeScaleOrientation; SbVec3f shapeCenter; shapeMatrix.getTransform(shapeTranslation, shapeRotation, shapeScaleFactor, shapeScaleOrientation, shapeCenter); for (int m = 0; m < 3; ++m) { if (::std::abs(shapeScaleFactor[m] - 1.0f) > 1.0e-6f) { throw Exception("::rl::sg::Scene::load() - shapeScaleFactor not supported"); } } } SoVRMLShape* shapeVrmlShape = static_cast< SoVRMLShape* >(static_cast< SoFullPath* >(shapeSearchAction.getPaths()[l])->getTail()); Shape* shape = body->create(shapeVrmlShape); shape->setName(shapeVrmlShape->getName().getString()); ::rl::math::Transform transform; for (int m = 0; m < 4; ++m) { for (int n = 0; n < 4; ++n) { transform(m, n) = shapeMatrix[n][m]; } } shape->setTransform(transform); } // bounding box if (doBoundingBoxPoints) { SoGetBoundingBoxAction getBoundingBoxAction(viewportRegion); getBoundingBoxAction.apply(pathList); SbBox3f boundingBox = getBoundingBoxAction.getBoundingBox(); for (int l = 0; l < 3; ++l) { body->max(l) = boundingBox.getMax()[l]; body->min(l) = boundingBox.getMin()[l]; } } // convex hull if (doPoints) { SoCallbackAction callbackAction; callbackAction.addTriangleCallback(SoVRMLGeometry::getClassTypeId(), Scene::triangleCallback, &body->points); callbackAction.apply(pathList); } } } root->unref(); } }
int main(int argc, char ** argv) { if ( argc != 3 ) { fprintf(stderr, "Usage: %s <infile.iv> <outfile.iv>\n", argv[0]); return -1; } SoDB::init(); SoNodeKit::init(); SoInteraction::init(); SoGenerateSceneGraphAction::initClass(); SoTweakAction::initClass(); SoInput in; SoNode * scene, * graph; if ( !in.openFile(argv[1]) ) { fprintf(stderr, "%s: error opening \"%s\" for reading.\n", argv[0], argv[1]); return -1; } scene = SoDB::readAll(&in); if ( scene == NULL ) { fprintf(stderr, "%s: error parsing \"%s\"\n", argv[0], argv[1]); return -1; } scene->ref(); SoGenerateSceneGraphAction action; // action.setDropTypeIfNameEnabled(TRUE); action.apply(scene); graph = action.getGraph(); if ( graph == NULL ) { fprintf(stderr, "%s: error generating scene graph\n", argv[0]); return -1; } graph->ref(); scene->unref(); scene = NULL; // figure out camera settings and needed rendering canvas size SoGetBoundingBoxAction bbaction(SbViewportRegion(64,64)); // just something bbaction.apply(graph); SbBox3f bbox = bbaction.getBoundingBox(); SbVec3f min = bbox.getMin(); SbVec3f max = bbox.getMax(); float bwidth = max[0] - min[0]; float bheight = max[1] - min[1]; // fprintf(stdout, "min: %g %g %g\n", min[0], min[1], min[2]); // fprintf(stdout, "max: %g %g %g\n", max[0], max[1], max[2]); // place camera SoSearchAction search; search.setType(SoCamera::getClassTypeId()); search.setInterest(SoSearchAction::FIRST); search.apply(graph); SoPath * campath = search.getPath(); SoOrthographicCamera * cam = (SoOrthographicCamera *) campath->getTail(); assert(cam != NULL); SbVec3f pos = cam->position.getValue(); cam->position.setValue(SbVec3f(min[0] + ((max[0]-min[0])/2.0), min[1] + ((max[1]-min[1])/2.0), pos[2])); cam->height.setValue(bheight); if ( TRUE ) { // FIXME: only write .iv-scene if asked SoOutput out; if ( !out.openFile(argv[2]) ) { fprintf(stderr, "%s: error opening \"%s\" for writing.\n", argv[0], argv[2]); return -1; } SoWriteAction writer(&out); // writer.setCoinFormattingEnabled(TRUE); writer.apply(graph); } int width = (int) ceil(bwidth * 150.0) + 2; int height = (int) ceil(bheight * 150.0); fprintf(stderr, "image: %d x %d\n", width, height); if ( TRUE ) { // FIXME: only write image if asked SoOffscreenRenderer renderer(SbViewportRegion(width, height)); SoGLRenderAction * glra = renderer.getGLRenderAction(); glra->setNumPasses(9); // FIXME: auto-crop image afterwards? seems like it's a perfect fit right now renderer.setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); renderer.setBackgroundColor(SbColor(1.0,1.0,1.0)); renderer.render(graph); // FIXME: support command line option filename // FIXME: also support .eps renderer.writeToFile("output.png", "png"); } graph->unref(); return 0; }