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
.geom
;
8 import gov
.nasa
.worldwind
.*;
10 import java
.util
.logging
.Level
;
13 * @author Paul Collins
14 * @version $Id: ViewFrustum.java 1774 2007-05-08 01:03:37Z dcollins $
16 public class ViewFrustum
18 private final Frustum frustum
;
19 private final Matrix4 projection
;
20 // private java.awt.geom.Rectangle2D nearRect;
21 // private java.awt.geom.Rectangle2D farRect;
23 public ViewFrustum(Matrix4 projectionMatrix
)
25 if (projectionMatrix
== null)
27 String message
= WorldWind
.retrieveErrMsg("nullValue.MatrixIsNull");
28 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
29 throw new IllegalArgumentException(message
);
32 double[] m
= projectionMatrix
.getEntries();
33 // Extract the near clipping plane from the projection-matrix.
34 double nearMag
= Math
.sqrt((m
[3] + m
[2]) * (m
[3] + m
[2]) + (m
[7] + m
[6]) * (m
[7] + m
[6])
35 + (m
[11] + m
[10]) * (m
[11] + m
[10]));
36 Plane nearPlane
= new Plane((m
[3] + m
[2]) / nearMag
, (m
[7] + m
[6]) / nearMag
, (m
[11] + m
[10]) / nearMag
,
38 // Extract the far clipping plane from the projection-matrix.
39 double farMag
= Math
.sqrt((m
[3] - m
[2]) * (m
[3] - m
[2]) + (m
[7] - m
[6]) * (m
[7] - m
[6])
40 + (m
[11] - m
[10]) * (m
[11] - m
[10]));
41 Plane farPlane
= new Plane((m
[3] - m
[2]) / farMag
, (m
[7] - m
[6]) / farMag
, (m
[11] - m
[10]) / farMag
,
43 // Extract the left clipping plane from the projection-matrix.
44 double leftMag
= Math
.sqrt((m
[3] + m
[0]) * (m
[3] + m
[0]) + (m
[7] + m
[4]) * (m
[7] + m
[4])
45 + (m
[11] + m
[8]) * (m
[11] + m
[8]));
46 Plane leftPlane
= new Plane((m
[3] + m
[0]) / leftMag
, (m
[7] + m
[4]) / leftMag
, (m
[11] + m
[8]) / leftMag
,
48 // Extract the right clipping plane from the projection-matrix.
49 double rightMag
= Math
.sqrt((m
[3] - m
[0]) * (m
[3] - m
[0]) + (m
[7] - m
[4]) * (m
[7] - m
[4])
50 + (m
[11] - m
[8]) * (m
[11] - m
[8]));
51 Plane rightPlane
= new Plane((m
[3] - m
[0]) / rightMag
, (m
[7] - m
[4]) / rightMag
, (m
[11] - m
[8]) / rightMag
,
53 // Extract the bottom clipping plane from the projection-matrix.
54 double bottomMag
= Math
.sqrt((m
[3] + m
[1]) * (m
[3] + m
[1]) + (m
[7] + m
[5]) * (m
[7] + m
[5])
55 + (m
[11] + m
[9]) * (m
[11] + m
[9]));
56 Plane bottomPlane
= new Plane((m
[3] + m
[1]) / bottomMag
, (m
[7] + m
[5]) / bottomMag
, (m
[11] + m
[9]) / bottomMag
,
58 // Extract the top clipping plane from the projection-matrix.
59 double topMag
= Math
.sqrt((m
[3] - m
[1]) * (m
[3] - m
[1]) + (m
[7] - m
[5]) * (m
[7] - m
[5])
60 + (m
[11] - m
[9]) * (m
[11] - m
[9]));
61 Plane topPlane
= new Plane((m
[3] - m
[1]) / topMag
, (m
[7] - m
[5]) / topMag
, (m
[11] - m
[9]) / topMag
,
63 this.frustum
= new Frustum(nearPlane
, farPlane
, leftPlane
, rightPlane
, bottomPlane
, topPlane
);
64 this.projection
= projectionMatrix
;
68 * Creates a <code>Frustum</code> from a horizontal field-of-view, viewport aspect ratio and distance to near and
69 * far depth clipping planes. The near plane must be closer than the far plane, and both planes must be a positive
72 * @param fieldOfView horizontal field-of-view angle in the range (0, 180)
73 * @param viewportWidth the width of the viewport in screen pixels
74 * @param viewportHeight the height of the viewport in screen pixels
75 * @param near distance to the near depth clipping plane
76 * @param far distance to far depth clipping plane
77 * @throws IllegalArgumentException if fov is not in the range (0, 180), if either near or far are negative, or near
78 * is greater than or equal to far
80 public ViewFrustum(Angle fieldOfView
, int viewportWidth
, int viewportHeight
, double near
, double far
)
82 if (fieldOfView
== null)
84 String message
= WorldWind
.retrieveErrMsg("geom.ViewFrustum.FieldOfViewIsNull");
85 WorldWind
.logger().log(Level
.FINE
, message
);
86 throw new IllegalArgumentException(message
);
88 double fov
= fieldOfView
.getDegrees();
89 double farMinusNear
= far
- near
;
90 String message
= null;
91 if (fov
<= 0 || fov
> 180)
92 message
= WorldWind
.retrieveErrMsg("geom.ViewFrustum.FieldOfViewOutOfRange");
93 if (near
<= 0 || farMinusNear
<= 0)
94 message
= WorldWind
.retrieveErrMsg("geom.ViewFrusutm.ClippingDistanceOutOfRange");
97 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, message
);
98 throw new IllegalArgumentException(message
);
101 double focalLength
= 1d
/ fieldOfView
.tanHalfAngle();
102 double aspect
= viewportHeight
/ (double) viewportWidth
;
103 double lrLen
= Math
.sqrt(focalLength
* focalLength
+ 1);
104 double btLen
= Math
.sqrt(focalLength
* focalLength
+ aspect
* aspect
);
105 Plane nearPlane
= new Plane(0d
, 0d
, 0d
- 1d
, 0d
- near
);
106 Plane farPlane
= new Plane(0d
, 0d
, 1d
, far
);
107 Plane leftPlane
= new Plane(focalLength
/ lrLen
, 0d
, 0d
- 1d
/ lrLen
, 0);
108 Plane rightPlane
= new Plane(0d
- focalLength
/ lrLen
, 0d
, 0d
- 1d
/ lrLen
, 0d
);
109 Plane bottomPlane
= new Plane(0d
, focalLength
/ btLen
, 0d
- aspect
/ btLen
, 0d
);
110 Plane topPlane
= new Plane(0d
, 0d
- focalLength
/ btLen
, 0d
- aspect
/ btLen
, 0d
);
111 double[] projectionMatrix
= new double[] {
112 focalLength
, 0d
, 0d
, 0d
,
113 0d
, focalLength
/ aspect
, 0d
, 0d
,
114 0d
, 0d
, 0d
- (far
+ near
) / farMinusNear
, 0d
- 1d
,
115 0d
, 0d
, 0d
- (2d
* far
* near
) / farMinusNear
, 0d
117 this.frustum
= new Frustum(nearPlane
, farPlane
, leftPlane
, rightPlane
, bottomPlane
, topPlane
);
118 this.projection
= new Matrix4(projectionMatrix
);
122 * Creates a <code>Frustum</code> from three sets of parallel clipping planes (a parallel projection). In this case,
123 * the near and far depth clipping planes may be a negative distance away.
125 * @param left distance to the left vertical clipping plane
126 * @param right distance to the right vertical clipping plane
127 * @param bottom distance to the bottom horizontal clipping plane
128 * @param top distance to the top horizontal clipping plane
129 * @param near distance to the near depth clipping plane
130 * @param far distance to far depth clipping plane
131 * @throws IllegalArgumentException if the difference of any plane set (lright - left, top - bottom, far - near) is
132 * less than or equal to zero.
134 public ViewFrustum(double near
, double far
, double left
, double right
, double bottom
,
137 double farMinusNear
= far
- near
;
138 double rightMinusLeft
= right
- left
;
139 double topMinusBottom
= top
- bottom
;
140 if (rightMinusLeft
<= 0 || topMinusBottom
<= 0 || farMinusNear
<= 0)
142 String message
= WorldWind
.retrieveErrMsg("geom.ViewFrusutm.ClippingDistanceOutOfRange");
143 WorldWind
.logger().log(Level
.FINE
, message
);
144 throw new IllegalArgumentException(message
);
147 Plane nearPlane
= new Plane(0d
, 0d
, 0d
- 1d
, near
< 0d ? near
: 0d
- near
);
148 Plane farPlane
= new Plane(0d
, 0d
, 1d
, far
< 0d ?
0d
- far
: far
);
149 Plane leftPlane
= new Plane(1d
, 0d
, 0d
, left
< 0d ? left
: 0d
- left
);
150 Plane rightPlane
= new Plane(0d
- 1d
, 0d
, 0d
, right
< 0d ?
0d
- right
: right
);
151 Plane bottomPlane
= new Plane(0d
, 1d
, 0d
, bottom
< 0d ? bottom
: 0d
- bottom
);
152 Plane topPlane
= new Plane(0d
, 0d
- 1d
, 0d
, top
< 0d ?
0d
- top
: top
);
153 double[] projectionMatrix
= new double[] {
154 2d
/ rightMinusLeft
, 0d
, 0d
, 0d
- (right
+ left
) / rightMinusLeft
,
155 0d
, 0d
/ topMinusBottom
, 0d
, 0d
- (top
+ bottom
) / topMinusBottom
,
156 0d
, 0d
, 0d
- 2d
/ farMinusNear
, 0d
- (far
+ near
) / farMinusNear
,
159 this.frustum
= new Frustum(nearPlane
, farPlane
, leftPlane
, rightPlane
, bottomPlane
, topPlane
);
160 this.projection
= new Matrix4(projectionMatrix
);
163 public final Frustum
getFrustum()
168 public final Matrix4
getProjectionMatrix()
170 return this.projection
;
173 // public final java.awt.geom.Rectangle2D getNearRectangle()
175 // return this.nearRect;
178 // public final java.awt.geom.Rectangle2D getFarRectangle()
180 // return this.farRect;