Advertisement
Guest User

Untitled

a guest
Mar 24th, 2019
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.97 KB | None | 0 0
  1. /**
  2. * @author Eberhard Graether / http://egraether.com/
  3. */
  4.  
  5. THREE.TrackballControls = function ( object, domElement ) {
  6.  
  7. var _this = this;
  8. var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 };
  9.  
  10. this.object = object;
  11. this.domElement = ( domElement !== undefined ) ? domElement : document;
  12.  
  13. // API
  14.  
  15. this.enabled = true;
  16.  
  17. this.screen = { left: 0, top: 0, width: 0, height: 0 };
  18.  
  19. this.rotateSpeed = 1.0;
  20. this.zoomSpeed = 1.2;
  21. this.panSpeed = 0.3;
  22.  
  23. this.noRotate = false;
  24. this.noZoom = false;
  25. this.noPan = false;
  26. this.noRoll = false;
  27.  
  28. this.staticMoving = false;
  29. this.dynamicDampingFactor = 0.2;
  30.  
  31. this.minDistance = 0;
  32. this.maxDistance = Infinity;
  33.  
  34. this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
  35.  
  36. // internals
  37.  
  38. this.target = new THREE.Vector3();
  39.  
  40. var lastPosition = new THREE.Vector3();
  41.  
  42. var _state = STATE.NONE,
  43. _prevState = STATE.NONE,
  44.  
  45. _eye = new THREE.Vector3(),
  46.  
  47. _rotateStart = new THREE.Vector3(),
  48. _rotateEnd = new THREE.Vector3(),
  49.  
  50. _zoomStart = new THREE.Vector2(),
  51. _zoomEnd = new THREE.Vector2(),
  52.  
  53. _touchZoomDistanceStart = 0,
  54. _touchZoomDistanceEnd = 0,
  55.  
  56. _panStart = new THREE.Vector2(),
  57. _panEnd = new THREE.Vector2();
  58.  
  59. // for reset
  60.  
  61. this.target0 = this.target.clone();
  62. this.position0 = this.object.position.clone();
  63. this.up0 = this.object.up.clone();
  64.  
  65. // events
  66.  
  67. var changeEvent = { type: 'change' };
  68.  
  69.  
  70. // methods
  71.  
  72. this.handleResize = function () {
  73.  
  74. if ( this.domElement === document ) {
  75.  
  76. this.screen.left = 0;
  77. this.screen.top = 0;
  78. this.screen.width = window.innerWidth;
  79. this.screen.height = window.innerHeight;
  80.  
  81. } else {
  82.  
  83. this.screen = this.domElement.getBoundingClientRect();
  84.  
  85. }
  86.  
  87. };
  88.  
  89. this.handleEvent = function ( event ) {
  90.  
  91. if ( typeof this[ event.type ] == 'function' ) {
  92.  
  93. this[ event.type ]( event );
  94.  
  95. }
  96.  
  97. };
  98.  
  99. this.getMouseOnScreen = function ( clientX, clientY ) {
  100.  
  101. return new THREE.Vector2(
  102. ( clientX - _this.screen.left ) / _this.screen.width,
  103. ( clientY - _this.screen.top ) / _this.screen.height
  104. );
  105.  
  106. };
  107.  
  108. this.getMouseProjectionOnBall = function ( clientX, clientY ) {
  109.  
  110. var mouseOnBall = new THREE.Vector3(
  111. ( clientX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
  112. ( _this.screen.height * 0.5 + _this.screen.top - clientY ) / (_this.screen.height*.5),
  113. 0.0
  114. );
  115.  
  116. var length = mouseOnBall.length();
  117.  
  118. if ( _this.noRoll ) {
  119.  
  120. if ( length < Math.SQRT1_2 ) {
  121.  
  122. mouseOnBall.z = Math.sqrt( 1.0 - length*length );
  123.  
  124. } else {
  125.  
  126. mouseOnBall.z = .5 / length;
  127.  
  128. }
  129.  
  130. } else if ( length > 1.0 ) {
  131.  
  132. mouseOnBall.normalize();
  133.  
  134. } else {
  135.  
  136. mouseOnBall.z = Math.sqrt( 1.0 - length * length );
  137.  
  138. }
  139.  
  140. _eye.copy( _this.object.position ).sub( _this.target );
  141.  
  142. var projection = _this.object.up.clone().setLength( mouseOnBall.y );
  143. projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) );
  144. projection.add( _eye.setLength( mouseOnBall.z ) );
  145.  
  146. return projection;
  147.  
  148. };
  149.  
  150. this.rotateCamera = function () {
  151.  
  152. var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
  153.  
  154. if ( angle ) {
  155.  
  156. var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(),
  157. quaternion = new THREE.Quaternion();
  158.  
  159. angle *= _this.rotateSpeed;
  160.  
  161. quaternion.setFromAxisAngle( axis, -angle );
  162.  
  163. _eye.applyQuaternion( quaternion );
  164. _this.object.up.applyQuaternion( quaternion );
  165.  
  166. _rotateEnd.applyQuaternion( quaternion );
  167.  
  168. if ( _this.staticMoving ) {
  169.  
  170. _rotateStart.copy( _rotateEnd );
  171.  
  172. } else {
  173.  
  174. quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
  175. _rotateStart.applyQuaternion( quaternion );
  176.  
  177. }
  178.  
  179. }
  180.  
  181. };
  182.  
  183. this.zoomCamera = function () {
  184.  
  185. if ( _state === STATE.TOUCH_ZOOM ) {
  186.  
  187. var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
  188. _touchZoomDistanceStart = _touchZoomDistanceEnd;
  189. _eye.multiplyScalar( factor );
  190.  
  191. } else {
  192.  
  193. var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
  194.  
  195. if ( factor !== 1.0 && factor > 0.0 ) {
  196.  
  197. _eye.multiplyScalar( factor );
  198.  
  199. if ( _this.staticMoving ) {
  200.  
  201. _zoomStart.copy( _zoomEnd );
  202.  
  203. } else {
  204.  
  205. _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
  206.  
  207. }
  208.  
  209. }
  210.  
  211. }
  212.  
  213. };
  214.  
  215. this.panCamera = function () {
  216.  
  217. var mouseChange = _panEnd.clone().sub( _panStart );
  218.  
  219. if ( mouseChange.lengthSq() ) {
  220.  
  221. mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
  222.  
  223. var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x );
  224. pan.add( _this.object.up.clone().setLength( mouseChange.y ) );
  225.  
  226. _this.object.position.add( pan );
  227. _this.target.add( pan );
  228.  
  229. if ( _this.staticMoving ) {
  230.  
  231. _panStart = _panEnd;
  232.  
  233. } else {
  234.  
  235. _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
  236.  
  237. }
  238.  
  239. }
  240.  
  241. };
  242.  
  243. this.checkDistances = function () {
  244.  
  245. if ( !_this.noZoom || !_this.noPan ) {
  246.  
  247. if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
  248.  
  249. _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
  250.  
  251. }
  252.  
  253. if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
  254.  
  255. _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
  256.  
  257. }
  258.  
  259. }
  260.  
  261. };
  262.  
  263. this.update = function () {
  264.  
  265. _eye.subVectors( _this.object.position, _this.target );
  266.  
  267. if ( !_this.noRotate ) {
  268.  
  269. _this.rotateCamera();
  270.  
  271. }
  272.  
  273. if ( !_this.noZoom ) {
  274.  
  275. _this.zoomCamera();
  276.  
  277. }
  278.  
  279. if ( !_this.noPan ) {
  280.  
  281. _this.panCamera();
  282.  
  283. }
  284.  
  285. _this.object.position.addVectors( _this.target, _eye );
  286.  
  287. _this.checkDistances();
  288.  
  289. _this.object.lookAt( _this.target );
  290.  
  291. if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) {
  292.  
  293. _this.dispatchEvent( changeEvent );
  294.  
  295. lastPosition.copy( _this.object.position );
  296.  
  297. }
  298.  
  299. };
  300.  
  301. this.reset = function () {
  302.  
  303. _state = STATE.NONE;
  304. _prevState = STATE.NONE;
  305.  
  306. _this.target.copy( _this.target0 );
  307. _this.object.position.copy( _this.position0 );
  308. _this.object.up.copy( _this.up0 );
  309.  
  310. _eye.subVectors( _this.object.position, _this.target );
  311.  
  312. _this.object.lookAt( _this.target );
  313.  
  314. _this.dispatchEvent( changeEvent );
  315.  
  316. lastPosition.copy( _this.object.position );
  317.  
  318. };
  319.  
  320. // listeners
  321.  
  322. function keydown( event ) {
  323.  
  324. if ( _this.enabled === false ) return;
  325.  
  326. window.removeEventListener( 'keydown', keydown );
  327.  
  328. _prevState = _state;
  329.  
  330. if ( _state !== STATE.NONE ) {
  331.  
  332. return;
  333.  
  334. } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
  335.  
  336. _state = STATE.ROTATE;
  337.  
  338. } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
  339.  
  340. _state = STATE.ZOOM;
  341.  
  342. } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
  343.  
  344. _state = STATE.PAN;
  345.  
  346. }
  347.  
  348. }
  349.  
  350. function keyup( event ) {
  351.  
  352. if ( _this.enabled === false ) return;
  353.  
  354. _state = _prevState;
  355.  
  356. window.addEventListener( 'keydown', keydown, false );
  357.  
  358. }
  359.  
  360. function mousedown( event ) {
  361.  
  362. if ( _this.enabled === false ) return;
  363.  
  364. event.preventDefault();
  365. event.stopPropagation();
  366.  
  367. if ( _state === STATE.NONE ) {
  368.  
  369. _state = event.button;
  370.  
  371. }
  372.  
  373. if ( _state === STATE.ROTATE && !_this.noRotate ) {
  374.  
  375. _rotateStart = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
  376. _rotateEnd.copy(_rotateStart)
  377.  
  378. } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
  379.  
  380. _zoomStart = _this.getMouseOnScreen( event.clientX, event.clientY );
  381. _zoomEnd.copy(_zoomStart);
  382.  
  383. } else if ( _state === STATE.PAN && !_this.noPan ) {
  384.  
  385. _panStart = _this.getMouseOnScreen( event.clientX, event.clientY );
  386. _panEnd.copy(_panStart)
  387.  
  388. }
  389.  
  390. document.addEventListener( 'mousemove', mousemove, false );
  391. document.addEventListener( 'mouseup', mouseup, false );
  392.  
  393. }
  394.  
  395. function mousemove( event ) {
  396.  
  397. if ( _this.enabled === false ) return;
  398.  
  399. event.preventDefault();
  400. event.stopPropagation();
  401.  
  402. if ( _state === STATE.ROTATE && !_this.noRotate ) {
  403.  
  404. _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
  405.  
  406. } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
  407.  
  408. _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  409.  
  410. } else if ( _state === STATE.PAN && !_this.noPan ) {
  411.  
  412. _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
  413.  
  414. }
  415.  
  416. }
  417.  
  418. function mouseup( event ) {
  419.  
  420. if ( _this.enabled === false ) return;
  421.  
  422. event.preventDefault();
  423. event.stopPropagation();
  424.  
  425. _state = STATE.NONE;
  426.  
  427. document.removeEventListener( 'mousemove', mousemove );
  428. document.removeEventListener( 'mouseup', mouseup );
  429.  
  430. }
  431.  
  432. function mousewheel( event ) {
  433.  
  434. if ( _this.enabled === false ) return;
  435.  
  436. event.preventDefault();
  437. event.stopPropagation();
  438.  
  439. var delta = 0;
  440.  
  441. if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
  442.  
  443. delta = event.wheelDelta / 40;
  444.  
  445. } else if ( event.detail ) { // Firefox
  446.  
  447. delta = - event.detail / 3;
  448.  
  449. }
  450.  
  451. _zoomStart.y += delta * 0.01;
  452.  
  453. }
  454.  
  455. function touchstart( event ) {
  456.  
  457. if ( _this.enabled === false ) return;
  458.  
  459. switch ( event.touches.length ) {
  460.  
  461. case 1:
  462. _state = STATE.TOUCH_ROTATE;
  463. _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  464. break;
  465.  
  466. case 2:
  467. _state = STATE.TOUCH_ZOOM;
  468. var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
  469. var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
  470. _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
  471. break;
  472.  
  473. case 3:
  474. _state = STATE.TOUCH_PAN;
  475. _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  476. break;
  477.  
  478. default:
  479. _state = STATE.NONE;
  480.  
  481. }
  482.  
  483. }
  484.  
  485. function touchmove( event ) {
  486.  
  487. if ( _this.enabled === false ) return;
  488.  
  489. event.preventDefault();
  490. event.stopPropagation();
  491.  
  492. switch ( event.touches.length ) {
  493.  
  494. case 1:
  495. _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  496. break;
  497.  
  498. case 2:
  499. var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
  500. var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
  501. _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy )
  502. break;
  503.  
  504. case 3:
  505. _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  506. break;
  507.  
  508. default:
  509. _state = STATE.NONE;
  510.  
  511. }
  512.  
  513. }
  514.  
  515. function touchend( event ) {
  516.  
  517. if ( _this.enabled === false ) return;
  518.  
  519. switch ( event.touches.length ) {
  520.  
  521. case 1:
  522. _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  523. break;
  524.  
  525. case 2:
  526. _touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
  527. break;
  528.  
  529. case 3:
  530. _panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
  531. break;
  532.  
  533. }
  534.  
  535. _state = STATE.NONE;
  536.  
  537. }
  538.  
  539. this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
  540.  
  541. this.domElement.addEventListener( 'mousedown', mousedown, false );
  542.  
  543. this.domElement.addEventListener( 'mousewheel', mousewheel, false );
  544. this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
  545.  
  546. this.domElement.addEventListener( 'touchstart', touchstart, false );
  547. this.domElement.addEventListener( 'touchend', touchend, false );
  548. this.domElement.addEventListener( 'touchmove', touchmove, false );
  549.  
  550. window.addEventListener( 'keydown', keydown, false );
  551. window.addEventListener( 'keyup', keyup, false );
  552.  
  553. this.handleResize();
  554.  
  555. };
  556.  
  557. THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement