aframe-route-component.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /******/ (function(modules) { // webpackBootstrap
  2. /******/ // The module cache
  3. /******/ var installedModules = {};
  4. /******/ // The require function
  5. /******/ function __webpack_require__(moduleId) {
  6. /******/ // Check if module is in cache
  7. /******/ if(installedModules[moduleId])
  8. /******/ return installedModules[moduleId].exports;
  9. /******/ // Create a new module (and put it into the cache)
  10. /******/ var module = installedModules[moduleId] = {
  11. /******/ exports: {},
  12. /******/ id: moduleId,
  13. /******/ loaded: false
  14. /******/ };
  15. /******/ // Execute the module function
  16. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  17. /******/ // Flag the module as loaded
  18. /******/ module.loaded = true;
  19. /******/ // Return the exports of the module
  20. /******/ return module.exports;
  21. /******/ }
  22. /******/ // expose the modules object (__webpack_modules__)
  23. /******/ __webpack_require__.m = modules;
  24. /******/ // expose the module cache
  25. /******/ __webpack_require__.c = installedModules;
  26. /******/ // __webpack_public_path__
  27. /******/ __webpack_require__.p = "";
  28. /******/ // Load entry module and return exports
  29. /******/ return __webpack_require__(0);
  30. /******/ })
  31. /************************************************************************/
  32. /******/ ([
  33. /* 0 */
  34. /***/ (function(module, exports) {
  35. /* global AFRAME */
  36. if (typeof AFRAME === 'undefined') {
  37. throw new Error('Component attempted to register before AFRAME was available.');
  38. }
  39. var zAxis = new THREE.Vector3(0, 0, 1);
  40. var degToRad = THREE.Math.degToRad;
  41. AFRAME.registerComponent('route-point', {
  42. //dependencies: ['position'],
  43. schema: {},
  44. init: function () {
  45. this.el.addEventListener("componentchanged", this.changeHandler.bind(this));
  46. this.el.emit("curve-point-change");
  47. },
  48. changeHandler: function (event) {
  49. if (event.detail.name == "position") {
  50. this.el.emit("curve-point-change");
  51. }
  52. }
  53. });
  54. AFRAME.registerComponent('curve', {
  55. //dependencies: ['curve-point'],
  56. schema: {
  57. type: {
  58. type: 'string',
  59. default: 'CurvePath',
  60. oneOf: ['CatmullRom', 'CubicBezier', 'QuadraticBezier', 'Line', 'CurvePath']
  61. },
  62. closed: {
  63. type: 'boolean',
  64. default: false
  65. }
  66. },
  67. init: function () {
  68. this.pathPoints = null;
  69. this.curve = null;
  70. this.el.addEventListener("curve-point-change", this.update.bind(this));
  71. },
  72. update: function (oldData) {
  73. this.points = Array.from(this.el.querySelectorAll("a-curve-point, [curve-point]"));
  74. if (this.points.length <= 1) {
  75. console.warn("At least 2 curve-points needed to draw a curve");
  76. this.curve = null;
  77. } else {
  78. // Get Array of Positions from Curve-Points
  79. var pointsArray = this.points.map(function (point) {
  80. if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
  81. return point;
  82. }
  83. return point.object3D.getWorldPosition();
  84. });
  85. // Update the Curve if either the Curve-Points or other Properties changed
  86. if (!AFRAME.utils.deepEqual(pointsArray, this.pathPoints) || (oldData !== 'CustomEvent' && !AFRAME.utils.deepEqual(this.data, oldData))) {
  87. this.curve = null;
  88. this.pathPoints = pointsArray;
  89. // Create Curve
  90. switch (this.data.type) {
  91. case 'CubicBezier':
  92. if (this.pathPoints.length != 4) {
  93. throw new Error('The Three constructor of type CubicBezierCurve3 requires 4 points');
  94. }
  95. this.curve = new THREE.CubicBezierCurve3(this.pathPoints[0], this.pathPoints[1], this.pathPoints[2], this.pathPoints[3]);
  96. break;
  97. case 'QuadraticBezier':
  98. if (this.pathPoints.length != 3) {
  99. throw new Error('The Three constructor of type QuadraticBezierCurve3 requires 3 points');
  100. }
  101. this.curve = new THREE.QuadraticBezierCurve3(this.pathPoints[0], this.pathPoints[1], this.pathPoints[2]);
  102. break;
  103. case 'Line':
  104. if (this.pathPoints.length != 2) {
  105. throw new Error('The Three constructor of type LineCurve3 requires 2 points');
  106. }
  107. this.curve = new THREE.LineCurve3(this.pathPoints[0], this.pathPoints[1]);
  108. break;
  109. case 'CatmullRom':
  110. this.curve = new THREE.CatmullRomCurve3(this.pathPoints);
  111. break;
  112. case 'Spline':
  113. this.curve = new THREE.SplineCurve3(this.pathPoints);
  114. break;
  115. // Patrick
  116. case 'CurvePath':
  117. this.curve = new THREE.CurvePath();
  118. for(var i = 0, p = this.pathPoints.length - 1; i < p; i++) {
  119. var curveSegment = new THREE.LineCurve3(this.pathPoints[i], this.pathPoints[i + 1]);
  120. this.curve.add(curveSegment);
  121. }
  122. break;
  123. default:
  124. throw new Error('No Three constructor of type (case sensitive): ' + this.data.type + 'Curve3');
  125. }
  126. this.curve.closed = this.data.closed;
  127. this.el.emit('curve-updated');
  128. }
  129. }
  130. },
  131. remove: function () {
  132. this.el.removeEventListener("curve-point-change", this.update.bind(this));
  133. },
  134. closestPointInLocalSpace: function closestPoint(point, resolution, testPoint, currentRes) {
  135. if (!this.curve) throw Error('Curve not instantiated yet.');
  136. resolution = resolution || 0.1 / this.curve.getLength();
  137. currentRes = currentRes || 0.5;
  138. testPoint = testPoint || 0.5;
  139. currentRes /= 2;
  140. var aTest = testPoint + currentRes;
  141. var bTest = testPoint - currentRes;
  142. var a = this.curve.getPointAt(aTest);
  143. var b = this.curve.getPointAt(bTest);
  144. var aDistance = a.distanceTo(point);
  145. var bDistance = b.distanceTo(point);
  146. var aSmaller = aDistance < bDistance;
  147. if (currentRes < resolution) {
  148. var tangent = this.curve.getTangentAt(aSmaller ? aTest : bTest);
  149. if (currentRes < resolution) return {
  150. result: aSmaller ? aTest : bTest,
  151. location: aSmaller ? a : b,
  152. distance: aSmaller ? aDistance : bDistance,
  153. normal: normalFromTangent(tangent),
  154. tangent: tangent
  155. };
  156. }
  157. if (aDistance < bDistance) {
  158. return this.closestPointInLocalSpace(point, resolution, aTest, currentRes);
  159. } else {
  160. return this.closestPointInLocalSpace(point, resolution, bTest, currentRes);
  161. }
  162. }
  163. });
  164. var tempQuaternion = new THREE.Quaternion();
  165. function normalFromTangent(tangent) {
  166. var lineEnd = new THREE.Vector3(0, 1, 0);
  167. tempQuaternion.setFromUnitVectors(zAxis, tangent);
  168. lineEnd.applyQuaternion(tempQuaternion);
  169. return lineEnd;
  170. }
  171. AFRAME.registerShader('line', {
  172. schema: {
  173. color: {default: '#ff0000'},
  174. },
  175. init: function (data) {
  176. this.material = new THREE.LineBasicMaterial(data);
  177. },
  178. update: function (data) {
  179. this.material = new THREE.LineBasicMaterial(data);
  180. },
  181. });
  182. AFRAME.registerComponent('draw-curve', {
  183. //dependencies: ['curve', 'material'],
  184. schema: {
  185. curve: {type: 'selector'}
  186. },
  187. init: function () {
  188. console.log(this.data);
  189. this.data.curve.addEventListener('curve-updated', this.update.bind(this));
  190. },
  191. update: function () {
  192. if (this.data.curve) {
  193. this.curve = this.data.curve.components.curve;
  194. }
  195. if (this.curve && this.curve.curve) {
  196. var lineGeometry = new THREE.BufferGeometry().setFromPoints(this.curve.curve.getPoints(this.curve.curve.getPoints().length * 10));
  197. var mesh = this.el.getOrCreateObject3D('mesh', THREE.Line);
  198. lineMaterial = mesh.material ? mesh.material : new THREE.LineBasicMaterial({
  199. color: "#ff0000"
  200. });
  201. this.el.setObject3D('mesh', new THREE.Line(lineGeometry, lineMaterial));
  202. }
  203. },
  204. remove: function () {
  205. this.data.curve.removeEventListener('curve-updated', this.update.bind(this));
  206. this.el.getObject3D('mesh').geometry = new THREE.Geometry();
  207. }
  208. });
  209. AFRAME.registerComponent('clone-along-curve', {
  210. //dependencies: ['curve'],
  211. schema: {
  212. curve: {type: 'selector'},
  213. spacing: {default: 1},
  214. rotation: {
  215. type: 'vec3',
  216. default: '0 0 0'
  217. },
  218. scale: {
  219. type: 'vec3',
  220. default: '1 1 1'
  221. }
  222. },
  223. init: function () {
  224. this.el.addEventListener('model-loaded', this.update.bind(this));
  225. this.data.curve.addEventListener('curve-updated', this.update.bind(this));
  226. },
  227. update: function () {
  228. this.remove();
  229. if (this.data.curve) {
  230. this.curve = this.data.curve.components.curve;
  231. }
  232. console.log(this.curve);
  233. if (!this.el.getObject3D('clones') && this.curve && this.curve.curve) {
  234. var mesh = this.el.getObject3D('mesh');
  235. var length = this.curve.curve.getLength();
  236. var start = 0;
  237. var counter = start;
  238. var cloneMesh = this.el.getOrCreateObject3D('clones', THREE.Group);
  239. var parent = new THREE.Object3D();
  240. mesh.scale.set(this.data.scale.x, this.data.scale.y, this.data.scale.z);
  241. mesh.rotation.set(degToRad(this.data.rotation.x), degToRad(this.data.rotation.y), degToRad(this.data.rotation.z));
  242. mesh.rotation.order = 'YXZ';
  243. parent.add(mesh);
  244. while (counter <= length) {
  245. var child = parent.clone(true);
  246. child.position.copy(this.curve.curve.getPointAt(counter / length));
  247. tangent = this.curve.curve.getTangentAt(counter / length).normalize();
  248. child.quaternion.setFromUnitVectors(zAxis, tangent);
  249. cloneMesh.add(child);
  250. counter += this.data.spacing;
  251. }
  252. }
  253. },
  254. remove: function () {
  255. this.curve = null;
  256. if (this.el.getObject3D('clones')) {
  257. this.el.removeObject3D('clones');
  258. }
  259. }
  260. });
  261. AFRAME.registerPrimitive('a-draw-curve', {
  262. defaultComponents: {
  263. 'draw-curve': {},
  264. },
  265. mappings: {
  266. curveref: 'draw-curve.curve',
  267. }
  268. });
  269. AFRAME.registerPrimitive('a-curve-point', {
  270. defaultComponents: {
  271. 'curve-point': {},
  272. },
  273. mappings: {}
  274. });
  275. AFRAME.registerPrimitive('a-curve', {
  276. defaultComponents: {
  277. 'curve': {}
  278. },
  279. mappings: {
  280. type: 'curve.type',
  281. }
  282. });
  283. /***/ })
  284. /******/ ]);