Anders and Briegel in Python
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
7.9KB

  1. // three.js - http://github.com/mrdoob/three.js
  2. /**
  3. * @author qiao / https://github.com/qiao
  4. * @author mrdoob / http://mrdoob.com
  5. * @author alteredq / http://alteredqualia.com/
  6. * @author WestLangley / http://github.com/WestLangley
  7. */
  8. THREE.OrbitControls = function ( object, domElement ) {
  9. this.object = object;
  10. this.domElement = ( domElement !== undefined ) ? domElement : document;
  11. // API
  12. this.enabled = true;
  13. this.center = new THREE.Vector3();
  14. this.target = new THREE.Vector3();
  15. this.userZoom = true;
  16. this.userZoomSpeed = 1.0;
  17. this.userRotate = true;
  18. this.userRotateSpeed = 1.0;
  19. this.userPan = true;
  20. this.userPanSpeed = 0.1;
  21. this.autoRotate = false;
  22. this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
  23. this.minPolarAngle = 0; // radians
  24. this.maxPolarAngle = Math.PI; // radians
  25. this.minDistance = 0;
  26. this.maxDistance = Infinity;
  27. // 65 /*A*/, 83 /*S*/, 68 /*D*/
  28. this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 };
  29. // internals
  30. var scope = this;
  31. var EPS = 0.000001;
  32. var PIXELS_PER_ROUND = 1800;
  33. var rotateStart = new THREE.Vector2();
  34. var rotateEnd = new THREE.Vector2();
  35. var rotateDelta = new THREE.Vector2();
  36. var zoomStart = new THREE.Vector2();
  37. var zoomEnd = new THREE.Vector2();
  38. var zoomDelta = new THREE.Vector2();
  39. var phiDelta = 0;
  40. var thetaDelta = 0;
  41. var scale = 1;
  42. var lastPosition = new THREE.Vector3();
  43. var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
  44. var state = STATE.NONE;
  45. // events
  46. var changeEvent = { type: 'change' };
  47. this.rotateLeft = function ( angle ) {
  48. if ( angle === undefined ) {
  49. angle = getAutoRotationAngle();
  50. }
  51. thetaDelta -= angle;
  52. };
  53. this.rotateRight = function ( angle ) {
  54. if ( angle === undefined ) {
  55. angle = getAutoRotationAngle();
  56. }
  57. thetaDelta += angle;
  58. };
  59. this.rotateUp = function ( angle ) {
  60. if ( angle === undefined ) {
  61. angle = getAutoRotationAngle();
  62. }
  63. phiDelta -= angle;
  64. };
  65. this.rotateDown = function ( angle ) {
  66. if ( angle === undefined ) {
  67. angle = getAutoRotationAngle();
  68. }
  69. phiDelta += angle;
  70. };
  71. this.zoomIn = function ( zoomScale ) {
  72. if ( zoomScale === undefined ) {
  73. zoomScale = getZoomScale();
  74. }
  75. scale /= zoomScale;
  76. };
  77. this.zoomOut = function ( zoomScale ) {
  78. if ( zoomScale === undefined ) {
  79. zoomScale = getZoomScale();
  80. }
  81. scale *= zoomScale;
  82. };
  83. this.pan = function ( distance ) {
  84. distance.transformDirection( this.object.matrix );
  85. distance.multiplyScalar( scope.userPanSpeed );
  86. this.object.position.add( distance );
  87. this.center.add( distance );
  88. };
  89. this.update = function () {
  90. var position = this.object.position;
  91. var offset = position.clone().sub( this.center );
  92. var diff = this.center.clone().sub( this.target ).multiplyScalar(0.2);
  93. this.center.sub(diff);
  94. // angle from z-axis around y-axis
  95. var theta = Math.atan2( offset.x, offset.z );
  96. // angle from y-axis
  97. var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
  98. if ( this.autoRotate ) {
  99. this.rotateLeft( getAutoRotationAngle() );
  100. }
  101. theta += thetaDelta;
  102. phi += phiDelta;
  103. // restrict phi to be between desired limits
  104. phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
  105. // restrict phi to be betwee EPS and PI-EPS
  106. phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
  107. var radius = offset.length() * scale;
  108. // restrict radius to be between desired limits
  109. radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
  110. offset.x = radius * Math.sin( phi ) * Math.sin( theta );
  111. offset.y = radius * Math.cos( phi );
  112. offset.z = radius * Math.sin( phi ) * Math.cos( theta );
  113. position.copy( this.center ).add( offset );
  114. this.object.lookAt( this.center );
  115. thetaDelta /= 1.5;
  116. phiDelta /= 1.5;
  117. scale = 1;
  118. if ( lastPosition.distanceTo( this.object.position ) > 0.01 ) {
  119. this.dispatchEvent( changeEvent );
  120. lastPosition.copy( this.object.position );
  121. }
  122. };
  123. function getAutoRotationAngle() {
  124. return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
  125. }
  126. function getZoomScale() {
  127. return Math.pow( 0.95, scope.userZoomSpeed );
  128. }
  129. function onMouseDown( event ) {
  130. if ( scope.enabled === false ) return;
  131. if ( scope.userRotate === false ) return;
  132. event.preventDefault();
  133. if ( state === STATE.NONE )
  134. {
  135. if ( event.button === 0 )
  136. state = STATE.ROTATE;
  137. if ( event.button === 1 )
  138. state = STATE.ZOOM;
  139. if ( event.button === 2 )
  140. state = STATE.PAN;
  141. }
  142. if ( state === STATE.ROTATE ) {
  143. //state = STATE.ROTATE;
  144. rotateStart.set( event.clientX, event.clientY );
  145. } else if ( state === STATE.ZOOM ) {
  146. //state = STATE.ZOOM;
  147. zoomStart.set( event.clientX, event.clientY );
  148. } else if ( state === STATE.PAN ) {
  149. //state = STATE.PAN;
  150. }
  151. document.addEventListener( 'mousemove', onMouseMove, false );
  152. document.addEventListener( 'mouseup', onMouseUp, false );
  153. }
  154. function onMouseMove( event ) {
  155. if ( scope.enabled === false ) return;
  156. event.preventDefault();
  157. if ( state === STATE.ROTATE ) {
  158. rotateEnd.set( event.clientX, event.clientY );
  159. rotateDelta.subVectors( rotateEnd, rotateStart );
  160. scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
  161. scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
  162. rotateStart.copy( rotateEnd );
  163. } else if ( state === STATE.ZOOM ) {
  164. zoomEnd.set( event.clientX, event.clientY );
  165. zoomDelta.subVectors( zoomEnd, zoomStart );
  166. if ( zoomDelta.y > 0 ) {
  167. scope.zoomIn();
  168. } else {
  169. scope.zoomOut();
  170. }
  171. zoomStart.copy( zoomEnd );
  172. } else if ( state === STATE.PAN ) {
  173. var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
  174. var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
  175. scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
  176. }
  177. }
  178. function onMouseUp( event ) {
  179. if ( scope.enabled === false ) return;
  180. if ( scope.userRotate === false ) return;
  181. document.removeEventListener( 'mousemove', onMouseMove, false );
  182. document.removeEventListener( 'mouseup', onMouseUp, false );
  183. state = STATE.NONE;
  184. }
  185. function onMouseWheel( event ) {
  186. if ( scope.enabled === false ) return;
  187. if ( scope.userZoom === false ) return;
  188. var delta = 0;
  189. if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
  190. delta = event.wheelDelta;
  191. } else if ( event.detail ) { // Firefox
  192. delta = - event.detail;
  193. }
  194. if ( delta > 0 ) {
  195. scope.zoomOut();
  196. } else {
  197. scope.zoomIn();
  198. }
  199. }
  200. function onKeyDown( event ) {
  201. if ( scope.enabled === false ) return;
  202. if ( scope.userPan === false ) return;
  203. switch ( event.keyCode ) {
  204. /*case scope.keys.UP:
  205. scope.pan( new THREE.Vector3( 0, 1, 0 ) );
  206. break;
  207. case scope.keys.BOTTOM:
  208. scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
  209. break;
  210. case scope.keys.LEFT:
  211. scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
  212. break;
  213. case scope.keys.RIGHT:
  214. scope.pan( new THREE.Vector3( 1, 0, 0 ) );
  215. break;
  216. */
  217. case scope.keys.ROTATE:
  218. state = STATE.ROTATE;
  219. break;
  220. case scope.keys.ZOOM:
  221. state = STATE.ZOOM;
  222. break;
  223. case scope.keys.PAN:
  224. state = STATE.PAN;
  225. break;
  226. }
  227. }
  228. function onKeyUp( event ) {
  229. switch ( event.keyCode ) {
  230. case scope.keys.ROTATE:
  231. case scope.keys.ZOOM:
  232. case scope.keys.PAN:
  233. state = STATE.NONE;
  234. break;
  235. }
  236. }
  237. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  238. this.domElement.addEventListener( 'mousedown', onMouseDown, false );
  239. this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
  240. this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
  241. window.addEventListener( 'keydown', onKeyDown, false );
  242. window.addEventListener( 'keyup', onKeyUp, false );
  243. };
  244. THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );