pickingInfo.ts 5.8 KB

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