[vtkusers] Re: How to avoid actors resizing when camera zooms?????

BURRELL Benjamin Benjamin.BURRELL at Tenix.com
Thu Sep 30 20:28:56 EDT 2004


To Mathieu,

I had a similar problem, I have got textured flat planes that display symbols and I wanted them to keep the same size no matter how close/far the camera is from the object (NOTE: I do not use zoom but actually move the camera closer to the object).

This is how I did it. The basic principle I used was that you want to scale the object (my textured planes) proportional to the distance between the object and the camera. You can make use of the vtkCallbackCommand class to do this.

This is the code I used to set up the callback. Stick this code in say your constructor or initialization routine.

	// Set callback for constant sized objects
	mp_CBCommand = vtkCallbackCommand::New();
	mp_CBCommand->SetCallback( UpdateConstantSize );
    	mp_CBCommand->SetClientData((void*)this);

	mp_ren->AddObserver( vtkCommand::AnyEvent ,mp_CBCommand );   // mp_ren is the vtkRenderer object.


Now this is the specified callback routine which, when called, goes through all my objects and scales them proportionally to the distance between the camera and the object.
NOTE:  An instantiated 'TrackVisualEntity' class represents one object, eg. You can regard it as a vtkActor object as the class is essentially just a wrapper for a vtkActor.


vtkMath *pg_vtkMathObj = vtkMath::New();	// General global utility object used by the static
						// routine UpdateConstantSize(...).

// This is used for updating the scaling of the VTK actors which are
// supposed to be show as a constant size relative to the viewport/window.
void UpdateConstantSize(vtkObject* caller,
                                  unsigned long vtkNotUsed(event),
                                  void* arg,
                                  void* vtkNotUsed(whatIsThis))
{
	double cameraFocalPoint[3], cameraPosition[3];
	double objectPosition[3];
	double newScale = 0;
	double totalSquared = 0;

	CVtkMDIView *pMDIView;             // CVtkMDIView is my MFC   CView or CViewForm class.
	pMDIView = (CVtkMDIView*)arg;
	vtkRenderer* p_ren = pMDIView->GetRenderer();

	std::map<TrackId, TrackVisualEntity*> & trackMap = pMDIView->GetTrackMap();  // This is a map containing all my objects that need to be
										// scaled so that they stay the same size relative to the 												// viewport/window

	std::map<TrackId, TrackVisualEntity*>::iterator iTrackMap = trackMap.begin(); // Map iterator.
											
	if ( p_ren == NULL ) return ;

	// Get a pointer to the current camera according to the main renderer.
	vtkCamera *p_currentCamera = (vtkCamera *)p_ren->GetActiveCamera();
	p_currentCamera->GetPosition( cameraPosition );
	p_currentCamera->GetFocalPoint( cameraFocalPoint );
	
	// This loops through the objects that need to be kept
	// the same size relative to the viewport. It does this by
	// changing the scaling of the object to be proportional to
	// the distance between the current camera and the object.

	for(  ; iTrackMap != trackMap.end(); iTrackMap++ )
	{
		TrackVisualEntity *p_Assembly = (*iTrackMap).second;
		p_Assembly->GetPosition( objectPosition );

		totalSquared = sqrt(pg_vtkMathObj->Distance2BetweenPoints( objectPosition, cameraPosition ));
		newScale = totalSquared/40;    // The value 40 is an abitary number that gives me the desired size of the objects on screen.
		p_Assembly->SetScale( newScale );
	}
}


Hope this helps Mathieu.


Regards,
Benjamin Burrell

Computer Engineer
Electronic Systems Division
Tenix Defence Pty Ltd
Second Ave., Technology Park, 
Mawson Lakes SA 5095
Ph:  (08) 8300 4404   Mob: 0414 390 979
Email: Benjamin.Burrell at Tenix.com




More information about the vtkusers mailing list