|
@@ -9,11 +9,14 @@ import { BoundingSphere } from "./boundingSphere";
|
|
|
import { Scene } from "../scene";
|
|
|
import { Camera } from "../Cameras/camera";
|
|
|
import { Plane } from "../Maths/math.plane";
|
|
|
+
|
|
|
+declare type Mesh = import("../Meshes/mesh").Mesh;
|
|
|
+
|
|
|
/**
|
|
|
* Class representing a ray with position and direction
|
|
|
*/
|
|
|
export class Ray {
|
|
|
- private static readonly TmpVector3 = ArrayTools.BuildArray(6, Vector3.Zero);
|
|
|
+ private static readonly _TmpVector3 = ArrayTools.BuildArray(6, Vector3.Zero);
|
|
|
private _tmpRay: Ray;
|
|
|
|
|
|
/**
|
|
@@ -41,8 +44,8 @@ export class Ray {
|
|
|
* @returns if the box was hit
|
|
|
*/
|
|
|
public intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold: number = 0): boolean {
|
|
|
- const newMinimum = Ray.TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
|
|
|
- const newMaximum = Ray.TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
|
|
|
+ const newMinimum = Ray._TmpVector3[0].copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
|
|
|
+ const newMaximum = Ray._TmpVector3[1].copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
|
|
|
var d = 0.0;
|
|
|
var maxValue = Number.MAX_VALUE;
|
|
|
var inv: number;
|
|
@@ -178,11 +181,11 @@ export class Ray {
|
|
|
* @returns intersection information if hit
|
|
|
*/
|
|
|
public intersectsTriangle(vertex0: DeepImmutable<Vector3>, vertex1: DeepImmutable<Vector3>, vertex2: DeepImmutable<Vector3>): Nullable<IntersectionInfo> {
|
|
|
- const edge1 = Ray.TmpVector3[0];
|
|
|
- const edge2 = Ray.TmpVector3[1];
|
|
|
- const pvec = Ray.TmpVector3[2];
|
|
|
- const tvec = Ray.TmpVector3[3];
|
|
|
- const qvec = Ray.TmpVector3[4];
|
|
|
+ const edge1 = Ray._TmpVector3[0];
|
|
|
+ const edge2 = Ray._TmpVector3[1];
|
|
|
+ const pvec = Ray._TmpVector3[2];
|
|
|
+ const tvec = Ray._TmpVector3[3];
|
|
|
+ const qvec = Ray._TmpVector3[4];
|
|
|
|
|
|
vertex1.subtractToRef(vertex0, edge1);
|
|
|
vertex2.subtractToRef(vertex0, edge2);
|
|
@@ -586,6 +589,9 @@ declare module "../scene" {
|
|
|
|
|
|
/** @hidden */
|
|
|
_internalMultiPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, trianglePredicate?: TrianglePickingPredicate): Nullable<PickingInfo[]>;
|
|
|
+
|
|
|
+ /** @hidden */
|
|
|
+ _internalPickForMesh(pickingInfo: Nullable<PickingInfo>, rayFunction: (world: Matrix) => Ray, mesh: AbstractMesh, world: Matrix, fastCheck?: boolean, onlyBoundingInfo?: boolean, trianglePredicate?: TrianglePickingPredicate): Nullable<PickingInfo>;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -653,15 +659,30 @@ Scene.prototype.createPickingRayInCameraSpaceToRef = function (x: number, y: num
|
|
|
return this;
|
|
|
};
|
|
|
|
|
|
+Scene.prototype._internalPickForMesh = function (pickingInfo: Nullable<PickingInfo>, rayFunction: (world: Matrix) => Ray, mesh: AbstractMesh, world: Matrix, fastCheck?: boolean, onlyBoundingInfo?: boolean, trianglePredicate?: TrianglePickingPredicate) {
|
|
|
+ let ray = rayFunction(world);
|
|
|
+
|
|
|
+ let result = mesh.intersects(ray, fastCheck, trianglePredicate, onlyBoundingInfo, world);
|
|
|
+ if (!result || !result.hit) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+};
|
|
|
+
|
|
|
Scene.prototype._internalPick = function (rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, onlyBoundingInfo?: boolean, trianglePredicate?: TrianglePickingPredicate): Nullable<PickingInfo> {
|
|
|
if (!PickingInfo) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- var pickingInfo = null;
|
|
|
+ let pickingInfo = null;
|
|
|
|
|
|
- for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
|
|
|
- var mesh = this.meshes[meshIndex];
|
|
|
+ for (let meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
|
|
|
+ let mesh = this.meshes[meshIndex];
|
|
|
|
|
|
if (predicate) {
|
|
|
if (!predicate(mesh)) {
|
|
@@ -671,22 +692,33 @@ Scene.prototype._internalPick = function (rayFunction: (world: Matrix) => Ray, p
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- var world = mesh.skeleton && mesh.skeleton.overrideMesh ? mesh.skeleton.overrideMesh.getWorldMatrix() : mesh.getWorldMatrix();
|
|
|
- var ray = rayFunction(world);
|
|
|
+ if (mesh.hasThinInstances && (mesh as Mesh).thinInstanceEnablePicking) {
|
|
|
+ let thinMatrices = (mesh as Mesh).thinInstanceGetWorldMatrices();
|
|
|
+ for (let index = 0; index < thinMatrices.length; index++) {
|
|
|
+ let world = thinMatrices[index];
|
|
|
+ let result = this._internalPickForMesh(pickingInfo, rayFunction, mesh, world, fastCheck, onlyBoundingInfo, trianglePredicate);
|
|
|
|
|
|
- var result = mesh.intersects(ray, fastCheck, trianglePredicate, onlyBoundingInfo);
|
|
|
- if (!result || !result.hit) {
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (result) {
|
|
|
+ pickingInfo = result;
|
|
|
+ pickingInfo.thinInstanceIndex = index;
|
|
|
|
|
|
- if (!fastCheck && pickingInfo != null && result.distance >= pickingInfo.distance) {
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (fastCheck) {
|
|
|
+ return pickingInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let world = mesh.skeleton && mesh.skeleton.overrideMesh ? mesh.skeleton.overrideMesh.getWorldMatrix() : mesh.getWorldMatrix();
|
|
|
+
|
|
|
+ let result = this._internalPickForMesh(pickingInfo, rayFunction, mesh, world, fastCheck, onlyBoundingInfo, trianglePredicate);
|
|
|
|
|
|
- pickingInfo = result;
|
|
|
+ if (result) {
|
|
|
+ pickingInfo = result;
|
|
|
|
|
|
- if (fastCheck) {
|
|
|
- break;
|
|
|
+ if (fastCheck) {
|
|
|
+ return pickingInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -697,10 +729,10 @@ Scene.prototype._internalMultiPick = function (rayFunction: (world: Matrix) => R
|
|
|
if (!PickingInfo) {
|
|
|
return null;
|
|
|
}
|
|
|
- var pickingInfos = new Array<PickingInfo>();
|
|
|
+ let pickingInfos = new Array<PickingInfo>();
|
|
|
|
|
|
- for (var meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
|
|
|
- var mesh = this.meshes[meshIndex];
|
|
|
+ for (let meshIndex = 0; meshIndex < this.meshes.length; meshIndex++) {
|
|
|
+ let mesh = this.meshes[meshIndex];
|
|
|
|
|
|
if (predicate) {
|
|
|
if (!predicate(mesh)) {
|
|
@@ -710,15 +742,26 @@ Scene.prototype._internalMultiPick = function (rayFunction: (world: Matrix) => R
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- var world = mesh.getWorldMatrix();
|
|
|
- var ray = rayFunction(world);
|
|
|
+ if (mesh.hasThinInstances && (mesh as Mesh).thinInstanceEnablePicking) {
|
|
|
+ let thinMatrices = (mesh as Mesh).thinInstanceGetWorldMatrices();
|
|
|
+ for (let index = 0; index < thinMatrices.length; index++) {
|
|
|
+ let world = thinMatrices[index];
|
|
|
+ let result = this._internalPickForMesh(null, rayFunction, mesh, world, false, false, trianglePredicate);
|
|
|
|
|
|
- var result = mesh.intersects(ray, false, trianglePredicate);
|
|
|
- if (!result || !result.hit) {
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (result) {
|
|
|
+ result.thinInstanceIndex = index;
|
|
|
+ pickingInfos.push(result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let world = mesh.skeleton && mesh.skeleton.overrideMesh ? mesh.skeleton.overrideMesh.getWorldMatrix() : mesh.getWorldMatrix();
|
|
|
+
|
|
|
+ let result = this._internalPickForMesh(null, rayFunction, mesh, world, false, false, trianglePredicate);
|
|
|
|
|
|
- pickingInfos.push(result);
|
|
|
+ if (result) {
|
|
|
+ pickingInfos.push(result);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return pickingInfos;
|