예제 #1
0
파일: Group.cpp 프로젝트: Alexpux/Coin3D
// 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);
}
    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;
    }
예제 #3
0
// 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;
}
예제 #4
0
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;
        }
    }
}
    /// 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;
    }
예제 #6
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();
}
예제 #7
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();
}