pickingInfo.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { Nullable, FloatArray } from "types";
  2. import { Vector3, Vector2, Tmp } from "Math/math";
  3. import { AbstractMesh } from "Mesh/abstractMesh";
  4. import { VertexBuffer } from "Mesh/vertexBuffer";
  5. import { Ray } from "Culling/ray";
  6. import { Sprite } from "Sprites/sprite";
  7. /**
  8. * @hidden
  9. */
  10. export class IntersectionInfo {
  11. public faceId = 0;
  12. public subMeshId = 0;
  13. constructor(
  14. public bu: Nullable<number>,
  15. public bv: Nullable<number>,
  16. public distance: number) {
  17. }
  18. }
  19. /**
  20. * Information about the result of picking within a scene
  21. * @see https://doc.babylonjs.com/babylon101/picking_collisions
  22. */
  23. export class PickingInfo {
  24. /**
  25. * If the pick collided with an object
  26. */
  27. public hit = false;
  28. /**
  29. * Distance away where the pick collided
  30. */
  31. public distance = 0;
  32. /**
  33. * The location of pick collision
  34. */
  35. public pickedPoint: Nullable<Vector3> = null;
  36. /**
  37. * The mesh corresponding the the pick collision
  38. */
  39. public pickedMesh: Nullable<AbstractMesh> = null;
  40. /** (See getTextureCoordinates) The barycentric U coordinate that is used when calulating the texture coordinates of the collision.*/
  41. public bu = 0;
  42. /** (See getTextureCoordinates) The barycentric V coordinate that is used when calulating the texture coordinates of the collision.*/
  43. public bv = 0;
  44. /** The id of the face on the mesh that was picked */
  45. public faceId = -1;
  46. /** Id of the the submesh that was picked */
  47. public subMeshId = 0;
  48. /** If a sprite was picked, this will be the sprite the pick collided with */
  49. public pickedSprite: Nullable<Sprite> = null;
  50. /**
  51. * If a mesh was used to do the picking (eg. 6dof controller) this will be populated.
  52. */
  53. public originMesh: Nullable<AbstractMesh> = null;
  54. /**
  55. * The ray that was used to perform the picking.
  56. */
  57. public ray: Nullable<Ray> = null;
  58. /**
  59. * Gets the normal correspodning to the face the pick collided with
  60. * @param useWorldCoordinates If the resulting normal should be relative to the world (default: false)
  61. * @param useVerticesNormals If the vertices normals should be used to calculate the normal instead of the normal map
  62. * @returns The normal correspodning to the face the pick collided with
  63. */
  64. public getNormal(useWorldCoordinates = false, useVerticesNormals = true): Nullable<Vector3> {
  65. if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
  66. return null;
  67. }
  68. var indices = this.pickedMesh.getIndices();
  69. if (!indices) {
  70. return null;
  71. }
  72. var result: Vector3;
  73. if (useVerticesNormals) {
  74. var normals = (<FloatArray>this.pickedMesh.getVerticesData(VertexBuffer.NormalKind));
  75. var normal0 = Vector3.FromArray(normals, indices[this.faceId * 3] * 3);
  76. var normal1 = Vector3.FromArray(normals, indices[this.faceId * 3 + 1] * 3);
  77. var normal2 = Vector3.FromArray(normals, indices[this.faceId * 3 + 2] * 3);
  78. normal0 = normal0.scale(this.bu);
  79. normal1 = normal1.scale(this.bv);
  80. normal2 = normal2.scale(1.0 - this.bu - this.bv);
  81. result = new Vector3(normal0.x + normal1.x + normal2.x, normal0.y + normal1.y + normal2.y, normal0.z + normal1.z + normal2.z);
  82. } else {
  83. var positions = (<FloatArray>this.pickedMesh.getVerticesData(VertexBuffer.PositionKind));
  84. var vertex1 = Vector3.FromArray(positions, indices[this.faceId * 3] * 3);
  85. var vertex2 = Vector3.FromArray(positions, indices[this.faceId * 3 + 1] * 3);
  86. var vertex3 = Vector3.FromArray(positions, indices[this.faceId * 3 + 2] * 3);
  87. var p1p2 = vertex1.subtract(vertex2);
  88. var p3p2 = vertex3.subtract(vertex2);
  89. result = Vector3.Cross(p1p2, p3p2);
  90. }
  91. if (useWorldCoordinates) {
  92. let wm = this.pickedMesh.getWorldMatrix();
  93. if (this.pickedMesh.nonUniformScaling) {
  94. Tmp.Matrix[0].copyFrom(wm);
  95. wm = Tmp.Matrix[0];
  96. wm.setTranslationFromFloats(0, 0, 0);
  97. wm.invert();
  98. wm.transposeToRef(Tmp.Matrix[1]);
  99. wm = Tmp.Matrix[1];
  100. }
  101. result = Vector3.TransformNormal(result, wm);
  102. }
  103. result.normalize();
  104. return result;
  105. }
  106. /**
  107. * Gets the texture coordinates of where the pick occured
  108. * @returns the vector containing the coordnates of the texture
  109. */
  110. public getTextureCoordinates(): Nullable<Vector2> {
  111. if (!this.pickedMesh || !this.pickedMesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
  112. return null;
  113. }
  114. var indices = this.pickedMesh.getIndices();
  115. if (!indices) {
  116. return null;
  117. }
  118. var uvs = this.pickedMesh.getVerticesData(VertexBuffer.UVKind);
  119. if (!uvs) {
  120. return null;
  121. }
  122. var uv0 = Vector2.FromArray(uvs, indices[this.faceId * 3] * 2);
  123. var uv1 = Vector2.FromArray(uvs, indices[this.faceId * 3 + 1] * 2);
  124. var uv2 = Vector2.FromArray(uvs, indices[this.faceId * 3 + 2] * 2);
  125. uv0 = uv0.scale(1.0 - this.bu - this.bv);
  126. uv1 = uv1.scale(this.bu);
  127. uv2 = uv2.scale(this.bv);
  128. return new Vector2(uv0.x + uv1.x + uv2.x, uv0.y + uv1.y + uv2.y);
  129. }
  130. }