Rotation.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import * as THREE from "three";
  2. // window.log = function()
  3. // {
  4. // if (this.console)
  5. // {
  6. // console.log(Array.prototype.slice.call(arguments));
  7. // }
  8. // };
  9. // Namespace
  10. var Defmech = Defmech ||
  11. {};
  12. Defmech.RotationWithQuaternion = (function()
  13. {
  14. 'use_strict';
  15. var container;
  16. var camera, scene, renderer;
  17. var cube, plane;
  18. var mouseDown = false;
  19. var rotateStartPoint = new THREE.Vector3(0, 0, 1);
  20. var rotateEndPoint = new THREE.Vector3(0, 0, 1);
  21. var curQuaternion;
  22. var windowHalfX = window.innerWidth / 2;
  23. var windowHalfY = window.innerHeight / 2;
  24. var rotationSpeed = 2;
  25. var lastMoveTimestamp,
  26. moveReleaseTimeDelta = 50;
  27. var startPoint = {
  28. x: 0,
  29. y: 0
  30. };
  31. var deltaX = 0,
  32. deltaY = 0;
  33. var setup = function()
  34. {
  35. container = document.createElement('div');
  36. document.body.appendChild(container);
  37. var info = document.createElement('div');
  38. info.style.position = 'absolute';
  39. info.style.top = '10px';
  40. info.style.width = '100%';
  41. info.style.textAlign = 'center';
  42. info.innerHTML = 'Drag to spin the cube';
  43. container.appendChild(info);
  44. camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
  45. camera.position.y = 150;
  46. camera.position.z = 500;
  47. scene = new THREE.Scene();
  48. // Cube
  49. var boxGeometry = new THREE.BoxGeometry(200, 200, 200);
  50. for (var i = 0; i < boxGeometry.faces.length; i += 2)
  51. {
  52. var color = {
  53. h: (1 / (boxGeometry.faces.length)) * i,
  54. s: 0.5,
  55. l: 0.5
  56. };
  57. boxGeometry.faces[i].color.setHSL(color.h, color.s, color.l);
  58. boxGeometry.faces[i + 1].color.setHSL(color.h, color.s, color.l);
  59. }
  60. var cubeMaterial = new THREE.MeshBasicMaterial(
  61. {
  62. vertexColors: THREE.FaceColors,
  63. overdraw: 0.5
  64. });
  65. cube = new THREE.Mesh(boxGeometry, cubeMaterial);
  66. cube.position.y = 200;
  67. scene.add(cube);
  68. // Plane
  69. var planeGeometry = new THREE.PlaneGeometry(200, 200);
  70. planeGeometry.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
  71. var planeMaterial = new THREE.MeshBasicMaterial(
  72. {
  73. color: 0xe0e0e0,
  74. overdraw: 0.5
  75. });
  76. plane = new THREE.Mesh(planeGeometry, planeMaterial);
  77. scene.add(plane);
  78. renderer = new THREE.CanvasRenderer();
  79. renderer.setClearColor(0xf0f0f0);
  80. renderer.setSize(window.innerWidth, window.innerHeight);
  81. container.appendChild(renderer.domElement);
  82. document.addEventListener('mousedown', onDocumentMouseDown, false);
  83. window.addEventListener('resize', onWindowResize, false);
  84. animate();
  85. };
  86. function onWindowResize()
  87. {
  88. windowHalfX = window.innerWidth / 2;
  89. windowHalfY = window.innerHeight / 2;
  90. camera.aspect = window.innerWidth / window.innerHeight;
  91. camera.updateProjectionMatrix();
  92. renderer.setSize(window.innerWidth, window.innerHeight);
  93. }
  94. function onDocumentMouseDown(event)
  95. {
  96. event.preventDefault();
  97. document.addEventListener('mousemove', onDocumentMouseMove, false);
  98. document.addEventListener('mouseup', onDocumentMouseUp, false);
  99. mouseDown = true;
  100. startPoint = {
  101. x: event.clientX,
  102. y: event.clientY
  103. };
  104. rotateStartPoint = rotateEndPoint = projectOnTrackball(0, 0);
  105. }
  106. function onDocumentMouseMove(event)
  107. {
  108. deltaX = event.x - startPoint.x;
  109. deltaY = event.y - startPoint.y;
  110. handleRotation();
  111. startPoint.x = event.x;
  112. startPoint.y = event.y;
  113. lastMoveTimestamp = new Date();
  114. }
  115. function onDocumentMouseUp(event)
  116. {
  117. if (new Date().getTime() - lastMoveTimestamp.getTime() > moveReleaseTimeDelta)
  118. {
  119. deltaX = event.x - startPoint.x;
  120. deltaY = event.y - startPoint.y;
  121. }
  122. mouseDown = false;
  123. document.removeEventListener('mousemove', onDocumentMouseMove, false);
  124. document.removeEventListener('mouseup', onDocumentMouseUp, false);
  125. }
  126. function projectOnTrackball(touchX, touchY)
  127. {
  128. var mouseOnBall = new THREE.Vector3();
  129. mouseOnBall.set(
  130. clamp(touchX / windowHalfX, -1, 1), clamp(-touchY / windowHalfY, -1, 1),
  131. 0.0
  132. );
  133. var length = mouseOnBall.length();
  134. if (length > 1.0)
  135. {
  136. mouseOnBall.normalize();
  137. }
  138. else
  139. {
  140. mouseOnBall.z = Math.sqrt(1.0 - length * length);
  141. }
  142. return mouseOnBall;
  143. }
  144. function rotateMatrix(rotateStart, rotateEnd)
  145. {
  146. var axis = new THREE.Vector3(),
  147. quaternion = new THREE.Quaternion();
  148. var angle = Math.acos(rotateStart.dot(rotateEnd) / rotateStart.length() / rotateEnd.length());
  149. if (angle)
  150. {
  151. axis.crossVectors(rotateStart, rotateEnd).normalize();
  152. angle *= rotationSpeed;
  153. quaternion.setFromAxisAngle(axis, angle);
  154. }
  155. return quaternion;
  156. }
  157. function clamp(value, min, max)
  158. {
  159. return Math.min(Math.max(value, min), max);
  160. }
  161. function animate()
  162. {
  163. requestAnimationFrame(animate);
  164. render();
  165. }
  166. function render()
  167. {
  168. if (!mouseDown)
  169. {
  170. var drag = 0.95;
  171. var minDelta = 0.05;
  172. if (deltaX < -minDelta || deltaX > minDelta)
  173. {
  174. deltaX *= drag;
  175. }
  176. else
  177. {
  178. deltaX = 0;
  179. }
  180. if (deltaY < -minDelta || deltaY > minDelta)
  181. {
  182. deltaY *= drag;
  183. }
  184. else
  185. {
  186. deltaY = 0;
  187. }
  188. handleRotation();
  189. }
  190. renderer.render(scene, camera);
  191. }
  192. var handleRotation = function()
  193. {
  194. rotateEndPoint = projectOnTrackball(deltaX, deltaY);
  195. var rotateQuaternion = rotateMatrix(rotateStartPoint, rotateEndPoint);
  196. curQuaternion = cube.quaternion;
  197. curQuaternion.multiplyQuaternions(rotateQuaternion, curQuaternion);
  198. curQuaternion.normalize();
  199. cube.setRotationFromQuaternion(curQuaternion);
  200. rotateEndPoint = rotateStartPoint;
  201. };
  202. // PUBLIC INTERFACE
  203. return {
  204. init: function()
  205. {
  206. setup();
  207. }
  208. };
  209. })();
  210. document.onreadystatechange = function()
  211. {
  212. if (document.readyState === 'complete')
  213. {
  214. Defmech.RotationWithQuaternion.init();
  215. }
  216. };