@@ -4,6 +4,7 @@ import Check from './Check.js';
4
4
import defaultValue from './defaultValue.js' ;
5
5
import defined from './defined.js' ;
6
6
import defineProperties from './defineProperties.js' ;
7
+ import Ellipsoid from './Ellipsoid.js' ;
7
8
import Rectangle from './Rectangle.js' ;
8
9
9
10
/**
@@ -96,7 +97,7 @@ import Rectangle from './Rectangle.js';
96
97
EllipsoidalOccluder . prototype . isPointVisible = function ( occludee ) {
97
98
var ellipsoid = this . _ellipsoid ;
98
99
var occludeeScaledSpacePosition = ellipsoid . transformPositionToScaledSpace ( occludee , scratchCartesian ) ;
99
- return this . isScaledSpacePointVisible ( occludeeScaledSpacePosition ) ;
100
+ return isScaledSpacePointVisible ( occludeeScaledSpacePosition , this . _cameraPositionInScaledSpace , this . _distanceToLimbInScaledSpaceSquared ) ;
100
101
} ;
101
102
102
103
/**
@@ -116,16 +117,39 @@ import Rectangle from './Rectangle.js';
116
117
* occluder.isScaledSpacePointVisible(scaledSpacePoint); //returns true
117
118
*/
118
119
EllipsoidalOccluder . prototype . isScaledSpacePointVisible = function ( occludeeScaledSpacePosition ) {
119
- // See https://cesium.com/blog/2013/04/25/Horizon-culling/
120
- var cv = this . _cameraPositionInScaledSpace ;
121
- var vhMagnitudeSquared = this . _distanceToLimbInScaledSpaceSquared ;
122
- var vt = Cartesian3 . subtract ( occludeeScaledSpacePosition , cv , scratchCartesian ) ;
123
- var vtDotVc = - Cartesian3 . dot ( vt , cv ) ;
124
- // If vhMagnitudeSquared < 0 then we are below the surface of the ellipsoid and
125
- // in this case, set the culling plane to be on V.
126
- var isOccluded = vhMagnitudeSquared < 0 ? vtDotVc > 0 : ( vtDotVc > vhMagnitudeSquared &&
127
- vtDotVc * vtDotVc / Cartesian3 . magnitudeSquared ( vt ) > vhMagnitudeSquared ) ;
128
- return ! isOccluded ;
120
+ return isScaledSpacePointVisible ( occludeeScaledSpacePosition , this . _cameraPositionInScaledSpace , this . _distanceToLimbInScaledSpaceSquared ) ;
121
+ } ;
122
+
123
+ var scratchCameraPositionInScaledSpaceShrunk = new Cartesian3 ( ) ;
124
+
125
+ /**
126
+ * Similar to {@link EllipsoidalOccluder#isScaledSpacePointVisible} except tests against an
127
+ * ellipsoid that has been shrunk by the minimum height when the minimum height is below
128
+ * the ellipsoid. This is intended to be used with points generated by
129
+ * {@link EllipsoidalOccluder#computeHorizonCullingPointPossiblyUnderEllipsoid} or
130
+ * {@link EllipsoidalOccluder#computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid}.
131
+ *
132
+ * @param {Cartesian3 } occludeeScaledSpacePosition The point to test for visibility, represented in the scaled space of the possibly-shrunk ellipsoid.
133
+ * @returns {Boolean } <code>true</code> if the occludee is visible; otherwise <code>false</code>.
134
+ */
135
+ EllipsoidalOccluder . prototype . isScaledSpacePointVisiblePossiblyUnderEllipsoid = function ( occludeeScaledSpacePosition , minimumHeight ) {
136
+ var ellipsoid = this . _ellipsoid ;
137
+ var vhMagnitudeSquared ;
138
+ var cv ;
139
+
140
+ if ( defined ( minimumHeight ) && minimumHeight < 0.0 && ellipsoid . minimumRadius > - minimumHeight ) {
141
+ // This code is similar to the cameraPosition setter, but unrolled for performance because it will be called a lot.
142
+ cv = scratchCameraPositionInScaledSpaceShrunk ;
143
+ cv . x = this . _cameraPosition . x / ( ellipsoid . radii . x + minimumHeight ) ;
144
+ cv . y = this . _cameraPosition . y / ( ellipsoid . radii . y + minimumHeight ) ;
145
+ cv . z = this . _cameraPosition . z / ( ellipsoid . radii . z + minimumHeight ) ;
146
+ vhMagnitudeSquared = cv . x * cv . x + cv . y * cv . y + cv . z * cv . z - 1.0 ;
147
+ } else {
148
+ cv = this . _cameraPositionInScaledSpace ;
149
+ vhMagnitudeSquared = this . _distanceToLimbInScaledSpaceSquared ;
150
+ }
151
+
152
+ return isScaledSpacePointVisible ( occludeeScaledSpacePosition , cv , vhMagnitudeSquared ) ;
129
153
} ;
130
154
131
155
/**
@@ -145,30 +169,32 @@ import Rectangle from './Rectangle.js';
145
169
* @returns {Cartesian3 } The computed horizon culling point, expressed in the ellipsoid-scaled space.
146
170
*/
147
171
EllipsoidalOccluder . prototype . computeHorizonCullingPoint = function ( directionToPoint , positions , result ) {
148
- //>>includeStart('debug', pragmas.debug);
149
- Check . typeOf . object ( 'directionToPoint' , directionToPoint ) ;
150
- Check . defined ( 'positions' , positions ) ;
151
- //>>includeEnd('debug');
152
-
153
- if ( ! defined ( result ) ) {
154
- result = new Cartesian3 ( ) ;
155
- }
156
-
157
- var ellipsoid = this . _ellipsoid ;
158
- var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint ( ellipsoid , directionToPoint ) ;
159
- var resultMagnitude = 0.0 ;
160
-
161
- for ( var i = 0 , len = positions . length ; i < len ; ++ i ) {
162
- var position = positions [ i ] ;
163
- var candidateMagnitude = computeMagnitude ( ellipsoid , position , scaledSpaceDirectionToPoint ) ;
164
- resultMagnitude = Math . max ( resultMagnitude , candidateMagnitude ) ;
165
- }
166
-
167
- return magnitudeToPoint ( scaledSpaceDirectionToPoint , resultMagnitude , result ) ;
172
+ return computeHorizonCullingPointFromPositions ( this . _ellipsoid , directionToPoint , positions , result ) ;
168
173
} ;
169
174
170
- var positionScratch = new Cartesian3 ( ) ;
175
+ var scratchEllipsoidShrunk = Ellipsoid . clone ( Ellipsoid . UNIT_SPHERE ) ;
171
176
177
+ /**
178
+ * Similar to {@link EllipsoidalOccluder#computeHorizonCullingPoint} except computes the culling
179
+ * point relative to an ellipsoid that has been shrunk by the minimum height when the minimum height is below
180
+ * the ellipsoid. The returned point is expressed in the possibly-shrunk ellipsoid-scaled space and is suitable
181
+ * for use with {@link EllipsoidalOccluder#isScaledSpacePointVisiblePossiblyUnderEllipsoid}.
182
+ *
183
+ * @param {Cartesian3 } directionToPoint The direction that the computed point will lie along.
184
+ * A reasonable direction to use is the direction from the center of the ellipsoid to
185
+ * the center of the bounding sphere computed from the positions. The direction need not
186
+ * be normalized.
187
+ * @param {Cartesian3[] } positions The positions from which to compute the horizon culling point. The positions
188
+ * must be expressed in a reference frame centered at the ellipsoid and aligned with the
189
+ * ellipsoid's axes.
190
+ * @param {Number } [minimumHeight] The minimum height of all positions. If this value is undefined, all positions are assumed to be above the ellipsoid.
191
+ * @param {Cartesian3 } [result] The instance on which to store the result instead of allocating a new instance.
192
+ * @returns {Cartesian3 } The computed horizon culling point, expressed in the possibly-shrunk ellipsoid-scaled space.
193
+ */
194
+ EllipsoidalOccluder . prototype . computeHorizonCullingPointPossiblyUnderEllipsoid = function ( directionToPoint , positions , minimumHeight , result ) {
195
+ var possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid ( this . _ellipsoid , minimumHeight , scratchEllipsoidShrunk ) ;
196
+ return computeHorizonCullingPointFromPositions ( possiblyShrunkEllipsoid , directionToPoint , positions , result ) ;
197
+ } ;
172
198
/**
173
199
* Computes a point that can be used for horizon culling from a list of positions. If the point is below
174
200
* the horizon, all of the positions are guaranteed to be below the horizon as well. The returned point
@@ -188,31 +214,31 @@ import Rectangle from './Rectangle.js';
188
214
* @returns {Cartesian3 } The computed horizon culling point, expressed in the ellipsoid-scaled space.
189
215
*/
190
216
EllipsoidalOccluder . prototype . computeHorizonCullingPointFromVertices = function ( directionToPoint , vertices , stride , center , result ) {
191
- //>>includeStart('debug', pragmas.debug);
192
- Check . typeOf . object ( 'directionToPoint' , directionToPoint ) ;
193
- Check . defined ( 'vertices' , vertices ) ;
194
- Check . typeOf . number ( 'stride' , stride ) ;
195
- //>>includeEnd('debug');
196
-
197
- if ( ! defined ( result ) ) {
198
- result = new Cartesian3 ( ) ;
199
- }
200
-
201
- center = defaultValue ( center , Cartesian3 . ZERO ) ;
202
- var ellipsoid = this . _ellipsoid ;
203
- var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint ( ellipsoid , directionToPoint ) ;
204
- var resultMagnitude = 0.0 ;
205
-
206
- for ( var i = 0 , len = vertices . length ; i < len ; i += stride ) {
207
- positionScratch . x = vertices [ i ] + center . x ;
208
- positionScratch . y = vertices [ i + 1 ] + center . y ;
209
- positionScratch . z = vertices [ i + 2 ] + center . z ;
210
-
211
- var candidateMagnitude = computeMagnitude ( ellipsoid , positionScratch , scaledSpaceDirectionToPoint ) ;
212
- resultMagnitude = Math . max ( resultMagnitude , candidateMagnitude ) ;
213
- }
217
+ return computeHorizonCullingPointFromVertices ( this . _ellipsoid , directionToPoint , vertices , stride , center , result ) ;
218
+ } ;
214
219
215
- return magnitudeToPoint ( scaledSpaceDirectionToPoint , resultMagnitude , result ) ;
220
+ /**
221
+ * Similar to {@link EllipsoidalOccluder#computeHorizonCullingPointFromVertices} except computes the culling
222
+ * point relative to an ellipsoid that has been shrunk by the minimum height when the minimum height is below
223
+ * the ellipsoid. The returned point is expressed in the possibly-shrunk ellipsoid-scaled space and is suitable
224
+ * for use with {@link EllipsoidalOccluder#isScaledSpacePointVisiblePossiblyUnderEllipsoid}.
225
+ *
226
+ * @param {Cartesian3 } directionToPoint The direction that the computed point will lie along.
227
+ * A reasonable direction to use is the direction from the center of the ellipsoid to
228
+ * the center of the bounding sphere computed from the positions. The direction need not
229
+ * be normalized.
230
+ * @param {Number[] } vertices The vertices from which to compute the horizon culling point. The positions
231
+ * must be expressed in a reference frame centered at the ellipsoid and aligned with the
232
+ * ellipsoid's axes.
233
+ * @param {Number } [stride=3]
234
+ * @param {Cartesian3 } [center=Cartesian3.ZERO]
235
+ * @param {Number } [minimumHeight] The minimum height of all vertices. If this value is undefined, all vertices are assumed to be above the ellipsoid.
236
+ * @param {Cartesian3 } [result] The instance on which to store the result instead of allocating a new instance.
237
+ * @returns {Cartesian3 } The computed horizon culling point, expressed in the possibly-shrunk ellipsoid-scaled space.
238
+ */
239
+ EllipsoidalOccluder . prototype . computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid = function ( directionToPoint , vertices , stride , center , minimumHeight , result ) {
240
+ var possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid ( this . _ellipsoid , minimumHeight , scratchEllipsoidShrunk ) ;
241
+ return computeHorizonCullingPointFromVertices ( possiblyShrunkEllipsoid , directionToPoint , vertices , stride , center , result ) ;
216
242
} ;
217
243
218
244
var subsampleScratch = [ ] ;
@@ -246,6 +272,86 @@ import Rectangle from './Rectangle.js';
246
272
return this . computeHorizonCullingPoint ( bs . center , positions , result ) ;
247
273
} ;
248
274
275
+ var scratchEllipsoidShrunkRadii = new Cartesian3 ( ) ;
276
+
277
+ function getPossiblyShrunkEllipsoid ( ellipsoid , minimumHeight , result ) {
278
+ if ( defined ( minimumHeight ) && minimumHeight < 0.0 && ellipsoid . minimumRadius > - minimumHeight ) {
279
+ var ellipsoidShrunkRadii = Cartesian3 . fromElements (
280
+ ellipsoid . radii . x + minimumHeight ,
281
+ ellipsoid . radii . y + minimumHeight ,
282
+ ellipsoid . radii . z + minimumHeight ,
283
+ scratchEllipsoidShrunkRadii
284
+ ) ;
285
+ ellipsoid = Ellipsoid . fromCartesian3 ( ellipsoidShrunkRadii , result ) ;
286
+ }
287
+ return ellipsoid ;
288
+ }
289
+
290
+ function computeHorizonCullingPointFromPositions ( ellipsoid , directionToPoint , positions , result ) {
291
+ //>>includeStart('debug', pragmas.debug);
292
+ Check . typeOf . object ( 'directionToPoint' , directionToPoint ) ;
293
+ Check . defined ( 'positions' , positions ) ;
294
+ //>>includeEnd('debug');
295
+
296
+ if ( ! defined ( result ) ) {
297
+ result = new Cartesian3 ( ) ;
298
+ }
299
+
300
+ var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint ( ellipsoid , directionToPoint ) ;
301
+ var resultMagnitude = 0.0 ;
302
+
303
+ for ( var i = 0 , len = positions . length ; i < len ; ++ i ) {
304
+ var position = positions [ i ] ;
305
+ var candidateMagnitude = computeMagnitude ( ellipsoid , position , scaledSpaceDirectionToPoint ) ;
306
+ resultMagnitude = Math . max ( resultMagnitude , candidateMagnitude ) ;
307
+ }
308
+
309
+ return magnitudeToPoint ( scaledSpaceDirectionToPoint , resultMagnitude , result ) ;
310
+ }
311
+
312
+ var positionScratch = new Cartesian3 ( ) ;
313
+
314
+ function computeHorizonCullingPointFromVertices ( ellipsoid , directionToPoint , vertices , stride , center , result ) {
315
+ //>>includeStart('debug', pragmas.debug);
316
+ Check . typeOf . object ( 'directionToPoint' , directionToPoint ) ;
317
+ Check . defined ( 'vertices' , vertices ) ;
318
+ Check . typeOf . number ( 'stride' , stride ) ;
319
+ //>>includeEnd('debug');
320
+
321
+ if ( ! defined ( result ) ) {
322
+ result = new Cartesian3 ( ) ;
323
+ }
324
+
325
+ stride = defaultValue ( stride , 3 ) ;
326
+ center = defaultValue ( center , Cartesian3 . ZERO ) ;
327
+ var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint ( ellipsoid , directionToPoint ) ;
328
+ var resultMagnitude = 0.0 ;
329
+
330
+ for ( var i = 0 , len = vertices . length ; i < len ; i += stride ) {
331
+ positionScratch . x = vertices [ i ] + center . x ;
332
+ positionScratch . y = vertices [ i + 1 ] + center . y ;
333
+ positionScratch . z = vertices [ i + 2 ] + center . z ;
334
+
335
+ var candidateMagnitude = computeMagnitude ( ellipsoid , positionScratch , scaledSpaceDirectionToPoint ) ;
336
+ resultMagnitude = Math . max ( resultMagnitude , candidateMagnitude ) ;
337
+ }
338
+
339
+ return magnitudeToPoint ( scaledSpaceDirectionToPoint , resultMagnitude , result ) ;
340
+ }
341
+
342
+ function isScaledSpacePointVisible ( occludeeScaledSpacePosition , cameraPositionInScaledSpace , distanceToLimbInScaledSpaceSquared ) {
343
+ // See https://cesium.com/blog/2013/04/25/Horizon-culling/
344
+ var cv = cameraPositionInScaledSpace ;
345
+ var vhMagnitudeSquared = distanceToLimbInScaledSpaceSquared ;
346
+ var vt = Cartesian3 . subtract ( occludeeScaledSpacePosition , cv , scratchCartesian ) ;
347
+ var vtDotVc = - Cartesian3 . dot ( vt , cv ) ;
348
+ // If vhMagnitudeSquared < 0 then we are below the surface of the ellipsoid and
349
+ // in this case, set the culling plane to be on V.
350
+ var isOccluded = vhMagnitudeSquared < 0 ? vtDotVc > 0 : ( vtDotVc > vhMagnitudeSquared &&
351
+ vtDotVc * vtDotVc / Cartesian3 . magnitudeSquared ( vt ) > vhMagnitudeSquared ) ;
352
+ return ! isOccluded ;
353
+ }
354
+
249
355
var scaledSpaceScratch = new Cartesian3 ( ) ;
250
356
var directionScratch = new Cartesian3 ( ) ;
251
357
0 commit comments