Просмотр исходного кода

Improved OrbitControls and added example.

Mr.doob 13 лет назад
Родитель
Сommit
22182b08de
3 измененных файлов с 208 добавлено и 45 удалено
  1. 140 0
      examples/misc_camera_orbit.html
  2. 20 19
      examples/misc_camera_trackball.html
  3. 48 26
      src/extras/controls/OrbitControls.js

+ 140 - 0
examples/misc_camera_orbit.html

@@ -0,0 +1,140 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - orbit camera</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #000;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				font-weight: bold;
+
+				background-color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				color:#000;
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+
+			}
+
+			a {
+				color: red;
+			}
+		</style>
+	</head>
+
+	<body>
+		<div id="container"></div>
+		<div id="info">
+			<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - orbit camera example
+		</div>
+
+		<script src="../build/Three.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/Stats.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, controls, scene, renderer;
+
+			var cross;
+
+			init();
+			animate();
+
+			function init() {
+
+				// scene and camera
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
+
+				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.z = 500;
+
+				scene.add( camera );
+
+				controls = new THREE.OrbitControls( camera );
+				controls.addEventListener( 'change', render );
+
+				// world
+
+				var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 );
+				var material =  new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } );
+
+				for ( var i = 0; i < 500; i ++ ) {
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.position.x = ( Math.random() - 0.5 ) * 1000;
+					mesh.position.y = ( Math.random() - 0.5 ) * 1000;
+					mesh.position.z = ( Math.random() - 0.5 ) * 1000;
+					mesh.updateMatrix();
+					mesh.matrixAutoUpdate = false;
+					scene.add( mesh );
+
+				}
+
+
+				// lights
+
+				light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 1, 1, 1 );
+				scene.add( light );
+
+				light = new THREE.DirectionalLight( 0x002288 );
+				light.position.set( -1, -1, -1 );
+				scene.add( light );
+
+				light = new THREE.AmbientLight( 0x222222 );
+				scene.add( light );
+
+
+				// renderer
+
+				renderer = new THREE.WebGLRenderer( { antialias: false } );
+				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container = document.getElementById( 'container' );
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				stats.domElement.style.zIndex = 100;
+				container.appendChild( stats.domElement );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				controls.update();
+
+			}
+
+			function render() {
+
+				renderer.render( scene, camera );
+				stats.update();
+
+			}
+
+
+		</script>
+
+	</body>
+</html>

+ 20 - 19
examples/misc_camera_trackball.html

@@ -5,28 +5,29 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
-		    body {
-			color: #000;
-			font-family:Monospace;
-			font-size:13px;
-			text-align:center;
-			font-weight: bold;
-
-			background-color: #fff;
-			margin: 0px;
-			overflow: hidden;
-		    }
-
-		    #info {
-					color:#000;
-			position: absolute;
-			top: 0px; width: 100%;
-			padding: 5px;
+			body {
+				color: #000;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				font-weight: bold;
+
+				background-color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
 
-		    }
+			#info {
+				color:#000;
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
 
-		    a { color: red; }
+			}
 
+			a {
+				color: red;
+			}
 		</style>
 	</head>
 

+ 48 - 26
src/extras/controls/OrbitControls.js

@@ -1,15 +1,18 @@
 /**
  * @author qiao / https://github.com/qiao
+ * @author mrdoob / http://mrdoob.com
  */
 
-THREE.OrbitControls = function( object, domElement ) {
-	
+THREE.OrbitControls = function ( object, domElement ) {
+
+	THREE.EventTarget.call( this );
+
 	this.object = object;
-	this.domElement = ( domElement !== undefined ? domElement : document );
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
 
 	// API
 	
-	this.center = new THREE.Vector3( 0, 0, 0 );
+	this.center = new THREE.Vector3();
 	
 	this.userZoom = true;
 	this.userZoomSpeed = 1.0;
@@ -22,7 +25,7 @@ THREE.OrbitControls = function( object, domElement ) {
 
 	// internals
 	
-	var self = this;
+	var scope = this;
 
 	var EPS = 0.000001;
 	var PIXELS_PER_ROUND = 1800;
@@ -30,11 +33,18 @@ THREE.OrbitControls = function( object, domElement ) {
 	var rotateStart = new THREE.Vector2();
 	var rotateEnd = new THREE.Vector2();
 	var rotateDelta = new THREE.Vector2();
-	var rotating = false;
+
 	var phiDelta = 0;
 	var thetaDelta = 0;
 	var scale = 1;
 
+	var lastPosition = new THREE.Vector3();
+
+	// events
+
+	var changeEvent = { type: 'change' };
+
+
 	this.rotateLeft = function ( angle ) {
 
 		if ( angle === undefined ) {
@@ -142,72 +152,84 @@ THREE.OrbitControls = function( object, domElement ) {
 		thetaDelta = 0;
 		phiDelta = 0;
 		scale = 1;
+
+		if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
+			
+			this.dispatchEvent( changeEvent );
+
+			lastPosition.copy( this.object.position );
+
+		}
+
 	};
 
 
 	function getAutoRotationAngle() {
 
-		return 2 * Math.PI / 60 / 60 * self.autoRotateSpeed;
+		return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
 
 	}
 
 	function getZoomScale() {
 	
-		return Math.pow( 0.95, self.userZoomSpeed );
+		return Math.pow( 0.95, scope.userZoomSpeed );
 	
 	}
 
-	function onMouseMove( event ) {
+	function onMouseDown( event ) {
 
-		if ( !rotating ) return;
+		if ( !scope.userRotate ) return;
 
-		rotateEnd.set( event.clientX, event.clientY );
-		rotateDelta.sub( rotateEnd, rotateStart );
+		event.preventDefault();
 
-		self.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * self.userRotateSpeed );
-		self.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * self.userRotateSpeed );
+		rotateStart.set( event.clientX, event.clientY );
 
-		rotateStart.copy( rotateEnd );
+		document.addEventListener( 'mousemove', onMouseMove, false );
+		document.addEventListener( 'mouseup', onMouseUp, false );
 
 	}
 
-	function onMouseDown( event ) {
+	function onMouseMove( event ) {
 
-		if ( !self.userRotate ) return;
+		event.preventDefault();
 
-		rotateStart.set( event.clientX, event.clientY );
-		rotating = true;
+		rotateEnd.set( event.clientX, event.clientY );
+		rotateDelta.sub( rotateEnd, rotateStart );
+
+		scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
+		scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
+
+		rotateStart.copy( rotateEnd );
 
 	}
 
 	function onMouseUp( event ) {
 
-		if ( !self.userRotate ) return;
+		if ( ! scope.userRotate ) return;
 
-		rotating = false;
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+		document.removeEventListener( 'mouseup', onMouseUp, false );
 
 	}
 
 	function onMouseWheel( event ) {
 
-		if ( !self.userZoom ) return;
+		if ( ! scope.userZoom ) return;
 
 		if ( event.wheelDelta > 0 ) {
 		
-			self.zoomOut();
+			scope.zoomOut();
 		
 		} else {
 		
-			self.zoomIn();
+			scope.zoomIn();
 		
 		}
 	
 	}
 
 	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
-	this.domElement.addEventListener( 'mousemove', onMouseMove, false );
 	this.domElement.addEventListener( 'mousedown', onMouseDown, false );
-	this.domElement.addEventListener( 'mouseup', onMouseUp, false );
 	this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
 
 };