rayHelper.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import { Nullable } from "../types";
  2. import { Ray } from "../Culling/ray";
  3. import { Vector3, Color3 } from "../Maths/math";
  4. import { Scene } from "../scene";
  5. import { AbstractMesh } from "../Meshes/abstractMesh";
  6. import { Mesh } from "../Meshes/mesh";
  7. import { LinesMesh } from "../Meshes/linesMesh";
  8. import "../Meshes/Builders/linesBuilder";
  9. /**
  10. * As raycast might be hard to debug, the RayHelper can help rendering the different rays
  11. * in order to better appreciate the issue one might have.
  12. * @see http://doc.babylonjs.com/babylon101/raycasts#debugging
  13. */
  14. export class RayHelper {
  15. /**
  16. * Defines the ray we are currently tryin to visualize.
  17. */
  18. public ray: Nullable<Ray>;
  19. private _renderPoints: Vector3[];
  20. private _renderLine: Nullable<LinesMesh>;
  21. private _renderFunction: Nullable<() => void>;
  22. private _scene: Nullable<Scene>;
  23. private _updateToMeshFunction: Nullable<() => void>;
  24. private _attachedToMesh: Nullable<AbstractMesh>;
  25. private _meshSpaceDirection: Vector3;
  26. private _meshSpaceOrigin: Vector3;
  27. /**
  28. * Helper function to create a colored helper in a scene in one line.
  29. * @param ray Defines the ray we are currently tryin to visualize
  30. * @param scene Defines the scene the ray is used in
  31. * @param color Defines the color we want to see the ray in
  32. * @returns The newly created ray helper.
  33. */
  34. public static CreateAndShow(ray: Ray, scene: Scene, color: Color3): RayHelper {
  35. var helper = new RayHelper(ray);
  36. helper.show(scene, color);
  37. return helper;
  38. }
  39. /**
  40. * Instantiate a new ray helper.
  41. * As raycast might be hard to debug, the RayHelper can help rendering the different rays
  42. * in order to better appreciate the issue one might have.
  43. * @see http://doc.babylonjs.com/babylon101/raycasts#debugging
  44. * @param ray Defines the ray we are currently tryin to visualize
  45. */
  46. constructor(ray: Ray) {
  47. this.ray = ray;
  48. }
  49. /**
  50. * Shows the ray we are willing to debug.
  51. * @param scene Defines the scene the ray needs to be rendered in
  52. * @param color Defines the color the ray needs to be rendered in
  53. */
  54. public show(scene: Scene, color?: Color3): void {
  55. if (!this._renderFunction && this.ray) {
  56. var ray = this.ray;
  57. this._renderFunction = this._render.bind(this);
  58. this._scene = scene;
  59. this._renderPoints = [ray.origin, ray.origin.add(ray.direction.scale(ray.length))];
  60. this._renderLine = Mesh.CreateLines("ray", this._renderPoints, scene, true);
  61. if (this._renderFunction) {
  62. this._scene.registerBeforeRender(this._renderFunction);
  63. }
  64. }
  65. if (color && this._renderLine) {
  66. this._renderLine.color.copyFrom(color);
  67. }
  68. }
  69. /**
  70. * Hides the ray we are debugging.
  71. */
  72. public hide(): void {
  73. if (this._renderFunction && this._scene) {
  74. this._scene.unregisterBeforeRender(this._renderFunction);
  75. this._scene = null;
  76. this._renderFunction = null;
  77. if (this._renderLine) {
  78. this._renderLine.dispose();
  79. this._renderLine = null;
  80. }
  81. this._renderPoints = [];
  82. }
  83. }
  84. private _render(): void {
  85. var ray = this.ray;
  86. if (!ray) {
  87. return;
  88. }
  89. var point = this._renderPoints[1];
  90. var len = Math.min(ray.length, 1000000);
  91. point.copyFrom(ray.direction);
  92. point.scaleInPlace(len);
  93. point.addInPlace(ray.origin);
  94. Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
  95. }
  96. /**
  97. * Attach a ray helper to a mesh so that we can easily see its orientation for instance or information like its normals.
  98. * @param mesh Defines the mesh we want the helper attached to
  99. * @param meshSpaceDirection Defines the direction of the Ray in mesh space (local space of the mesh node)
  100. * @param meshSpaceOrigin Defines the origin of the Ray in mesh space (local space of the mesh node)
  101. * @param length Defines the length of the ray
  102. */
  103. public attachToMesh(mesh: AbstractMesh, meshSpaceDirection?: Vector3, meshSpaceOrigin?: Vector3, length?: number): void {
  104. this._attachedToMesh = mesh;
  105. var ray = this.ray;
  106. if (!ray) {
  107. return;
  108. }
  109. if (!ray.direction) {
  110. ray.direction = Vector3.Zero();
  111. }
  112. if (!ray.origin) {
  113. ray.origin = Vector3.Zero();
  114. }
  115. if (length) {
  116. ray.length = length;
  117. }
  118. if (!meshSpaceOrigin) {
  119. meshSpaceOrigin = Vector3.Zero();
  120. }
  121. if (!meshSpaceDirection) {
  122. // -1 so that this will work with Mesh.lookAt
  123. meshSpaceDirection = new Vector3(0, 0, -1);
  124. }
  125. if (!this._meshSpaceDirection) {
  126. this._meshSpaceDirection = meshSpaceDirection.clone();
  127. this._meshSpaceOrigin = meshSpaceOrigin.clone();
  128. } else {
  129. this._meshSpaceDirection.copyFrom(meshSpaceDirection);
  130. this._meshSpaceOrigin.copyFrom(meshSpaceOrigin);
  131. }
  132. if (!this._updateToMeshFunction) {
  133. this._updateToMeshFunction = (<() => void>this._updateToMesh.bind(this));
  134. this._attachedToMesh.getScene().registerBeforeRender(this._updateToMeshFunction);
  135. }
  136. this._updateToMesh();
  137. }
  138. /**
  139. * Detach the ray helper from the mesh it has previously been attached to.
  140. */
  141. public detachFromMesh(): void {
  142. if (this._attachedToMesh) {
  143. if (this._updateToMeshFunction) {
  144. this._attachedToMesh.getScene().unregisterBeforeRender(this._updateToMeshFunction);
  145. }
  146. this._attachedToMesh = null;
  147. this._updateToMeshFunction = null;
  148. }
  149. }
  150. private _updateToMesh(): void {
  151. var ray = this.ray;
  152. if (!this._attachedToMesh || !ray) {
  153. return;
  154. }
  155. if (this._attachedToMesh._isDisposed) {
  156. this.detachFromMesh();
  157. return;
  158. }
  159. this._attachedToMesh.getDirectionToRef(this._meshSpaceDirection, ray.direction);
  160. Vector3.TransformCoordinatesToRef(this._meshSpaceOrigin, this._attachedToMesh.getWorldMatrix(), ray.origin);
  161. }
  162. /**
  163. * Dispose the helper and release its associated resources.
  164. */
  165. public dispose(): void {
  166. this.hide();
  167. this.detachFromMesh();
  168. this.ray = null;
  169. }
  170. }