Пример #1
0
void
SbSphere::circumscribe(const SbBox3f &box)
//
//////////////////////////////////////////////////////////////////////////////
{
    center = 0.5 * (box.getMin() + box.getMax());
    radius = (box.getMax() - center).length();
}
Пример #2
0
// 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;
}
Пример #3
0
// 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);
}
Пример #6
0
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();
}
Пример #7
0
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] ) );
}
Пример #8
0
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();
}
Пример #9
0
/*
 * 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();
}
Пример #10
0
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);
  }
}
Пример #13
0
		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();
			}
		}
Пример #14
0
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;
}