Radix.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. var Sandbox;
  2. (function (Sandbox) {
  3. var Color3 = BABYLON.Color3;
  4. var StandardMaterial = BABYLON.StandardMaterial;
  5. var Matrix = BABYLON.Matrix;
  6. var Mesh = BABYLON.Mesh;
  7. var Vector3 = BABYLON.Vector3;
  8. var Quaternion = BABYLON.Quaternion;
  9. var VertexData = BABYLON.VertexData;
  10. var LinesMesh = BABYLON.LinesMesh;
  11. /**
  12. * This class create the visual geometry to display a manipulation radix in a viewport.
  13. * It also implements the logic to handler intersection, hover on feature.
  14. */
  15. var Radix = (function () {
  16. /**
  17. * Create a new Radix instance. The length/radius members are optionals and the default value should suit most cases
  18. * @param scene the owner Scene
  19. * @param features the feature the radix must display
  20. * @param arrowLength the length of a row of an axis, include the rotation cylinder (if any), but always exclude the arrow cone
  21. * @param coneLength the length of the arrow cone. this is also the length taken for the rotation cylinder (if any)
  22. * @param coneRadius the radius of the arrow cone
  23. * @param planeSelectionLength the length of the selection plane
  24. */
  25. function Radix(scene, features, arrowLength, coneLength, coneRadius, planeSelectionLength) {
  26. if (features === void 0) { features = 7 /* ArrowsXYZ */ | 112 /* AllPlanesSelection */ | 1792 /* Rotations */; }
  27. this._scene = scene;
  28. this._arrowLength = arrowLength ? arrowLength : 1;
  29. this._coneLength = coneLength ? coneLength : 0.2;
  30. this._coneRadius = coneRadius ? coneRadius : 0.1;
  31. this._planeSelectionLength = planeSelectionLength ? planeSelectionLength : (this._arrowLength / 5.0);
  32. this._wireSelectionThreshold = 0.05;
  33. this._light1 = new BABYLON.PointLight("ManipulatorLight", new BABYLON.Vector3(50, 50, 70), this._scene);
  34. this._light1.id = "***SceneManipulatorLight***";
  35. this._light2 = new BABYLON.PointLight("ManipulatorLight", new BABYLON.Vector3(-50, -50, -70), this._scene);
  36. this._light2.id = "***SceneManipulatorLight***";
  37. this._xArrowColor = new Color3(Radix.pc, Radix.sc / 2, Radix.sc);
  38. this._yArrowColor = new Color3(Radix.sc, Radix.pc, Radix.sc / 2);
  39. this._zArrowColor = new Color3(Radix.sc / 2, Radix.sc, Radix.pc);
  40. this._xyPlaneSelectionColor = new Color3(Radix.pc / 1.1, Radix.pc / 1.3, Radix.sc);
  41. this._xzPlaneSelectionColor = new Color3(Radix.pc / 1.1, Radix.sc, Radix.pc / 1.3);
  42. this._yzPlaneSelectionColor = new Color3(Radix.sc, Radix.pc / 1.3, Radix.pc / 1.1);
  43. var materials = [];
  44. materials.push({ name: "arrowX", color: this.xArrowColor });
  45. materials.push({ name: "arrowY", color: this.yArrowColor });
  46. materials.push({ name: "arrowZ", color: this.zArrowColor });
  47. materials.push({ name: "planeXY", color: this.xyPlaneSelectionColor });
  48. materials.push({ name: "planeXZ", color: this.xzPlaneSelectionColor });
  49. materials.push({ name: "planeYZ", color: this.yzPlaneSelectionColor });
  50. materials.push({ name: "rotationX", color: this.xArrowColor.clone() });
  51. materials.push({ name: "rotationY", color: this.yArrowColor.clone() });
  52. materials.push({ name: "rotationZ", color: this.zArrowColor.clone() });
  53. this._materials = [];
  54. for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) {
  55. var matData = materials_1[_i];
  56. var mtl = new StandardMaterial(matData.name + "RadixMaterial", this._scene);
  57. mtl.diffuseColor = matData.color;
  58. this._materials[matData.name] = mtl;
  59. }
  60. this._features = features;
  61. this._rootMesh = new Mesh("radixRoot", this._scene);
  62. this._rootMesh.renderingGroupId = 1;
  63. this.constructGraphicalObjects();
  64. }
  65. Object.defineProperty(Radix.prototype, "wireSelectionThreshold", {
  66. /**
  67. * Set/get the Wire Selection Threshold, set a bigger value to improve tolerance while picking a wire mesh
  68. */
  69. get: function () {
  70. return this._wireSelectionThreshold;
  71. },
  72. set: function (value) {
  73. this._wireSelectionThreshold = value;
  74. var meshes = this._rootMesh.getChildMeshes(true, function (m) { return m instanceof LinesMesh; });
  75. for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
  76. var mesh = meshes_1[_i];
  77. var lm = mesh;
  78. if (lm) {
  79. lm.intersectionThreshold = value;
  80. }
  81. }
  82. },
  83. enumerable: true,
  84. configurable: true
  85. });
  86. Object.defineProperty(Radix.prototype, "xArrowColor", {
  87. /**
  88. * Get/set the colors of the X Arrow
  89. */
  90. get: function () {
  91. return this._xArrowColor;
  92. },
  93. set: function (value) {
  94. this._xArrowColor = value;
  95. this.updateMaterial("arrowX", value);
  96. this.updateMaterial("rotationX", value);
  97. },
  98. enumerable: true,
  99. configurable: true
  100. });
  101. Object.defineProperty(Radix.prototype, "yArrowColor", {
  102. /**
  103. * Get/set the colors of the Y Arrow
  104. */
  105. get: function () {
  106. return this._yArrowColor;
  107. },
  108. set: function (value) {
  109. this._yArrowColor = value;
  110. this.updateMaterial("arrowY", value);
  111. this.updateMaterial("rotationY", value);
  112. },
  113. enumerable: true,
  114. configurable: true
  115. });
  116. Object.defineProperty(Radix.prototype, "zArrowColor", {
  117. /**
  118. * Get/set the colors of the Z Arrow
  119. */
  120. get: function () {
  121. return this._zArrowColor;
  122. },
  123. set: function (value) {
  124. this._zArrowColor = value;
  125. this.updateMaterial("arrowZ", value);
  126. this.updateMaterial("rotationZ", value);
  127. },
  128. enumerable: true,
  129. configurable: true
  130. });
  131. Object.defineProperty(Radix.prototype, "xyPlaneSelectionColor", {
  132. /**
  133. * Get/set the colors of the XY Plane selection anchor
  134. */
  135. get: function () {
  136. return this._xyPlaneSelectionColor;
  137. },
  138. set: function (value) {
  139. this._xyPlaneSelectionColor = value;
  140. },
  141. enumerable: true,
  142. configurable: true
  143. });
  144. Object.defineProperty(Radix.prototype, "xzPlaneSelectionColor", {
  145. /**
  146. * Get/set the colors of the XZ Plane selection anchor
  147. */
  148. get: function () {
  149. return this._xzPlaneSelectionColor;
  150. },
  151. set: function (value) {
  152. this._xzPlaneSelectionColor = value;
  153. },
  154. enumerable: true,
  155. configurable: true
  156. });
  157. Object.defineProperty(Radix.prototype, "yzPlaneSelectionColor", {
  158. /**
  159. * Get/set the colors of the YZ Plane selection anchor
  160. */
  161. get: function () {
  162. return this._yzPlaneSelectionColor;
  163. },
  164. set: function (value) {
  165. this._yzPlaneSelectionColor = value;
  166. },
  167. enumerable: true,
  168. configurable: true
  169. });
  170. Object.defineProperty(Radix.prototype, "highlighted", {
  171. /**
  172. * Get/set the feature of the Radix that are/must be highlighted
  173. * @returns {}
  174. */
  175. get: function () {
  176. return this._highlighted;
  177. },
  178. set: function (value) {
  179. this.updateMaterialFromHighlighted(1 /* ArrowX */, value, "arrowX");
  180. this.updateMaterialFromHighlighted(2 /* ArrowY */, value, "arrowY");
  181. this.updateMaterialFromHighlighted(4 /* ArrowZ */, value, "arrowZ");
  182. this.updateMaterialFromHighlighted(16 /* PlaneSelectionXY */, value, "planeXY");
  183. this.updateMaterialFromHighlighted(32 /* PlaneSelectionXZ */, value, "planeXZ");
  184. this.updateMaterialFromHighlighted(64 /* PlaneSelectionYZ */, value, "planeYZ");
  185. this.updateMaterialFromHighlighted(256 /* RotationX */, value, "rotationX");
  186. this.updateMaterialFromHighlighted(512 /* RotationY */, value, "rotationY");
  187. this.updateMaterialFromHighlighted(1024 /* RotationZ */, value, "rotationZ");
  188. this._highlighted = value;
  189. },
  190. enumerable: true,
  191. configurable: true
  192. });
  193. Object.defineProperty(Radix.prototype, "features", {
  194. /**
  195. * Get the Radix Features that were selected upon creation
  196. */
  197. get: function () {
  198. return this._features;
  199. },
  200. enumerable: true,
  201. configurable: true
  202. });
  203. /**
  204. * make an intersection test between a point position in the viwport and the Radix, return the feature that is intersected, if any.
  205. * only the closer Radix Feature is picked.
  206. * @param pos the viewport position to create the picking ray from.
  207. */
  208. Radix.prototype.intersect = function (pos) {
  209. var hit = 0 /* None */;
  210. var closest = Number.MAX_VALUE;
  211. // Arrows
  212. if (this.hasFeature(1 /* ArrowX */)) {
  213. var dist = this.intersectMeshes(pos, "arrowX", closest);
  214. if (dist < closest) {
  215. closest = dist;
  216. hit = 1 /* ArrowX */;
  217. }
  218. }
  219. if (this.hasFeature(2 /* ArrowY */)) {
  220. var dist = this.intersectMeshes(pos, "arrowY", closest);
  221. if (dist < closest) {
  222. closest = dist;
  223. hit = 2 /* ArrowY */;
  224. }
  225. }
  226. if (this.hasFeature(4 /* ArrowZ */)) {
  227. var dist = this.intersectMeshes(pos, "arrowZ", closest);
  228. if (dist < closest) {
  229. closest = dist;
  230. hit = 4 /* ArrowZ */;
  231. }
  232. }
  233. // Planes
  234. if (this.hasFeature(16 /* PlaneSelectionXY */)) {
  235. var dist = this.intersectMeshes(pos, "planeXY", closest);
  236. if (dist < closest) {
  237. closest = dist;
  238. hit = 16 /* PlaneSelectionXY */;
  239. }
  240. }
  241. if (this.hasFeature(32 /* PlaneSelectionXZ */)) {
  242. var dist = this.intersectMeshes(pos, "planeXZ", closest);
  243. if (dist < closest) {
  244. closest = dist;
  245. hit = 32 /* PlaneSelectionXZ */;
  246. }
  247. }
  248. if (this.hasFeature(64 /* PlaneSelectionYZ */)) {
  249. var dist = this.intersectMeshes(pos, "planeYZ", closest);
  250. if (dist < closest) {
  251. closest = dist;
  252. hit = 64 /* PlaneSelectionYZ */;
  253. }
  254. }
  255. // Rotation
  256. if (this.hasFeature(256 /* RotationX */)) {
  257. var dist = this.intersectMeshes(pos, "rotationX", closest);
  258. if (dist < closest) {
  259. closest = dist;
  260. hit = 256 /* RotationX */;
  261. }
  262. }
  263. if (this.hasFeature(512 /* RotationY */)) {
  264. var dist = this.intersectMeshes(pos, "rotationY", closest);
  265. if (dist < closest) {
  266. closest = dist;
  267. hit = 512 /* RotationY */;
  268. }
  269. }
  270. if (this.hasFeature(1024 /* RotationZ */)) {
  271. var dist = this.intersectMeshes(pos, "rotationZ", closest);
  272. if (dist < closest) {
  273. closest = dist;
  274. hit = 1024 /* RotationZ */;
  275. }
  276. }
  277. return hit;
  278. };
  279. /**
  280. * Set the world coordinate of where the Axis should be displayed
  281. * @param position the position
  282. * @param rotation the rotation quaternion
  283. * @param scale the scale (should be uniform)
  284. */
  285. Radix.prototype.setWorld = function (position, rotation, scale) {
  286. this._rootMesh.position = position;
  287. this._rootMesh.rotationQuaternion = rotation;
  288. this._rootMesh.scaling = scale;
  289. };
  290. /**
  291. * Display the Radix on screen
  292. */
  293. Radix.prototype.show = function () {
  294. this.setVisibleState(this._rootMesh, true);
  295. };
  296. /**
  297. * Hide the Radix from the screen
  298. */
  299. Radix.prototype.hide = function () {
  300. this.setVisibleState(this._rootMesh, false);
  301. };
  302. Radix.prototype.setVisibleState = function (mesh, state) {
  303. var _this = this;
  304. mesh.isVisible = state;
  305. mesh.getChildMeshes(true).forEach(function (m) { return _this.setVisibleState(m, state); });
  306. };
  307. Radix.prototype.intersectMeshes = function (pos, startName, currentClosest) {
  308. var meshes = this._rootMesh.getChildMeshes(true, function (m) { return m.name.indexOf(startName) === 0; });
  309. for (var _i = 0, meshes_2 = meshes; _i < meshes_2.length; _i++) {
  310. var mesh = meshes_2[_i];
  311. var ray = this._scene.createPickingRay(pos.x, pos.y, mesh.getWorldMatrix(), this._scene.activeCamera);
  312. var pi = mesh.intersects(ray, false);
  313. if (pi.hit && pi.distance < currentClosest) {
  314. currentClosest = pi.distance;
  315. }
  316. }
  317. return currentClosest;
  318. };
  319. Radix.prototype.constructGraphicalObjects = function () {
  320. var hp = Math.PI / 2;
  321. if (this.hasFeature(1 /* ArrowX */)) {
  322. this.constructArrow(1 /* ArrowX */, "arrowX", Matrix.RotationZ(-hp));
  323. }
  324. if (this.hasFeature(2 /* ArrowY */)) {
  325. this.constructArrow(2 /* ArrowY */, "arrowY", Matrix.Identity());
  326. }
  327. if (this.hasFeature(4 /* ArrowZ */)) {
  328. this.constructArrow(4 /* ArrowZ */, "arrowZ", Matrix.RotationX(hp));
  329. }
  330. if (this.hasFeature(16 /* PlaneSelectionXY */)) {
  331. this.constructPlaneSelection(16 /* PlaneSelectionXY */, "planeXY", Matrix.Identity());
  332. }
  333. if (this.hasFeature(32 /* PlaneSelectionXZ */)) {
  334. this.constructPlaneSelection(32 /* PlaneSelectionXZ */, "planeXZ", Matrix.RotationX(hp));
  335. }
  336. if (this.hasFeature(64 /* PlaneSelectionYZ */)) {
  337. this.constructPlaneSelection(64 /* PlaneSelectionYZ */, "planeYZ", Matrix.RotationY(-hp));
  338. }
  339. if (this.hasFeature(256 /* RotationX */)) {
  340. this.constructRotation(256 /* RotationX */, "rotationX", Matrix.RotationZ(-hp));
  341. }
  342. if (this.hasFeature(512 /* RotationY */)) {
  343. this.constructRotation(512 /* RotationY */, "rotationY", Matrix.Identity());
  344. }
  345. if (this.hasFeature(1024 /* RotationZ */)) {
  346. this.constructRotation(1024 /* RotationZ */, "rotationZ", Matrix.RotationX(hp));
  347. }
  348. };
  349. Radix.prototype.constructArrow = function (feature, name, transform) {
  350. var mtl = this.getMaterial(name);
  351. var hasRot;
  352. switch (feature) {
  353. case 1 /* ArrowX */:
  354. hasRot = this.hasFeature(256 /* RotationX */);
  355. break;
  356. case 2 /* ArrowY */:
  357. hasRot = this.hasFeature(512 /* RotationY */);
  358. break;
  359. case 4 /* ArrowZ */:
  360. hasRot = this.hasFeature(1024 /* RotationZ */);
  361. break;
  362. }
  363. var rotation = Quaternion.FromRotationMatrix(transform);
  364. var points = new Array();
  365. points.push(0, hasRot ? this._coneLength : 0, 0);
  366. points.push(0, this._arrowLength - this._coneLength, 0);
  367. var wireMesh = new LinesMesh(name + "Wire", this._scene);
  368. wireMesh.rotationQuaternion = rotation;
  369. wireMesh.parent = this._rootMesh;
  370. wireMesh.color = mtl.diffuseColor;
  371. wireMesh.renderingGroupId = 1;
  372. wireMesh.intersectionThreshold = this.wireSelectionThreshold;
  373. wireMesh.isPickable = false;
  374. var vd = new VertexData();
  375. vd.positions = points;
  376. vd.indices = [0, 1];
  377. vd.applyToMesh(wireMesh);
  378. var arrow = Mesh.CreateCylinder(name + "Cone", this._coneLength, 0, this._coneRadius, 18, 1, this._scene, false);
  379. arrow.position = Vector3.TransformCoordinates(new Vector3(0, this._arrowLength - (this._coneLength / 2), 0), transform);
  380. arrow.rotationQuaternion = rotation;
  381. arrow.material = mtl;
  382. arrow.parent = this._rootMesh;
  383. arrow.renderingGroupId = 1;
  384. arrow.isPickable = false;
  385. this.addSymbolicMeshToLit(arrow);
  386. };
  387. Radix.prototype.constructPlaneSelection = function (feature, name, transform) {
  388. var mtl = this.getMaterial(name);
  389. var points = new Array();
  390. points.push(new Vector3(this._arrowLength - this._planeSelectionLength, this._arrowLength, 0));
  391. points.push(new Vector3(this._arrowLength, this._arrowLength, 0));
  392. points.push(new Vector3(this._arrowLength, this._arrowLength - this._planeSelectionLength, 0));
  393. var wireMesh = Mesh.CreateLines(name + "Plane", points, this._scene);
  394. wireMesh.parent = this._rootMesh;
  395. wireMesh.color = mtl.diffuseColor;
  396. wireMesh.rotationQuaternion = Quaternion.FromRotationMatrix(transform);
  397. wireMesh.renderingGroupId = 1;
  398. wireMesh.intersectionThreshold = this.wireSelectionThreshold;
  399. wireMesh.isPickable = false;
  400. };
  401. Radix.prototype.constructRotation = function (feature, name, transform) {
  402. var mtl = this.getMaterial(name);
  403. var rotCyl = Mesh.CreateCylinder(name + "Cylinder", this._coneLength, this._coneRadius, this._coneRadius, 18, 1, this._scene, false);
  404. rotCyl.material = mtl;
  405. rotCyl.position = Vector3.TransformCoordinates(new Vector3(0, this._coneLength / 2, 0), transform);
  406. rotCyl.rotationQuaternion = Quaternion.FromRotationMatrix(transform);
  407. rotCyl.parent = this._rootMesh;
  408. rotCyl.renderingGroupId = 1;
  409. rotCyl.isPickable = false;
  410. this.addSymbolicMeshToLit(rotCyl);
  411. };
  412. Radix.prototype.addSymbolicMeshToLit = function (mesh) {
  413. var _this = this;
  414. this._light1.includedOnlyMeshes.push(mesh);
  415. this._light2.includedOnlyMeshes.push(mesh);
  416. this._scene.lights.map(function (l) { if ((l !== _this._light1) && (l !== _this._light2))
  417. l.excludedMeshes.push(mesh); });
  418. };
  419. Radix.prototype.hasFeature = function (value) {
  420. return (this._features & value) !== 0;
  421. };
  422. Radix.prototype.hasHighlightedFeature = function (value) {
  423. return (this._highlighted & value) !== 0;
  424. };
  425. Radix.prototype.updateMaterial = function (name, color) {
  426. var mtl = this.getMaterial(name);
  427. if (mtl) {
  428. mtl.diffuseColor = color;
  429. }
  430. };
  431. Radix.prototype.updateMaterialFromHighlighted = function (feature, highlighted, name) {
  432. if (!this.hasFeature(feature)) {
  433. return;
  434. }
  435. if ((this._highlighted & feature) !== (highlighted & feature)) {
  436. var mtl = this.getMaterial(name);
  437. if ((highlighted & feature) !== 0) {
  438. mtl.diffuseColor.r *= 1.8;
  439. mtl.diffuseColor.g *= 1.8;
  440. mtl.diffuseColor.b *= 1.8;
  441. }
  442. else {
  443. mtl.diffuseColor.r /= 1.8;
  444. mtl.diffuseColor.g /= 1.8;
  445. mtl.diffuseColor.b /= 1.8;
  446. }
  447. }
  448. };
  449. Radix.prototype.getMaterial = function (name) {
  450. var mtl = this._materials[name];
  451. return mtl;
  452. };
  453. Radix.pc = 0.6;
  454. Radix.sc = 0.2;
  455. return Radix;
  456. }());
  457. Sandbox.Radix = Radix;
  458. })(Sandbox || (Sandbox = {}));
  459. //# sourceMappingURL=Radix.js.map