2 Copyright (C) 2001, 2006 United States Government as represented by
3 the Administrator of the National Aeronautics and Space Administration.
6 package gov
.nasa
.worldwind
.view
;
8 import gov
.nasa
.worldwind
.geom
.*;
9 import gov
.nasa
.worldwind
.globes
.Globe
;
10 import gov
.nasa
.worldwind
.render
.DrawContext
;
11 import gov
.nasa
.worldwind
.util
.Logging
;
14 * @author Patrick Muris from dcollins OrbitViewModel
17 class FlatOrbitViewModel
19 private Matrix transformMatrix
= null;
21 public FlatOrbitViewModel(DrawContext dc
)
23 this(dc
, Angle
.ZERO
, Angle
.ZERO
, Angle
.ZERO
, Angle
.ZERO
, 0);
26 public FlatOrbitViewModel(DrawContext dc
,
27 Angle lookAtLatitude
, Angle lookAtLongitude
,
28 Angle heading
, Angle pitch
,
31 this(dc
, createInitTransform(
33 lookAtLatitude
, lookAtLongitude
,
38 public FlatOrbitViewModel(DrawContext dc
, Matrix transformMatrix
)
42 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
43 Logging
.logger().severe(message
);
44 throw new IllegalArgumentException(message
);
46 if (transformMatrix
== null)
48 String message
= Logging
.getMessage("nullValue.MatrixIsNull");
49 Logging
.logger().severe(message
);
50 throw new IllegalArgumentException(message
);
53 this.setTransform(dc
, transformMatrix
);
56 public Matrix
getTransformMatrix()
58 return this.transformMatrix
;
61 private void onTransformChange(DrawContext dc
, Matrix newTransformMatrix
)
65 public void setTransform(DrawContext dc
, Matrix newTransformMatrix
)
69 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
70 Logging
.logger().severe(message
);
71 throw new IllegalArgumentException(message
);
73 if (newTransformMatrix
== null)
75 String message
= Logging
.getMessage("nullValue.MatrixIsNull");
76 Logging
.logger().severe(message
);
77 throw new IllegalArgumentException(message
);
80 this.transformMatrix
= newTransformMatrix
;
81 this.onTransformChange(dc
, newTransformMatrix
);
84 public void transform(DrawContext dc
, Matrix transformMatrix
)
88 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
89 Logging
.logger().severe(message
);
90 throw new IllegalArgumentException(message
);
92 if (transformMatrix
== null)
94 String message
= Logging
.getMessage("nullValue.MatrixIsNull");
95 Logging
.logger().severe(message
);
96 throw new IllegalArgumentException(message
);
99 if (this.transformMatrix
== null)
102 Matrix newTransformMatrix
= this.transformMatrix
.multiply(transformMatrix
);
103 this.setTransform(dc
, newTransformMatrix
);
106 public void transformLatitude(DrawContext dc
, Angle amount
)
110 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
111 Logging
.logger().severe(message
);
112 throw new IllegalArgumentException(message
);
116 String message
= Logging
.getMessage("nullValue.AngleIsNull");
117 Logging
.logger().severe(message
);
118 throw new IllegalArgumentException(message
);
121 Matrix latTransform
= this.createLatitudeTransform(dc
, amount
);
122 if (latTransform
== null)
125 if (this.transformMatrix
== null)
128 // Test transform application.
129 Matrix newTransformMatrix
= this.transformMatrix
.multiply(latTransform
);
130 Vec4 center
= computeLookAtPoint(dc
, this.transformMatrix
);
131 Vec4 newCenter
= computeLookAtPoint(dc
, newTransformMatrix
);
132 Position centerPos
= dc
.getGlobe().computePositionFromPoint(center
);
133 Position newCenterPos
= dc
.getGlobe().computePositionFromPoint(newCenter
);
134 // Abort the transform when it causes model errors.
135 final double EPSILON
= 1;
136 if (Math
.abs(newCenterPos
.getLongitude().subtract(centerPos
.getLongitude()).degrees
) > EPSILON
)
139 this.transform(dc
, latTransform
);
142 public void transformLongitude(DrawContext dc
, Angle amount
)
146 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
147 Logging
.logger().severe(message
);
148 throw new IllegalArgumentException(message
);
152 String message
= Logging
.getMessage("nullValue.AngleIsNull");
153 Logging
.logger().severe(message
);
154 throw new IllegalArgumentException(message
);
157 Matrix lonTransform
= this.createLongitudeTransform(dc
, amount
);
158 if (lonTransform
== null)
161 this.transform(dc
, lonTransform
);
164 public void transformAltitude(DrawContext dc
, double amount
)
168 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
169 Logging
.logger().severe(message
);
170 throw new IllegalArgumentException(message
);
173 Matrix altTransform
= this.createAltitudeTransform(dc
, amount
);
174 if (altTransform
== null)
177 this.transform(dc
, altTransform
);
180 public void transformHeading(DrawContext dc
, Angle amount
)
184 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
185 Logging
.logger().severe(message
);
186 throw new IllegalArgumentException(message
);
190 String message
= Logging
.getMessage("nullValue.AngleIsNull");
191 Logging
.logger().severe(message
);
192 throw new IllegalArgumentException(message
);
195 Matrix headingTransform
= this.createHeadingTransform(dc
, amount
);
196 if (headingTransform
== null)
199 this.transform(dc
, headingTransform
);
202 public void transformPitch(DrawContext dc
, Angle amount
)
206 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
207 Logging
.logger().severe(message
);
208 throw new IllegalArgumentException(message
);
212 String message
= Logging
.getMessage("nullValue.AngleIsNull");
213 Logging
.logger().severe(message
);
214 throw new IllegalArgumentException(message
);
217 Matrix pitchTransform
= this.createPitchTransform(dc
, amount
);
218 if (pitchTransform
== null)
221 if (this.transformMatrix
== null)
224 // Test transform application.
225 Matrix newTransformMatrix
= this.transformMatrix
.multiply(pitchTransform
);
226 Vec4 centerVec
= computeLookAtPoint(dc
, this.transformMatrix
);
227 Vec4 newHeading
= computeHeadingVector(newTransformMatrix
, centerVec
);
228 Vec4 newForward
= Vec4
.UNIT_NEGATIVE_Z
.transformBy3(newTransformMatrix
.getInverse());
229 // Abort the transform when it causes model errors.
230 if (newHeading
.dot3(newForward
) < 0)
233 this.transform(dc
, pitchTransform
);
236 public void transformZoom(DrawContext dc
, double amount
)
240 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
241 Logging
.logger().severe(message
);
242 throw new IllegalArgumentException(message
);
245 Matrix zoomTransform
= this.createZoomTransform(dc
, amount
);
246 if (zoomTransform
== null)
249 this.transform(dc
, zoomTransform
);
252 public Quaternion
getRotation()
254 return Quaternion
.fromMatrix(this.transformMatrix
);
257 public void setRotation(DrawContext dc
, Quaternion newRotation
)
261 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
262 Logging
.logger().severe(message
);
263 throw new IllegalArgumentException(message
);
265 if (newRotation
== null)
267 String message
= Logging
.getMessage("nullValue.QuaternionIsNull");
268 Logging
.logger().severe(message
);
269 throw new IllegalArgumentException(message
);
272 if (this.transformMatrix
== null)
275 Matrix posMatrix
= Matrix
.fromTranslation(
276 this.transformMatrix
.m14
,
277 this.transformMatrix
.m24
,
278 this.transformMatrix
.m34
);
279 Matrix rotMatrix
= Matrix
.fromQuaternion(newRotation
);
280 Matrix newTransformMatrix
= posMatrix
.multiply(rotMatrix
);
281 this.setTransform(dc
, newTransformMatrix
);
284 public void transformRotation(DrawContext dc
, Quaternion rotation
)
288 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
289 Logging
.logger().severe(message
);
290 throw new IllegalArgumentException(message
);
292 if (rotation
== null)
294 String message
= Logging
.getMessage("nullValue.QuaternionIsNull");
295 Logging
.logger().severe(message
);
296 throw new IllegalArgumentException(message
);
299 Quaternion transformRotation
= Quaternion
.fromMatrix(this.transformMatrix
);
300 Quaternion newTransformRotation
= transformRotation
.multiply(rotation
);
301 this.setRotation(dc
, newTransformRotation
);
304 // ============== Model Transforms ======================= //
305 // ============== Model Transforms ======================= //
306 // ============== Model Transforms ======================= //
308 private static Matrix
createInitTransform(
310 Angle lookAtLatitude
, Angle lookAtLongitude
,
311 Angle heading
, Angle pitch
,
315 || dc
.getGlobe() == null
316 || lookAtLatitude
== null
317 || lookAtLongitude
== null
322 Globe globe
= dc
.getGlobe();
323 // Vec4 globeOrigin = globe.getCenter();
324 Matrix initTransform
= Matrix
.IDENTITY
;
325 // Not sure why this isn't necessary, but when globeOrigin!=0 View is still centered on the Globe,
326 // without this code.
327 // initTransform = initTransform.multiply(Matrix.fromTranslation(
331 // Flat sea level at zero on z, no need to move from globe center to surface
332 // initTransform = initTransform.multiply(Matrix.fromTranslation(
335 // 0.0 - globe.getRadiusAt(lookAtLatitude, lookAtLongitude)));
336 initTransform
= initTransform
.multiply(Matrix
.fromRotationX(heading
.multiply(-1)));
337 initTransform
= initTransform
.multiply(Matrix
.fromRotationZ(pitch
));
338 initTransform
= initTransform
.multiply(Matrix
.fromTranslation(
342 // Use translation for lat/lon placement
343 Vec4 lookAtPoint
= globe
.computePointFromPosition(lookAtLatitude
, lookAtLongitude
, 0);
344 initTransform
= initTransform
.multiply(Matrix
.fromTranslation(
345 -lookAtPoint
.x
, -lookAtPoint
.y
, -lookAtPoint
.z
));
347 return initTransform
;
350 // TODO: use translation on y (OK)
351 public Matrix
createLatitudeTransform(DrawContext dc
, Angle amount
)
355 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
356 Logging
.logger().severe(message
);
357 throw new IllegalArgumentException(message
);
361 String message
= Logging
.getMessage("nullValue.AngleIsNull");
362 Logging
.logger().severe(message
);
363 throw new IllegalArgumentException(message
);
366 Vec4 delta
= dc
.getGlobe().computePointFromPosition(amount
, Angle
.ZERO
, 0);
367 return Matrix
.fromTranslation(-delta
.x
, -delta
.y
, -delta
.z
);
370 // TODO: use translation on x (OK)
371 public Matrix
createLongitudeTransform(DrawContext dc
, Angle amount
)
375 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
376 Logging
.logger().severe(message
);
377 throw new IllegalArgumentException(message
);
381 String message
= Logging
.getMessage("nullValue.AngleIsNull");
382 Logging
.logger().severe(message
);
383 throw new IllegalArgumentException(message
);
386 Vec4 delta
= dc
.getGlobe().computePointFromPosition(Angle
.ZERO
, amount
, 0);
387 return Matrix
.fromTranslation(-delta
.x
, -delta
.y
, -delta
.z
);
389 // TODO: use translation on z (OK)
390 public Matrix
createAltitudeTransform(DrawContext dc
, double amount
)
394 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
395 Logging
.logger().severe(message
);
396 throw new IllegalArgumentException(message
);
399 return Matrix
.fromTranslation(0, 0, amount
);
402 public Matrix
createHeadingTransform(DrawContext dc
, Angle amount
)
406 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
407 Logging
.logger().severe(message
);
408 throw new IllegalArgumentException(message
);
412 String message
= Logging
.getMessage("nullValue.AngleIsNull");
413 Logging
.logger().severe(message
);
414 throw new IllegalArgumentException(message
);
417 Vec4 centerVec
= this.getLookAtVector(dc
);
418 if (centerVec
== null)
421 Vec4 axis
= Vec4
.UNIT_Z
; // TODO: use globe normal (OK)
422 Matrix axisAngleTransform
= Matrix
.fromAxisAngle(amount
, axis
);
423 return this.createTransformAboutPivot(axisAngleTransform
, centerVec
);
426 public Matrix
createPitchTransform(DrawContext dc
, Angle amount
)
430 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
431 Logging
.logger().severe(message
);
432 throw new IllegalArgumentException(message
);
436 String message
= Logging
.getMessage("nullValue.AngleIsNull");
437 Logging
.logger().severe(message
);
438 throw new IllegalArgumentException(message
);
441 if (this.transformMatrix
== null)
444 Vec4 centerVec
= this.getLookAtVector(dc
);
445 if (centerVec
== null)
448 Vec4 axis
= Vec4
.UNIT_X
.transformBy3(this.transformMatrix
.getInverse());
449 Matrix axisAngleTransform
= Matrix
.fromAxisAngle(amount
.multiply(-1), axis
);
450 return this.createTransformAboutPivot(axisAngleTransform
, centerVec
);
453 public Matrix
createZoomTransform(DrawContext dc
, double amount
)
457 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
458 Logging
.logger().severe(message
);
459 throw new IllegalArgumentException(message
);
462 if (this.transformMatrix
== null)
465 Vec4 zoomVec
= Vec4
.UNIT_NEGATIVE_Z
.transformBy3(this.transformMatrix
.getInverse());
466 zoomVec
= zoomVec
.normalize3();
467 zoomVec
= zoomVec
.multiply3(amount
);
468 return Matrix
.fromTranslation(zoomVec
);
471 private Matrix
createTransformAboutPivot(Matrix transform
, Vec4 pivot
)
473 if (transform
== null || pivot
== null)
476 Matrix matrix
= Matrix
.IDENTITY
;
477 matrix
= matrix
.multiply(Matrix
.fromTranslation(pivot
.x
, pivot
.y
, pivot
.z
));
478 matrix
= matrix
.multiply(transform
);
479 matrix
= matrix
.multiply(Matrix
.fromTranslation(-pivot
.x
, -pivot
.y
, -pivot
.z
));
483 // ============== Rotation Transforms ======================= //
484 // ============== Rotation Transforms ======================= //
485 // ============== Rotation Transforms ======================= //
487 // TODO: return no rotation or use globe normal (OK)
488 public Quaternion
createRotationBetweenPositions(DrawContext dc
, Position beginPosition
, Position endPosition
)
492 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
493 Logging
.logger().severe(message
);
494 throw new IllegalArgumentException(message
);
496 if (beginPosition
== null || endPosition
== null)
498 String message
= Logging
.getMessage("nullValue.PositionIsNull");
499 Logging
.logger().severe(message
);
500 throw new IllegalArgumentException(message
);
503 Globe globe = dc.getGlobe();
507 Vec4 beginPoint = globe.computePointFromPosition(beginPosition);
508 Vec4 endPoint = globe.computePointFromPosition(endPosition);
509 if (beginPoint == null || endPoint == null)
512 Angle angle = beginPoint.angleBetween3(endPoint);
516 Vec4 axis = beginPoint.cross3(endPoint);
517 return Quaternion.fromAxisAngle(angle, axis);
519 return Quaternion
.IDENTITY
;
522 public Quaternion
createRotationForward(DrawContext dc
, Angle amount
)
526 String message
= Logging
.getMessage("nullValue.AngleIsNull");
527 Logging
.logger().severe(message
);
528 throw new IllegalArgumentException(message
);
531 if (this.transformMatrix
== null)
534 Vec4 xAxis
= Vec4
.UNIT_X
.transformBy3(this.transformMatrix
.getInverse());
535 return Quaternion
.fromAxisAngle(amount
, xAxis
);
538 public Quaternion
createRotationRight(DrawContext dc
, Angle amount
)
542 String message
= Logging
.getMessage("nullValue.AngleIsNull");
543 Logging
.logger().severe(message
);
544 throw new IllegalArgumentException(message
);
547 if (this.transformMatrix
== null)
550 Vec4 xAxis
= Vec4
.UNIT_X
.transformBy3(this.transformMatrix
.getInverse());
551 Vec4 centerVec
= this.getLookAtVector(dc
);
552 centerVec
= centerVec
.normalize3();
553 Vec4 yAxisNoTilt
= centerVec
.cross3(xAxis
);
554 return Quaternion
.fromAxisAngle(amount
.multiply(-1), yAxisNoTilt
);
557 // ============== Viewing Attributes ======================= //
558 // ============== Viewing Attributes ======================= //
559 // ============== Viewing Attributes ======================= //
561 public Vec4
getEyeVector()
563 if (this.transformMatrix
== null)
566 return Vec4
.UNIT_W
.transformBy4(this.transformMatrix
.getInverse());
569 public Position
getEyePosition(DrawContext dc
)
573 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
574 Logging
.logger().severe(message
);
575 throw new IllegalArgumentException(message
);
578 Vec4 eyeVec
= this.getEyeVector();
582 if (dc
.getGlobe() == null)
585 return dc
.getGlobe().computePositionFromPoint(eyeVec
);
588 public Vec4
getLookAtVector(DrawContext dc
)
592 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
593 Logging
.logger().severe(message
);
594 throw new IllegalArgumentException(message
);
597 if (this.transformMatrix
== null)
600 return computeLookAtPoint(dc
, this.transformMatrix
);
603 public Position
getLookAtPosition(DrawContext dc
)
607 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
608 Logging
.logger().severe(message
);
609 throw new IllegalArgumentException(message
);
612 Vec4 centerVec
= this.getLookAtVector(dc
);
613 if (centerVec
== null)
616 if (dc
.getGlobe() == null)
619 return dc
.getGlobe().computePositionFromPoint(centerVec
);
622 public Angle
getHeading(DrawContext dc
)
626 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
627 Logging
.logger().severe(message
);
628 throw new IllegalArgumentException(message
);
631 if (this.transformMatrix
== null)
634 Vec4 centerVec
= this.getLookAtVector(dc
);
635 if (centerVec
== null)
638 HeadingCoordinates headingCoordinates
= computeHeadingCoordinates(centerVec
);
639 if (headingCoordinates
== null)
642 return computeHeading(headingCoordinates
, this.transformMatrix
, centerVec
);
645 public Angle
getPitch(DrawContext dc
)
649 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
650 Logging
.logger().severe(message
);
651 throw new IllegalArgumentException(message
);
654 if (this.transformMatrix
== null)
657 Vec4 centerVec
= this.getLookAtVector(dc
);
658 if (centerVec
== null)
661 return computePitch(this.transformMatrix
, centerVec
);
664 public Double
getZoom(DrawContext dc
)
668 String message
= Logging
.getMessage("nullValue.DrawContextIsNull");
669 Logging
.logger().severe(message
);
670 throw new IllegalArgumentException(message
);
673 if (this.transformMatrix
== null)
676 Vec4 centerVec
= this.getLookAtVector(dc
);
677 if (centerVec
== null)
680 return computeZoom(this.transformMatrix
, centerVec
);
683 // ============== Attribute Computation Support ======================= //
684 // ============== Attribute Computation Support ======================= //
685 // ============== Attribute Computation Support ======================= //
687 private static Vec4
computeLookAtPoint(DrawContext dc
, Matrix transformMatrix
)
690 || dc
.getGlobe() == null
691 || transformMatrix
== null)
694 Globe globe
= dc
.getGlobe();
695 Vec4 eyeVec
= Vec4
.UNIT_W
.transformBy4(transformMatrix
.getInverse());
696 Vec4 forwardVec
= Vec4
.UNIT_NEGATIVE_Z
.transformBy3(transformMatrix
.getInverse());
697 forwardVec
= forwardVec
.normalize3();
699 Position centerPos
= globe
.getIntersectionPosition(new Line(eyeVec
, forwardVec
));
700 if (centerPos
!= null)
702 Angle centerLat
= centerPos
.getLatitude();
703 Angle centerLon
= centerPos
.getLongitude();
704 double centerElevation
= dc
.getVerticalExaggeration() * globe
.getElevation(centerLat
, centerLon
);
705 return globe
.computePointFromPosition(centerLat
, centerLon
, centerElevation
);
708 return computeHorizonPoint(globe
, transformMatrix
);
711 // TODO: adapt to flat globe
712 private static Vec4
computeHorizonPoint(Globe globe
, Matrix transformMatrix
)
714 if (globe
== null || transformMatrix
== null)
717 Vec4 globeOrigin
= globe
.getCenter();
718 Vec4 eyeVec
= Vec4
.UNIT_W
.transformBy4(transformMatrix
.getInverse());
719 Vec4 forward
= Vec4
.UNIT_NEGATIVE_Z
.transformBy3(transformMatrix
.getInverse());
720 Vec4 origin_sub_eye
= globeOrigin
.subtract3(eyeVec
);
722 double r
= globe
.getRadius();
723 double dSquared
= origin_sub_eye
.getLengthSquared3() - (r
* r
);
727 double d
= Math
.sqrt(dSquared
);
728 return forward
.normalize3().multiply3(d
).add3(eyeVec
);
731 private static Angle
computeHeading(HeadingCoordinates headingCoords
, Matrix transformMatrix
, Vec4 lookAtPoint
)
733 if (headingCoords
== null
734 || transformMatrix
== null
735 || lookAtPoint
== null)
738 Vec4 headingVec
= computeHeadingVector(transformMatrix
, lookAtPoint
);
739 if (headingVec
== null)
742 double dot
= headingCoords
.northVec
.dot3(headingVec
);
743 // Compute the sum of magnitudes.
744 double length
= headingCoords
.northVec
.getLength3() * headingVec
.getLength3();
745 // Normalize the dot product, if necessary.
746 if ((length
!= 0) && (length
!= 1.0))
749 if (dot
< -1) // Angle is positive 180.
753 else if (dot
> 1) // Angle is zero.
758 double degrees
= Math
.toDegrees(Math
.acos(dot
));
759 if (Double
.isNaN(degrees
))
762 if (headingCoords
.eastVec
.dot3(headingVec
) < 0)
763 degrees
= 360 - degrees
;
765 // Collapses duplicate values for North heading.
769 return Angle
.fromDegrees(degrees
);
772 private static class HeadingCoordinates
774 public final Vec4 northVec
;
775 public final Vec4 eastVec
;
777 public HeadingCoordinates(Vec4 northVec
, Vec4 eastVec
)
779 this.northVec
= northVec
;
780 this.eastVec
= eastVec
;
784 private static HeadingCoordinates
computeHeadingCoordinates(Vec4 lookAtPoint
)
786 if (lookAtPoint
== null)
789 Vec4 surfaceNormal
= Vec4
.UNIT_Z
; // TODO: get globe normal (OK)
790 Vec4 y_sub_normal
= Vec4
.UNIT_Y
.subtract3(surfaceNormal
);
791 y_sub_normal
= y_sub_normal
.normalize3();
792 Vec4 eastVec
= y_sub_normal
.cross3(surfaceNormal
);
793 Vec4 northVec
= surfaceNormal
.cross3(eastVec
);
794 eastVec
= northVec
.cross3(surfaceNormal
);
796 return new HeadingCoordinates(northVec
, eastVec
);
799 private static Vec4
computeHeadingVector(Matrix transformMatrix
, Vec4 surfacePoint
)
801 if (transformMatrix
== null || surfacePoint
== null)
804 Vec4 surfaceNormal
= Vec4
.UNIT_Z
; // TODO: get globe normal (OK)
805 Vec4 forward
= Vec4
.UNIT_NEGATIVE_Z
.transformBy3(transformMatrix
.getInverse());
806 Vec4 up
= Vec4
.UNIT_Y
.transformBy3(transformMatrix
.getInverse());
808 final double EPSILON
= 0.1;
809 Vec4 heading
= forward
.cross3(surfaceNormal
);
810 if (heading
.getLength3() < EPSILON
)
811 heading
= up
.cross3(surfaceNormal
);
812 heading
= surfaceNormal
.cross3(heading
);
813 heading
= heading
.normalize3();
818 private static Angle
computePitch(Matrix transformMatrix
, Vec4 lookAtPoint
)
820 if (transformMatrix
== null || lookAtPoint
== null)
823 Vec4 surfaceNormal
= Vec4
.UNIT_Z
; // TODO: get globe normal
824 Vec4 forward
= Vec4
.UNIT_Z
.transformBy3(transformMatrix
.getInverse());
825 forward
= forward
.normalize3();
827 double dot
= surfaceNormal
.dot3(forward
);
828 // Compute the sum of magnitudes.
829 double length
= surfaceNormal
.getLength3() * forward
.getLength3();
830 // Normalize the dot product, if necessary.
831 if ((length
!= 0) && (length
!= 1))
834 if (dot
<= 0) // Angle is positive 90.
838 else if (dot
>= 1) // Angle is zero.
842 else // Angle is arc-cosine of dot product.
844 double radians
= Math
.acos(dot
);
845 if (!Double
.isNaN(radians
))
846 return Angle
.fromRadians(radians
);
852 private static Double
computeZoom(Matrix transformMatrix
, Vec4 lookAtPoint
)
854 if (transformMatrix
== null || lookAtPoint
== null)
857 Vec4 eyeVec
= Vec4
.UNIT_W
.transformBy4(transformMatrix
.getInverse());
858 return lookAtPoint
.subtract3(eyeVec
).getLength3();
861 // private static class SurfaceAttributes
863 // public final Vec4 center;
864 // public final Position centerPos;
865 // public final Vec4 north;
866 // public final Vec4 east;
868 // public SurfaceAttributes(Vec4 centerVec, Position centerPos, Vec4 headingUp, Vec4 headingRight)
870 // this.center = centerVec;
871 // this.centerPos = centerPos;
872 // this.north = headingUp;
873 // this.east = headingRight;
877 // private static SurfaceAttributes computeSurfaceAttributes(DrawContext dc, Matrix transformMatrix)
879 // if (dc == null || dc.getGlobe() == null)
882 // if (transformMatrix == null)
885 // Globe globe = dc.getGlobe();
886 // Vec4 eyeVec = Vec4.UNIT_W.transformBy4(transformMatrix.getInverse());
887 // Vec4 forwardVec = Vec4.UNIT_NEGATIVE_Z.transformBy3(transformMatrix.getInverse());
888 // forwardVec = forwardVec.normalize3();
891 // Position centerPos = globe.getIntersectionPosition(new Line(eyeVec, forwardVec));
892 // if (centerPos != null)
894 // Angle centerLat = centerPos.getLatitude();
895 // Angle centerLon = centerPos.getLongitude();
896 // double centerElevation = dc.getVerticalExaggeration() * globe.getElevation(centerLat, centerLon);
897 // centerVec = globe.computePointFromPosition(centerLat, centerLon, centerElevation);
901 // centerVec = computeHorizonPoint(globe, transformMatrix);
902 // centerPos = globe.computePositionFromPoint(centerVec);
905 // if (centerVec == null)
908 // Vec4 normalVec = centerVec.normalize3();
910 // Vec4 y_sub_normal = Vec4.UNIT_Y.subtract3(normalVec);
911 // y_sub_normal = y_sub_normal.normalize3();
912 // Vec4 headingRight = y_sub_normal.cross3(normalVec);
913 // Vec4 headingUp = normalVec.cross3(headingRight);
914 // headingRight = headingUp.cross3(normalVec);
916 // return new SurfaceAttributes(centerVec, centerPos, headingUp.normalize3(), headingRight.normalize3());