浏览代码

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 );
 
 		}