|
|
|
|
|
#include "nmVTKPivotCameraInteractorStyle.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmVTKCameraController.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <vtkCamera.h>
|
|
|
|
|
|
#include <vtkMath.h>
|
|
|
|
|
|
#include <vtkObjectFactory.h>
|
|
|
|
|
|
#include <vtkRenderer.h>
|
|
|
|
|
|
#include <vtkRenderWindowInteractor.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
|
|
vtkStandardNewMacro(nmVTKPivotCameraInteractorStyle);
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
const double ROTATION_ANGLE_EPSILON = 1.0e-12;
|
|
|
|
|
|
|
|
|
|
|
|
bool isFiniteVector3(const double dVector[3])
|
|
|
|
|
|
{
|
|
|
|
|
|
return dVector != nullptr &&
|
|
|
|
|
|
vtkMath::IsFinite(dVector[0]) &&
|
|
|
|
|
|
vtkMath::IsFinite(dVector[1]) &&
|
|
|
|
|
|
vtkMath::IsFinite(dVector[2]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool rotateVector(const double dInput[3],
|
|
|
|
|
|
const double dAxis[3],
|
|
|
|
|
|
double dAngleDegrees,
|
|
|
|
|
|
double dOutput[3])
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!isFiniteVector3(dInput) || !isFiniteVector3(dAxis) ||
|
|
|
|
|
|
!vtkMath::IsFinite(dAngleDegrees) || dOutput == nullptr) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(std::fabs(dAngleDegrees) <= ROTATION_ANGLE_EPSILON) {
|
|
|
|
|
|
dOutput[0] = dInput[0];
|
|
|
|
|
|
dOutput[1] = dInput[1];
|
|
|
|
|
|
dOutput[2] = dInput[2];
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dUnitAxis[3] = {
|
|
|
|
|
|
dAxis[0], dAxis[1], dAxis[2]
|
|
|
|
|
|
};
|
|
|
|
|
|
if(vtkMath::Normalize(dUnitAxis) <= 0.0) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const double dAngleRadians =
|
|
|
|
|
|
vtkMath::RadiansFromDegrees(dAngleDegrees);
|
|
|
|
|
|
const double dCosine = std::cos(dAngleRadians);
|
|
|
|
|
|
const double dSine = std::sin(dAngleRadians);
|
|
|
|
|
|
const double dProjection = vtkMath::Dot(dUnitAxis, dInput);
|
|
|
|
|
|
double dCross[3];
|
|
|
|
|
|
vtkMath::Cross(dUnitAxis, dInput, dCross);
|
|
|
|
|
|
|
|
|
|
|
|
for(int nComponent = 0; nComponent < 3; ++nComponent) {
|
|
|
|
|
|
dOutput[nComponent] =
|
|
|
|
|
|
dInput[nComponent] * dCosine +
|
|
|
|
|
|
dCross[nComponent] * dSine +
|
|
|
|
|
|
dUnitAxis[nComponent] * dProjection *
|
|
|
|
|
|
(1.0 - dCosine);
|
|
|
|
|
|
}
|
|
|
|
|
|
return isFiniteVector3(dOutput);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool rotateCameraFrame(double dPosition[3],
|
|
|
|
|
|
double dFocalPoint[3],
|
|
|
|
|
|
double dViewUp[3],
|
|
|
|
|
|
const double dCenter[3],
|
|
|
|
|
|
const double dAxis[3],
|
|
|
|
|
|
double dAngleDegrees)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!isFiniteVector3(dPosition) ||
|
|
|
|
|
|
!isFiniteVector3(dFocalPoint) ||
|
|
|
|
|
|
!isFiniteVector3(dViewUp) ||
|
|
|
|
|
|
!isFiniteVector3(dCenter)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dRelativePosition[3];
|
|
|
|
|
|
double dRelativeFocalPoint[3];
|
|
|
|
|
|
for(int nComponent = 0; nComponent < 3; ++nComponent) {
|
|
|
|
|
|
dRelativePosition[nComponent] =
|
|
|
|
|
|
dPosition[nComponent] - dCenter[nComponent];
|
|
|
|
|
|
dRelativeFocalPoint[nComponent] =
|
|
|
|
|
|
dFocalPoint[nComponent] - dCenter[nComponent];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dRotatedPosition[3];
|
|
|
|
|
|
double dRotatedFocalPoint[3];
|
|
|
|
|
|
double dRotatedViewUp[3];
|
|
|
|
|
|
if(!rotateVector(dRelativePosition, dAxis, dAngleDegrees,
|
|
|
|
|
|
dRotatedPosition) ||
|
|
|
|
|
|
!rotateVector(dRelativeFocalPoint, dAxis, dAngleDegrees,
|
|
|
|
|
|
dRotatedFocalPoint) ||
|
|
|
|
|
|
!rotateVector(dViewUp, dAxis, dAngleDegrees,
|
|
|
|
|
|
dRotatedViewUp)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(int nComponent = 0; nComponent < 3; ++nComponent) {
|
|
|
|
|
|
dPosition[nComponent] =
|
|
|
|
|
|
dCenter[nComponent] + dRotatedPosition[nComponent];
|
|
|
|
|
|
dFocalPoint[nComponent] =
|
|
|
|
|
|
dCenter[nComponent] + dRotatedFocalPoint[nComponent];
|
|
|
|
|
|
dViewUp[nComponent] = dRotatedViewUp[nComponent];
|
|
|
|
|
|
}
|
|
|
|
|
|
return isFiniteVector3(dPosition) &&
|
|
|
|
|
|
isFiniteVector3(dFocalPoint) &&
|
|
|
|
|
|
isFiniteVector3(dViewUp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmVTKPivotCameraInteractorStyle::nmVTKPivotCameraInteractorStyle()
|
|
|
|
|
|
: m_pCameraController(nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmVTKPivotCameraInteractorStyle::~nmVTKPivotCameraInteractorStyle()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pCameraController = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmVTKPivotCameraInteractorStyle::setCameraController(
|
|
|
|
|
|
nmVTKCameraController* pController)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pCameraController = pController;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmVTKCameraController*
|
|
|
|
|
|
nmVTKPivotCameraInteractorStyle::getCameraController() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pCameraController;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmVTKPivotCameraInteractorStyle::Rotate()
|
|
|
|
|
|
{
|
|
|
|
|
|
double dCenter[3];
|
|
|
|
|
|
if(!getCurrentRotationCenter(dCenter)) {
|
|
|
|
|
|
vtkInteractorStyleTrackballCamera::Rotate();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(this->CurrentRenderer == nullptr || this->Interactor == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkCamera* pCamera = this->CurrentRenderer->GetActiveCamera();
|
|
|
|
|
|
int* pRendererSize = this->CurrentRenderer->GetSize();
|
|
|
|
|
|
int* pEventPosition = this->Interactor->GetEventPosition();
|
|
|
|
|
|
int* pLastEventPosition = this->Interactor->GetLastEventPosition();
|
|
|
|
|
|
if(pCamera == nullptr || pRendererSize == nullptr ||
|
|
|
|
|
|
pRendererSize[0] <= 0 || pRendererSize[1] <= 0 ||
|
|
|
|
|
|
pEventPosition == nullptr || pLastEventPosition == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const double dAzimuth =
|
|
|
|
|
|
(pEventPosition[0] - pLastEventPosition[0]) *
|
|
|
|
|
|
(-20.0 / pRendererSize[0]) * this->MotionFactor;
|
|
|
|
|
|
const double dElevation =
|
|
|
|
|
|
(pEventPosition[1] - pLastEventPosition[1]) *
|
|
|
|
|
|
(-20.0 / pRendererSize[1]) * this->MotionFactor;
|
|
|
|
|
|
|
|
|
|
|
|
double dPosition[3];
|
|
|
|
|
|
double dFocalPoint[3];
|
|
|
|
|
|
double dViewUp[3];
|
|
|
|
|
|
pCamera->GetPosition(dPosition);
|
|
|
|
|
|
pCamera->GetFocalPoint(dFocalPoint);
|
|
|
|
|
|
pCamera->GetViewUp(dViewUp);
|
|
|
|
|
|
|
|
|
|
|
|
if(!rotateCameraFrame(dPosition, dFocalPoint, dViewUp,
|
|
|
|
|
|
dCenter, dViewUp, dAzimuth)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// vtkCamera::Elevation 使用 (-DirectionOfProjection) x ViewUp。
|
|
|
|
|
|
double dNegativeDirection[3] = {
|
|
|
|
|
|
dPosition[0] - dFocalPoint[0],
|
|
|
|
|
|
dPosition[1] - dFocalPoint[1],
|
|
|
|
|
|
dPosition[2] - dFocalPoint[2]
|
|
|
|
|
|
};
|
|
|
|
|
|
double dElevationAxis[3];
|
|
|
|
|
|
vtkMath::Cross(dNegativeDirection, dViewUp, dElevationAxis);
|
|
|
|
|
|
if(!rotateCameraFrame(dPosition, dFocalPoint, dViewUp,
|
|
|
|
|
|
dCenter, dElevationAxis, dElevation)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
finishCameraMotion(dPosition, dFocalPoint, dViewUp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmVTKPivotCameraInteractorStyle::Spin()
|
|
|
|
|
|
{
|
|
|
|
|
|
double dCenter[3];
|
|
|
|
|
|
if(!getCurrentRotationCenter(dCenter)) {
|
|
|
|
|
|
vtkInteractorStyleTrackballCamera::Spin();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(this->CurrentRenderer == nullptr || this->Interactor == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkCamera* pCamera = this->CurrentRenderer->GetActiveCamera();
|
|
|
|
|
|
int* pEventPosition = this->Interactor->GetEventPosition();
|
|
|
|
|
|
int* pLastEventPosition = this->Interactor->GetLastEventPosition();
|
|
|
|
|
|
if(pCamera == nullptr || pEventPosition == nullptr ||
|
|
|
|
|
|
pLastEventPosition == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this->CurrentRenderer->SetWorldPoint(
|
|
|
|
|
|
dCenter[0], dCenter[1], dCenter[2], 1.0);
|
|
|
|
|
|
this->CurrentRenderer->WorldToDisplay();
|
|
|
|
|
|
const double* pDisplayCenter =
|
|
|
|
|
|
this->CurrentRenderer->GetDisplayPoint();
|
|
|
|
|
|
if(!isFiniteVector3(pDisplayCenter)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const double dNewAngle = std::atan2(
|
|
|
|
|
|
pEventPosition[1] - pDisplayCenter[1],
|
|
|
|
|
|
pEventPosition[0] - pDisplayCenter[0]);
|
|
|
|
|
|
const double dOldAngle = std::atan2(
|
|
|
|
|
|
pLastEventPosition[1] - pDisplayCenter[1],
|
|
|
|
|
|
pLastEventPosition[0] - pDisplayCenter[0]);
|
|
|
|
|
|
double dSpinAngle = vtkMath::DegreesFromRadians(
|
|
|
|
|
|
dNewAngle - dOldAngle);
|
|
|
|
|
|
if(dSpinAngle > 180.0) {
|
|
|
|
|
|
dSpinAngle -= 360.0;
|
|
|
|
|
|
} else if(dSpinAngle < -180.0) {
|
|
|
|
|
|
dSpinAngle += 360.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dPosition[3];
|
|
|
|
|
|
double dFocalPoint[3];
|
|
|
|
|
|
double dViewUp[3];
|
|
|
|
|
|
pCamera->GetPosition(dPosition);
|
|
|
|
|
|
pCamera->GetFocalPoint(dFocalPoint);
|
|
|
|
|
|
pCamera->GetViewUp(dViewUp);
|
|
|
|
|
|
double dDirectionOfProjection[3] = {
|
|
|
|
|
|
dFocalPoint[0] - dPosition[0],
|
|
|
|
|
|
dFocalPoint[1] - dPosition[1],
|
|
|
|
|
|
dFocalPoint[2] - dPosition[2]
|
|
|
|
|
|
};
|
|
|
|
|
|
if(!rotateCameraFrame(dPosition, dFocalPoint, dViewUp,
|
|
|
|
|
|
dCenter, dDirectionOfProjection,
|
|
|
|
|
|
dSpinAngle)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
finishCameraMotion(dPosition, dFocalPoint, dViewUp);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmVTKPivotCameraInteractorStyle::getCurrentRotationCenter(
|
|
|
|
|
|
double dCenter[3]) const
|
|
|
|
|
|
{
|
|
|
|
|
|
return dCenter != nullptr && m_pCameraController != nullptr &&
|
|
|
|
|
|
this->CurrentRenderer != nullptr &&
|
|
|
|
|
|
m_pCameraController->getRenderer() == this->CurrentRenderer &&
|
|
|
|
|
|
m_pCameraController->getRotationCenter(dCenter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmVTKPivotCameraInteractorStyle::finishCameraMotion(
|
|
|
|
|
|
const double dPosition[3],
|
|
|
|
|
|
const double dFocalPoint[3],
|
|
|
|
|
|
const double dViewUp[3])
|
|
|
|
|
|
{
|
|
|
|
|
|
if(this->CurrentRenderer == nullptr || this->Interactor == nullptr ||
|
|
|
|
|
|
!isFiniteVector3(dPosition) ||
|
|
|
|
|
|
!isFiniteVector3(dFocalPoint) ||
|
|
|
|
|
|
!isFiniteVector3(dViewUp)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkCamera* pCamera = this->CurrentRenderer->GetActiveCamera();
|
|
|
|
|
|
if(pCamera == nullptr) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
pCamera->SetPosition(dPosition);
|
|
|
|
|
|
pCamera->SetFocalPoint(dFocalPoint);
|
|
|
|
|
|
pCamera->SetViewUp(dViewUp);
|
|
|
|
|
|
pCamera->OrthogonalizeViewUp();
|
|
|
|
|
|
|
|
|
|
|
|
if(this->AutoAdjustCameraClippingRange != 0) {
|
|
|
|
|
|
this->CurrentRenderer->ResetCameraClippingRange();
|
|
|
|
|
|
}
|
|
|
|
|
|
if(this->Interactor->GetLightFollowCamera() != 0) {
|
|
|
|
|
|
this->CurrentRenderer->UpdateLightsGeometryToFollowCamera();
|
|
|
|
|
|
}
|
|
|
|
|
|
this->Interactor->Render();
|
|
|
|
|
|
}
|