فهرست منبع

OrbitControls update condition should check offset and orientation

`OrbitControls` only checks the camera position offset to decide when to
emit a `change` event. When the camera is near either pole and the user
is rotating in azimuth, the position changes very little while the
camera orientation changes a lot. As a result, the view feels 'stuck' in
azimuth near the poles.

This patch modifies the camera update condition to take into account
both the change in offset and orientation between `change` events. The
update condition is now:

    (camera displacement)^2 + (camera rotation in radians)^2 > EPS

The additional term is computed from the dot product of the camera's
orientation quaternion at consecutive time steps:

    8 * (1 - q.r)

The second-order Taylor expansion of this expression is the square of
the camera rotation angle between frames.
Leo Singer 11 سال پیش
والد
کامیت
4320eec34f
1فایلهای تغییر یافته به همراه8 افزوده شده و 1 حذف شده
  1. 8 1
      examples/js/controls/OrbitControls.js

+ 8 - 1
examples/js/controls/OrbitControls.js

@@ -98,6 +98,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 	var pan = new THREE.Vector3();
 
 	var lastPosition = new THREE.Vector3();
+	var lastQuaternion = new THREE.Vector4();
 
 	var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
 
@@ -284,11 +285,17 @@ THREE.OrbitControls = function ( object, domElement ) {
 		scale = 1;
 		pan.set( 0, 0, 0 );
 
-		if ( lastPosition.distanceToSquared( this.object.position ) > EPS ) {
+		// update condition is:
+		// (camera displacement)^2 + (camera rotation in radians)^2 > EPS
+		// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+		if ( lastPosition.distanceToSquared( this.object.position )
+		   + 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
 
 			this.dispatchEvent( changeEvent );
 
 			lastPosition.copy( this.object.position );
+			lastQuaternion.copy (this.object.quaternion );
 
 		}