rayHelper.ts 6.7 KB

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