Ver código fonte

Merge pull request #19298 from WestLangley/dev_azimuth_limits

OrbitControls: support more flexible azimuthal limits
Mr.doob 5 anos atrás
pai
commit
a811352302

+ 2 - 4
docs/examples/en/controls/OrbitControls.html

@@ -160,8 +160,7 @@ controls.keys = {
 
 
 		<h3>[property:Float maxAzimuthAngle]</h3>
 		<h3>[property:Float maxAzimuthAngle]</h3>
 		<p>
 		<p>
-			How far you can orbit horizontally, upper limit. Range is - Math.PI to Math.PI ( or Infinity for no limit ) and default is
-			Infinity;
+			How far you can orbit horizontally, upper limit. If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ). Default is Infinity.
 		</p>
 		</p>
 
 
 		<h3>[property:Float maxDistance]</h3>
 		<h3>[property:Float maxDistance]</h3>
@@ -181,8 +180,7 @@ controls.keys = {
 
 
 		<h3>[property:Float minAzimuthAngle]</h3>
 		<h3>[property:Float minAzimuthAngle]</h3>
 		<p>
 		<p>
-			How far you can orbit horizontally, lower limit. Range is - Math.PI to Math.PI ( or - Infinity for no limit ) and default
-			is - Infinity;
+			How far you can orbit horizontally, lower limit. If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ). Default is Infinity.
 		</p>
 		</p>
 
 
 		<h3>[property:Float minDistance]</h3>
 		<h3>[property:Float minDistance]</h3>

+ 2 - 4
docs/examples/zh/controls/OrbitControls.html

@@ -158,8 +158,7 @@ controls.keys = {
 
 
 		<h3>[property:Float maxAzimuthAngle]</h3>
 		<h3>[property:Float maxAzimuthAngle]</h3>
 		<p>
 		<p>
-			你能够水平旋转的角度的上限,范围是-Math.PI到Math.PI(或Infinity无限制),
-			其默认值为Infinity。
+			How far you can orbit horizontally, upper limit. If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ). Default is Infinity.
 		</p>
 		</p>
 
 
 		<h3>[property:Float maxDistance]</h3>
 		<h3>[property:Float maxDistance]</h3>
@@ -179,8 +178,7 @@ controls.keys = {
 
 
 		<h3>[property:Float minAzimuthAngle]</h3>
 		<h3>[property:Float minAzimuthAngle]</h3>
 		<p>
 		<p>
-			你能够水平旋转的角度的下限,范围是-Math.PI到Math.PI(或-Infinity无限制),
-			其默认值为-Infinity。
+			How far you can orbit horizontally, lower limit. If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ). Default is Infinity.
 		</p>
 		</p>
 
 
 		<h3>[property:Float minDistance]</h3>
 		<h3>[property:Float minDistance]</h3>

+ 26 - 2
examples/js/controls/OrbitControls.js

@@ -43,7 +43,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 	this.maxPolarAngle = Math.PI; // radians
 	this.maxPolarAngle = Math.PI; // radians
 
 
 	// How far you can orbit horizontally, upper and lower limits.
 	// How far you can orbit horizontally, upper and lower limits.
-	// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+	// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
 	this.minAzimuthAngle = - Infinity; // radians
 	this.minAzimuthAngle = - Infinity; // radians
 	this.maxAzimuthAngle = Infinity; // radians
 	this.maxAzimuthAngle = Infinity; // radians
 
 
@@ -140,6 +140,8 @@ THREE.OrbitControls = function ( object, domElement ) {
 		var lastPosition = new THREE.Vector3();
 		var lastPosition = new THREE.Vector3();
 		var lastQuaternion = new THREE.Quaternion();
 		var lastQuaternion = new THREE.Quaternion();
 
 
+		var twoPI = 2 * Math.PI;
+
 		return function update() {
 		return function update() {
 
 
 			var position = scope.object.position;
 			var position = scope.object.position;
@@ -171,7 +173,29 @@ THREE.OrbitControls = function ( object, domElement ) {
 			}
 			}
 
 
 			// restrict theta to be between desired limits
 			// restrict theta to be between desired limits
-			spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
+
+			var min = scope.minAzimuthAngle;
+			var max = scope.maxAzimuthAngle;
+
+			if ( isFinite ( min ) && isFinite( max ) ) {
+
+				if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
+
+				if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
+
+				if ( min < max ) {
+
+					spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
+
+				} else {
+
+					spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
+						Math.max( min, spherical.theta ) :
+						Math.min( max, spherical.theta );
+
+				}
+
+			}
 
 
 			// restrict phi to be between desired limits
 			// restrict phi to be between desired limits
 			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
 			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );

+ 26 - 2
examples/jsm/controls/OrbitControls.js

@@ -52,7 +52,7 @@ var OrbitControls = function ( object, domElement ) {
 	this.maxPolarAngle = Math.PI; // radians
 	this.maxPolarAngle = Math.PI; // radians
 
 
 	// How far you can orbit horizontally, upper and lower limits.
 	// How far you can orbit horizontally, upper and lower limits.
-	// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+	// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
 	this.minAzimuthAngle = - Infinity; // radians
 	this.minAzimuthAngle = - Infinity; // radians
 	this.maxAzimuthAngle = Infinity; // radians
 	this.maxAzimuthAngle = Infinity; // radians
 
 
@@ -149,6 +149,8 @@ var OrbitControls = function ( object, domElement ) {
 		var lastPosition = new Vector3();
 		var lastPosition = new Vector3();
 		var lastQuaternion = new Quaternion();
 		var lastQuaternion = new Quaternion();
 
 
+		var twoPI = 2 * Math.PI;
+
 		return function update() {
 		return function update() {
 
 
 			var position = scope.object.position;
 			var position = scope.object.position;
@@ -180,7 +182,29 @@ var OrbitControls = function ( object, domElement ) {
 			}
 			}
 
 
 			// restrict theta to be between desired limits
 			// restrict theta to be between desired limits
-			spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
+
+			var min = scope.minAzimuthAngle;
+			var max = scope.maxAzimuthAngle;
+
+			if ( isFinite ( min ) && isFinite( max ) ) {
+
+				if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
+
+				if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
+
+				if ( min < max ) {
+
+					spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
+
+				} else {
+
+					spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
+						Math.max( min, spherical.theta ) :
+						Math.min( max, spherical.theta );
+
+				}
+
+			}
 
 
 			// restrict phi to be between desired limits
 			// restrict phi to be between desired limits
 			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
 			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );