@@ -13,8 +13,8 @@ import {
13
13
14
14
// pre-allocated temp variables
15
15
var _deviceCoord = new Vec3 ( ) ;
16
- var _far = new Vec3 ( ) ;
17
- var _farW = new Vec3 ( ) ;
16
+ var _halfSize = new Vec3 ( ) ;
17
+ var _point = new Vec3 ( ) ;
18
18
var _invViewProjMat = new Mat4 ( ) ;
19
19
20
20
/**
@@ -383,6 +383,15 @@ Object.assign(Camera.prototype, {
383
383
this . vrDisplay = other . vrDisplay ;
384
384
} ,
385
385
386
+ _updateViewProjMat : function ( ) {
387
+ if ( this . _projMatDirty || this . _viewMatDirty || this . _viewProjMatDirty ) {
388
+ var projMat = this . projectionMatrix ;
389
+ var viewMat = this . viewMatrix ;
390
+ this . _viewProjMat . mul2 ( projMat , viewMat ) ;
391
+ this . _viewProjMatDirty = false ;
392
+ }
393
+ } ,
394
+
386
395
/**
387
396
* @private
388
397
* @function
@@ -399,12 +408,7 @@ Object.assign(Camera.prototype, {
399
408
screenCoord = new Vec3 ( ) ;
400
409
}
401
410
402
- if ( this . _projMatDirty || this . _viewMatDirty || this . _viewProjMatDirty ) {
403
- var projMat = this . projectionMatrix ;
404
- var viewMat = this . viewMatrix ;
405
- this . _viewProjMat . mul2 ( projMat , viewMat ) ;
406
- this . _viewProjMatDirty = false ;
407
- }
411
+ this . _updateViewProjMat ( ) ;
408
412
this . _viewProjMat . transformPoint ( worldCoord , screenCoord ) ;
409
413
410
414
// calculate w co-coord
@@ -438,40 +442,39 @@ Object.assign(Camera.prototype, {
438
442
worldCoord = new Vec3 ( ) ;
439
443
}
440
444
441
- if ( this . _projMatDirty || this . _viewMatDirty || this . _viewProjMatDirty ) {
442
- var projMat = this . projectionMatrix ;
443
- var viewMat = this . viewMatrix ;
444
- this . _viewProjMat . mul2 ( projMat , viewMat ) ;
445
- this . _viewProjMatDirty = false ;
446
- }
447
- _invViewProjMat . copy ( this . _viewProjMat ) . invert ( ) ;
445
+ // Calculate the screen click as a point on the far plane of the normalized device coordinate 'box' (z=1)
446
+ var range = this . _farClip - this . _nearClip ;
447
+ _deviceCoord . set ( x / cw , ( ch - y ) / ch , z / range ) ;
448
+ _deviceCoord . scale ( 2 ) ;
449
+ _deviceCoord . sub ( Vec3 . ONE ) ;
448
450
449
451
if ( this . _projection === PROJECTION_PERSPECTIVE ) {
450
- // Calculate the screen click as a point on the far plane of the
451
- // normalized device coordinate 'box' (z=1)
452
- _far . set ( x / cw * 2 - 1 , ( ch - y ) / ch * 2 - 1 , 1 ) ;
453
452
454
- // Transform to world space
455
- _invViewProjMat . transformPoint ( _far , _farW ) ;
453
+ // calculate half width and height at the near clip plane
454
+ Mat4 . _getPerspectiveHalfSize ( _halfSize , this . _fov , this . _aspectRatio , this . _nearClip , this . _horizontalFov ) ;
455
+
456
+ // scale by normalized screen coordinates
457
+ _halfSize . x *= _deviceCoord . x ;
458
+ _halfSize . y *= _deviceCoord . y ;
456
459
457
- var w = _far . x * _invViewProjMat . data [ 3 ] +
458
- _far . y * _invViewProjMat . data [ 7 ] +
459
- _far . z * _invViewProjMat . data [ 11 ] +
460
- _invViewProjMat . data [ 15 ] ;
460
+ // transform to world space
461
+ var invView = this . _node . getWorldTransform ( ) ;
462
+ _halfSize . z = - this . _nearClip ;
463
+ invView . transformPoint ( _halfSize , _point ) ;
461
464
462
- _farW . scale ( 1 / w ) ;
465
+ // point along camera->_point ray at distance z from the camera
466
+ var cameraPos = this . _node . getPosition ( ) ;
467
+ worldCoord . sub2 ( _point , cameraPos ) ;
468
+ worldCoord . normalize ( ) ;
469
+ worldCoord . scale ( z ) ;
470
+ worldCoord . add ( cameraPos ) ;
463
471
464
- var alpha = z / this . _farClip ;
465
- worldCoord . lerp ( this . _node . getPosition ( ) , _farW , alpha ) ;
466
472
} else {
467
- // Calculate the screen click as a point on the far plane of the
468
- // normalized device coordinate 'box' (z=1)
469
- var range = this . _farClip - this . _nearClip ;
470
- _deviceCoord . set ( x / cw , ( ch - y ) / ch , z / range ) ;
471
- _deviceCoord . scale ( 2 ) ;
472
- _deviceCoord . sub ( Vec3 . ONE ) ;
473
-
474
- // Transform to world space
473
+
474
+ this . _updateViewProjMat ( ) ;
475
+ _invViewProjMat . copy ( this . _viewProjMat ) . invert ( ) ;
476
+
477
+ // Transform to world space
475
478
_invViewProjMat . transformPoint ( _deviceCoord , worldCoord ) ;
476
479
}
477
480
0 commit comments