1/** 2 * @author qiao / https://github.com/qiao 3 * @author mrdoob / http://mrdoob.com 4 * @author alteredq / http://alteredqualia.com/ 5 * @author WestLangley / http://github.com/WestLangley 6 */ 7 8THREE.OrbitControls = function ( object, domElement ) { 9 10 this.object = object; 11 this.domElement = ( domElement !== undefined ) ? domElement : document; 12 13 // API 14 15 this.enabled = true; 16 17 this.center = new THREE.Vector3(); 18 19 this.userZoom = true; 20 this.userZoomSpeed = 1.0; 21 22 this.userRotate = true; 23 this.userRotateSpeed = 1.0; 24 25 this.userPan = true; 26 this.userPanSpeed = 2.0; 27 28 this.autoRotate = false; 29 this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 30 31 this.minPolarAngle = 0; // radians 32 this.maxPolarAngle = Math.PI; // radians 33 34 this.minDistance = 0; 35 this.maxDistance = Infinity; 36 37 this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; 38 this.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; // Añadido para compatibilidad 39 40 // internals 41 42 var scope = this; 43 44 var EPS = 0.000001; 45 var PIXELS_PER_ROUND = 1800; 46 47 var rotateStart = new THREE.Vector2(); 48 var rotateEnd = new THREE.Vector2(); 49 var rotateDelta = new THREE.Vector2(); 50 51 var zoomStart = new THREE.Vector2(); 52 var zoomEnd = new THREE.Vector2(); 53 var zoomDelta = new THREE.Vector2(); 54 55 var phiDelta = 0; 56 var thetaDelta = 0; 57 var scale = 1; 58 59 var lastPosition = new THREE.Vector3(); 60 61 var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 }; 62 var state = STATE.NONE; 63 64 // events 65 66 var changeEvent = { type: 'change' }; 67 68 69 this.rotateLeft = function ( angle ) { 70 71 if ( angle === undefined ) { 72 73 angle = getAutoRotationAngle(); 74 75 } 76 77 thetaDelta -= angle; 78 79 }; 80 81 this.rotateRight = function ( angle ) { 82 83 if ( angle === undefined ) { 84 85 angle = getAutoRotationAngle(); 86 87 } 88 89 thetaDelta += angle; 90 91 }; 92 93 this.rotateUp = function ( angle ) { 94 95 if ( angle === undefined ) { 96 97 angle = getAutoRotationAngle(); 98 99 } 100 101 phiDelta -= angle; 102 103 }; 104 105 this.rotateDown = function ( angle ) { 106 107 if ( angle === undefined ) { 108 109 angle = getAutoRotationAngle(); 110 111 } 112 113 phiDelta += angle; 114 115 }; 116 117 this.zoomIn = function ( zoomScale ) { 118 119 if ( zoomScale === undefined ) { 120 121 zoomScale = getZoomScale(); 122 123 } 124 125 scale /= zoomScale; 126 127 }; 128 129 this.zoomOut = function ( zoomScale ) { 130 131 if ( zoomScale === undefined ) { 132 133 zoomScale = getZoomScale(); 134 135 } 136 137 scale *= zoomScale; 138 139 }; 140 141 this.pan = function ( distance ) { 142 143 distance.transformDirection( this.object.matrix ); 144 distance.multiplyScalar( scope.userPanSpeed ); 145 146 this.object.position.add( distance ); 147 this.center.add( distance ); 148 149 }; 150 151 this.update = function () { 152 153 var position = this.object.position; 154 var offset = position.clone().sub( this.center ); 155 156 // angle from z-axis around y-axis 157 158 var theta = Math.atan2( offset.x, offset.z ); 159 160 // angle from y-axis 161 162 var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); 163 164 if ( this.autoRotate ) { 165 166 this.rotateLeft( getAutoRotationAngle() ); 167 168 } 169 170 theta += thetaDelta; 171 phi += phiDelta; 172 173 // restrict phi to be between desired limits 174 phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); 175 176 // restrict phi to be betwee EPS and PI-EPS 177 phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); 178 179 var radius = offset.length() * scale; 180 181 // restrict radius to be between desired limits 182 radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); 183 184 offset.x = radius * Math.sin( phi ) * Math.sin( theta ); 185 offset.y = radius * Math.cos( phi ); 186 offset.z = radius * Math.sin( phi ) * Math.cos( theta ); 187 188 position.copy( this.center ).add( offset ); 189 190 this.object.lookAt( this.center ); 191 192 thetaDelta = 0; 193 phiDelta = 0; 194 scale = 1; 195 196 if ( lastPosition.distanceTo( this.object.position ) > 0 ) { 197 198 this.dispatchEvent( changeEvent ); 199 200 lastPosition.copy( this.object.position ); 201 202 } 203 204 }; 205 206 207 function getAutoRotationAngle() { 208 209 return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 210 211 } 212 213 function getZoomScale() { 214 215 return Math.pow( 0.95, scope.userZoomSpeed ); 216 217 } 218 219 function onMouseDown( event ) { 220 221 if ( scope.enabled === false ) return; 222 223 event.preventDefault(); 224 225 var buttonMode = -1; 226 if ( event.button === 0 ) buttonMode = (scope.mouseButtons.LEFT !== undefined) ? scope.mouseButtons.LEFT : STATE.ROTATE; 227 else if ( event.button === 1 ) buttonMode = (scope.mouseButtons.MIDDLE !== undefined) ? scope.mouseButtons.MIDDLE : STATE.ZOOM; 228 else if ( event.button === 2 ) buttonMode = (scope.mouseButtons.RIGHT !== undefined) ? scope.mouseButtons.RIGHT : STATE.PAN; 229 230 if ( buttonMode === STATE.ROTATE && scope.userRotate ) { 231 state = STATE.ROTATE; 232 rotateStart.set( event.clientX, event.clientY ); 233 } else if ( buttonMode === STATE.ZOOM && scope.userZoom ) { 234 state = STATE.ZOOM; 235 zoomStart.set( event.clientX, event.clientY ); 236 } else if ( buttonMode === STATE.PAN && scope.userPan ) { 237 state = STATE.PAN; 238 // No logic for pan start here in this old version, but it checks in move 239 } 240 241 document.addEventListener( 'mousemove', onMouseMove, false ); 242 document.addEventListener( 'mouseup', onMouseUp, false ); 243 244 } 245 246 function onMouseMove( event ) { 247 248 if ( scope.enabled === false ) return; 249 250 event.preventDefault(); 251 252 if ( state === STATE.ROTATE ) { 253 254 rotateEnd.set( event.clientX, event.clientY ); 255 rotateDelta.subVectors( rotateEnd, rotateStart ); 256 257 scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed ); 258 scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed ); 259 260 rotateStart.copy( rotateEnd ); 261 262 } else if ( state === STATE.ZOOM ) { 263 264 zoomEnd.set( event.clientX, event.clientY ); 265 zoomDelta.subVectors( zoomEnd, zoomStart ); 266 267 if ( zoomDelta.y > 0 ) { 268 269 scope.zoomIn(); 270 271 } else { 272 273 scope.zoomOut(); 274 275 } 276 277 zoomStart.copy( zoomEnd ); 278 279 } else if ( state === STATE.PAN ) { 280 281 var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; 282 var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; 283 284 scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) ); 285 286 } 287 288 } 289 290 function onMouseUp( event ) { 291 292 if ( scope.enabled === false ) return; 293 if ( scope.userRotate === false ) return; 294 295 document.removeEventListener( 'mousemove', onMouseMove, false ); 296 document.removeEventListener( 'mouseup', onMouseUp, false ); 297 298 state = STATE.NONE; 299 300 } 301 302 function onMouseWheel( event ) { 303 304 if ( scope.enabled === false ) return; 305 if ( scope.userZoom === false ) return; 306 307 var delta = 0; 308 309 if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 310 311 delta = event.wheelDelta; 312 313 } else if ( event.detail ) { // Firefox 314 315 delta = - event.detail; 316 317 } 318 319 if ( delta > 0 ) { 320 321 scope.zoomOut(); 322 323 } else { 324 325 scope.zoomIn(); 326 327 } 328 329 } 330 331 function onKeyDown( event ) { 332 333 if ( scope.enabled === false ) return; 334 if ( scope.userPan === false ) return; 335 336 switch ( event.keyCode ) { 337 338 case scope.keys.UP: 339 scope.pan( new THREE.Vector3( 0, 1, 0 ) ); 340 break; 341 case scope.keys.BOTTOM: 342 scope.pan( new THREE.Vector3( 0, - 1, 0 ) ); 343 break; 344 case scope.keys.LEFT: 345 scope.pan( new THREE.Vector3( - 1, 0, 0 ) ); 346 break; 347 case scope.keys.RIGHT: 348 scope.pan( new THREE.Vector3( 1, 0, 0 ) ); 349 break; 350 } 351 352 } 353 354 this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); 355 this.domElement.addEventListener( 'mousedown', onMouseDown, false ); 356 this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); 357 this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox 358 this.domElement.addEventListener( 'keydown', onKeyDown, false ); 359 360}; 361 362THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.