protected double activeRate = 5.0;
protected double passiveRate = 0.01;
protected boolean doNotRotate = true;
+ private double[] upDirection = new double[] { 0, 1, 0 };
public vtkCameraAndSelectorAction(InteractiveVtkComposite panel) {
super(panel);
this.rw = panel.getRenderWindow();
this.cam = ren.GetActiveCamera();
}
+
+ public void setUpDirection(double[] upDirection) {
+ this.upDirection = upDirection;
+ }
public void Lock() {
panel.lock();
int y = e.getY();
// rotate
if (this.InteractionMode == 1) {
- cam.Azimuth(lastX - x);
- cam.Elevation(y - lastY);
+ cam.Elevation(clampElevationDelta(y - lastY));
if (doNotRotate)
- cam.SetRoll(0);
+ cam.SetViewUp(upDirection);
+ cam.Azimuth(lastX - x);
cam.OrthogonalizeViewUp();
resetCameraClippingRange();
// panel.UpdateLight();
if (this.InteractionMode == 2) {
double FPoint[];
double PPoint[];
- double APoint[] = new double[3];
+ double APoint[];
double RPoint[];
- double focalDepth;
// get the current focal point and position
FPoint = cam.GetFocalPoint();
// calculate the focal depth since we'll be using it a lot
ren.SetWorldPoint(FPoint[0], FPoint[1], FPoint[2], 1.0);
ren.WorldToDisplay();
- focalDepth = ren.GetDisplayPoint()[2];
-
- APoint[0] = rw.GetSize()[0] / 2.0 + (x - lastX);
- APoint[1] = rw.GetSize()[1] / 2.0 - (y - lastY);
- APoint[2] = focalDepth;
+ APoint = ren.GetDisplayPoint();
+
+// int[] size = rw.GetSize();
+ APoint[0] -= x - lastX;
+ APoint[1] += y - lastY;
ren.SetDisplayPoint(APoint);
ren.DisplayToWorld();
RPoint = ren.GetWorldPoint();
+
if (RPoint[3] != 0.0) {
RPoint[0] = RPoint[0] / RPoint[3];
RPoint[1] = RPoint[1] / RPoint[3];
* Compute a translation vector, moving everything 1/2 the distance to the
* cursor. (Arbitrary scale factor)
*/
- cam.SetFocalPoint((FPoint[0] - RPoint[0]) / 2.0 + FPoint[0], (FPoint[1] - RPoint[1]) / 2.0 + FPoint[1],
- (FPoint[2] - RPoint[2]) / 2.0 + FPoint[2]);
- cam.SetPosition((FPoint[0] - RPoint[0]) / 2.0 + PPoint[0], (FPoint[1] - RPoint[1]) / 2.0 + PPoint[1],
- (FPoint[2] - RPoint[2]) / 2.0 + PPoint[2]);
+ cam.SetFocalPoint(RPoint);
+ cam.SetPosition((RPoint[0] - FPoint[0]) + PPoint[0], (RPoint[1] - FPoint[1]) + PPoint[1],
+ (RPoint[2] - FPoint[2]) + PPoint[2]);
resetCameraClippingRange();
}
// zoom
zoomFactor = Math.pow(1.02, (y - lastY));
if (cam.GetParallelProjection() == 1) {
cam.SetParallelScale(cam.GetParallelScale() / zoomFactor);
+ resetCameraClippingRange();
} else {
cam.Dolly(zoomFactor);
resetCameraClippingRange();
return true;
}
+ private static double dot(double[] a, double[] b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+
+ /** Calculate change in elevation, clamped to vertical directions. */
+ private double clampElevationDelta(double elevationDelta) {
+ if (!doNotRotate)
+ return elevationDelta;
+
+ double[] direction = cam.GetDirectionOfProjection();
+ double d = Math.min(1.0, Math.max(-1.0, dot(direction, upDirection)));
+ double elevation = Math.toDegrees(Math.acos(d)) + elevationDelta;
+ if (elevation < 0)
+ elevationDelta -= elevation - 1e-5;
+ else if (elevation > 180)
+ elevationDelta -= elevation - 180 + 1e-5;
+ return elevationDelta;
+ }
+
@Override
public boolean mouseWheelMoved(MouseWheelEvent e) {
double zoomFactor;
Lock();
cam.SetFocalPoint(x, y, z);
if (doNotRotate)
- cam.SetRoll(0);
+ cam.SetViewUp(upDirection);
cam.OrthogonalizeViewUp();
resetCameraClippingRange();
// panel.UpdateLight();