Hi everyone,
as some of you might feel as I do that the camera in 3D view tilts when rotating, I have rewritten the code in Slicer/Libs/MRML/DisplayableManger/vtkMRMLCameraWidget.cxx
in vtkMRMLCameraWidget::ProcessRotate
as the following and then built my own Slicer.
//----------------------------------------------------------------------------
bool vtkMRMLCameraWidget::ProcessRotate(vtkMRMLInteractionEventData* eventData)
{
if (!this->Renderer || !eventData)
{
return false;
}
const int* eventPosition = eventData->GetDisplayPosition();
int dx = eventPosition[0] - this->PreviousEventPosition[0];
int dy = eventPosition[1] - this->PreviousEventPosition[1];
if (dx == 0 && dy == 0)
{
return true;
}
const int *size = this->Renderer->GetRenderWindow()->GetSize();
double delta_elevation = -20.0 / size[1];
double delta_azimuth = -20.0 / size[0];
double rxf = (double)dx * delta_azimuth * this->MotionFactor;
double ryf = (double)dy * delta_elevation * this->MotionFactor;
vtkCamera* camera = this->GetCamera();
if (!camera)
{
return false;
}
bool wasCameraNodeModified = this->CameraModifyStart();
if (this->CameraTiltLocked == true)
{
camera->Azimuth(rxf);
}
else
{
const double* cameraPosition = camera->GetPosition();
const double* cameraFocalPoint = camera->GetFocalPoint();
const double* cameraViewUp = camera->GetViewUp();
bool upside_down = cameraViewUp[2] < 0;
double upside_down_factor = upside_down ? -1.0 : 1.0;
double P[3] = {
cameraPosition[0] - cameraFocalPoint[0],
cameraPosition[1] - cameraFocalPoint[1],
cameraPosition[2] - cameraFocalPoint[2]
};
double H = sqrt(P[0] * P[0] + P[1] * P[1]);
double elev = atan2(P[2], H);
double sin_elev = sin(elev);
double azi;
if (abs(sin_elev) < 0.8) {
azi = atan2(P[1], P[0]);
} else {
if (sin_elev < -0.8) {
azi = atan2(upside_down_factor * cameraViewUp[1], upside_down_factor * cameraViewUp[0]);
} else {
azi = atan2(-upside_down_factor * cameraViewUp[1], -upside_down_factor * cameraViewUp[0]);
}
}
double D = sqrt(P[0] * P[0] + P[1] * P[1] + P[2] * P[2]);
double azi_new = azi + rxf / 60.0;
double elev_new = elev + upside_down_factor * ryf / 60.0;
double Hnew = D * cos(elev_new);
double Pnew[3] = {
Hnew * cos(azi_new),
Hnew * sin(azi_new),
D * sin(elev_new)
};
double up_z = upside_down_factor * cos(elev_new);
double up_h = upside_down_factor * sin(elev_new);
double up_new[3] = {
-up_h * cos(azi_new),
-up_h * sin(azi_new),
up_z
};
double new_pos[3] = {
cameraFocalPoint[0] + Pnew[0],
cameraFocalPoint[1] + Pnew[1],
cameraFocalPoint[2] + Pnew[2]
};
camera->SetViewUp(up_new);
camera->SetPosition(new_pos);
}
camera->OrthogonalizeViewUp();
this->CameraModifyEnd(wasCameraNodeModified, true, true);
this->PreviousEventPosition[0] = eventPosition[0];
this->PreviousEventPosition[1] = eventPosition[1];
return true;
}
I particularly changed the code after
if (this->CameraTiltLocked == true)
{
camera->Azimuth(rxf);
}
else
{ # changes are made here
I hope you will find it usefull as well
The code was rewritten to C++ based on this py-file:
https://github.com/RubendeBruin/DAVE/blob/d0dec40c9a2e9416f31edabfeaf1f769fb6eca51/src/DAVE/visual_helpers/vtkBlenderLikeInteractionStyle.py#L4