The following code comes from vtkFollower, we used it to make the original axes always face the camera.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkTriangleFilter.h>
#include <vtkRegularPolygonSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <vtkNamedColors.h>
#include <vtkImageActor.h>
#include <vtkImageViewer2.h>
#include <vtkPNGReader.h>
#include <vtkPlaneSource.h>
#include <vtkAxesActor.h>
#include <vtkTransform.h>
#include "tool.h"
using namespace std;
vtkSmartPointer<vtkTransform> m_UserTransform;
PointStruct Origin( 0, 0, 0 );
vtkCamera *Camera = nullptr;
vtkSmartPointer<vtkRenderWindow> renderWindow;
PointStruct Position( 0, 0, 0 );
vtkSmartPointer<vtkMatrix4x4> m_Matrix4x4;
void RebuildMatrix()
{
double Orientation[3];
m_UserTransform->GetOrientation( Orientation );
m_UserTransform->Push();
m_UserTransform->Identity();
m_UserTransform->PostMultiply();
m_UserTransform->Translate( -Origin[0], -Origin[1], -Origin[2]);
// rotate
m_UserTransform->RotateY(Orientation[1]);
m_UserTransform->RotateX(Orientation[0]);
m_UserTransform->RotateZ(Orientation[2]);
double *pos, *vup, distance;
double Rx[3], Ry[3], Rz[3];
vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
matrix->Identity();
// do the rotation
// first rotate y
pos = Camera->GetPosition();
vup = Camera->GetViewUp();
printf( "pos: (%lf, %lf, %lf)\n", pos[0], pos[1], pos[2] );
printf( "vup: (%lf, %lf, %lf)\n", vup[0], vup[1], vup[2] );
if (Camera->GetParallelProjection())
{
Camera->GetDirectionOfProjection(Rz);
Rz[0] = -Rz[0];
Rz[1] = -Rz[1];
Rz[2] = -Rz[2];
}
else
{
distance = sqrt(
(pos[0] - Position[0])*(pos[0] - Position[0]) +
(pos[1] - Position[1])*(pos[1] - Position[1]) +
(pos[2] - Position[2])*(pos[2] - Position[2]));
for (int i = 0; i < 3; i++)
{
Rz[i] = (pos[i] - Position[i])/distance;
}
}
//instead use the view right angle:
double dop[3], vur[3];
Camera->GetDirectionOfProjection(dop);
vtkMath::Cross(dop,vup,vur);
vtkMath::Normalize(vur);
vtkMath::Cross(Rz, vur, Ry);
vtkMath::Normalize(Ry);
vtkMath::Cross(Ry,Rz,Rx);
matrix->Element[0][0] = Rx[0];
matrix->Element[1][0] = Rx[1];
matrix->Element[2][0] = Rx[2];
matrix->Element[0][1] = Ry[0];
matrix->Element[1][1] = Ry[1];
matrix->Element[2][1] = Ry[2];
matrix->Element[0][2] = Rz[0];
matrix->Element[1][2] = Rz[1];
matrix->Element[2][2] = Rz[2];
printf( "================== matrix ===============\n" );
matrix->PrintSelf( std::cout, vtkIndent() );
m_UserTransform->Concatenate(matrix);
m_UserTransform->GetMatrix()->PrintSelf( std::cout, vtkIndent() );
m_UserTransform->Translate(Origin[0] + Position[0],
Origin[1] + Position[1],
Origin[2] + Position[2]);
m_UserTransform->PreMultiply();
m_UserTransform->GetMatrix( m_Matrix4x4 );
m_UserTransform->Pop();
renderWindow->Render();
printf( "================== finished ===============\n" );
m_UserTransform->GetMatrix()->PrintSelf( std::cout, vtkIndent() );
}
class vtkMyCallback : public vtkCommand
{
public:
static vtkMyCallback *New()
{
return new vtkMyCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkRenderer *ren = reinterpret_cast <vtkRenderer*>(caller);
cout << ren->GetActiveCamera()->GetPosition()[0] << " "
<< ren->GetActiveCamera()->GetPosition()[1] << " "
<< ren->GetActiveCamera()->GetPosition()[2] << "\n";
RebuildMatrix();
}
};
int main()
{
setbuf( stdout, nullptr );
m_Matrix4x4 = vtkSmartPointer<vtkMatrix4x4>::New();
vtkSmartPointer<vtkAxesActor> axesActor =
vtkSmartPointer<vtkAxesActor>::New();
m_UserTransform = vtkSmartPointer<vtkTransform>::New();
m_UserTransform->PreMultiply();
m_UserTransform->Identity();
axesActor->SetUserMatrix( m_Matrix4x4 );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor( axesActor );
renderer->SetBackground( 0, 0, 0 );
renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
Camera = renderer->GetActiveCamera();
Camera->SetParallelProjection( true );
renderWindow->Render();
vtkSmartPointer<vtkMyCallback> myCallback =
vtkSmartPointer<vtkMyCallback>::New();
renderer->AddObserver( vtkCommand::StartEvent, myCallback );
renderWindowInteractor->Start();
return 0;
}