|
@@ -3,11 +3,13 @@ module BABYLON {
|
|
|
* Class representing a ray with position and direction
|
|
|
*/
|
|
|
export class Ray {
|
|
|
- private _edge1: Vector3;
|
|
|
- private _edge2: Vector3;
|
|
|
- private _pvec: Vector3;
|
|
|
- private _tvec: Vector3;
|
|
|
- private _qvec: Vector3;
|
|
|
+ private static readonly _edge1 = Vector3.Zero();
|
|
|
+ private static readonly _edge2 = Vector3.Zero();
|
|
|
+ private static readonly _pvec = Vector3.Zero();
|
|
|
+ private static readonly _tvec = Vector3.Zero();
|
|
|
+ private static readonly _qvec = Vector3.Zero();
|
|
|
+ private static readonly _min = Vector3.Zero();
|
|
|
+ private static readonly _max = Vector3.Zero();
|
|
|
|
|
|
private _tmpRay: Ray;
|
|
|
|
|
@@ -31,9 +33,12 @@ module BABYLON {
|
|
|
* Checks if the ray intersects a box
|
|
|
* @param minimum bound of the box
|
|
|
* @param maximum bound of the box
|
|
|
+ * @param intersectionTreshold extra extend to be added to the box in all direction
|
|
|
* @returns if the box was hit
|
|
|
*/
|
|
|
- public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean {
|
|
|
+ public intersectsBoxMinMax(minimum: Vector3, maximum: Vector3, intersectionTreshold: number = 0): boolean {
|
|
|
+ const newMinimum = Ray._min.copyFromFloats(minimum.x - intersectionTreshold, minimum.y - intersectionTreshold, minimum.z - intersectionTreshold);
|
|
|
+ const newMaximum = Ray._max.copyFromFloats(maximum.x + intersectionTreshold, maximum.y + intersectionTreshold, maximum.z + intersectionTreshold);
|
|
|
var d = 0.0;
|
|
|
var maxValue = Number.MAX_VALUE;
|
|
|
var inv: number;
|
|
@@ -41,14 +46,14 @@ module BABYLON {
|
|
|
var max: number;
|
|
|
var temp: number;
|
|
|
if (Math.abs(this.direction.x) < 0.0000001) {
|
|
|
- if (this.origin.x < minimum.x || this.origin.x > maximum.x) {
|
|
|
+ if (this.origin.x < newMinimum.x || this.origin.x > newMaximum.x) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
inv = 1.0 / this.direction.x;
|
|
|
- min = (minimum.x - this.origin.x) * inv;
|
|
|
- max = (maximum.x - this.origin.x) * inv;
|
|
|
+ min = (newMinimum.x - this.origin.x) * inv;
|
|
|
+ max = (newMaximum.x - this.origin.x) * inv;
|
|
|
if (max === -Infinity) {
|
|
|
max = Infinity;
|
|
|
}
|
|
@@ -68,14 +73,14 @@ module BABYLON {
|
|
|
}
|
|
|
|
|
|
if (Math.abs(this.direction.y) < 0.0000001) {
|
|
|
- if (this.origin.y < minimum.y || this.origin.y > maximum.y) {
|
|
|
+ if (this.origin.y < newMinimum.y || this.origin.y > newMaximum.y) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
inv = 1.0 / this.direction.y;
|
|
|
- min = (minimum.y - this.origin.y) * inv;
|
|
|
- max = (maximum.y - this.origin.y) * inv;
|
|
|
+ min = (newMinimum.y - this.origin.y) * inv;
|
|
|
+ max = (newMaximum.y - this.origin.y) * inv;
|
|
|
|
|
|
if (max === -Infinity) {
|
|
|
max = Infinity;
|
|
@@ -96,14 +101,14 @@ module BABYLON {
|
|
|
}
|
|
|
|
|
|
if (Math.abs(this.direction.z) < 0.0000001) {
|
|
|
- if (this.origin.z < minimum.z || this.origin.z > maximum.z) {
|
|
|
+ if (this.origin.z < newMinimum.z || this.origin.z > newMaximum.z) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
inv = 1.0 / this.direction.z;
|
|
|
- min = (minimum.z - this.origin.z) * inv;
|
|
|
- max = (maximum.z - this.origin.z) * inv;
|
|
|
+ min = (newMinimum.z - this.origin.z) * inv;
|
|
|
+ max = (newMaximum.z - this.origin.z) * inv;
|
|
|
|
|
|
if (max === -Infinity) {
|
|
|
max = Infinity;
|
|
@@ -128,23 +133,26 @@ module BABYLON {
|
|
|
/**
|
|
|
* Checks if the ray intersects a box
|
|
|
* @param box the bounding box to check
|
|
|
+ * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
|
|
|
* @returns if the box was hit
|
|
|
*/
|
|
|
- public intersectsBox(box: BoundingBox): boolean {
|
|
|
- return this.intersectsBoxMinMax(box.minimum, box.maximum);
|
|
|
+ public intersectsBox(box: BoundingBox, intersectionTreshold: number = 0): boolean {
|
|
|
+ return this.intersectsBoxMinMax(box.minimum, box.maximum, intersectionTreshold);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* If the ray hits a sphere
|
|
|
* @param sphere the bounding sphere to check
|
|
|
+ * @param intersectionTreshold extra extend to be added to the BoundingSphere in all direction
|
|
|
* @returns true if it hits the sphere
|
|
|
*/
|
|
|
- public intersectsSphere(sphere: BoundingSphere): boolean {
|
|
|
+ public intersectsSphere(sphere: BoundingSphere, intersectionTreshold: number = 0): boolean {
|
|
|
var x = sphere.center.x - this.origin.x;
|
|
|
var y = sphere.center.y - this.origin.y;
|
|
|
var z = sphere.center.z - this.origin.z;
|
|
|
var pyth = (x * x) + (y * y) + (z * z);
|
|
|
- var rr = sphere.radius * sphere.radius;
|
|
|
+ const radius = sphere.radius + intersectionTreshold;
|
|
|
+ var rr = radius * radius;
|
|
|
|
|
|
if (pyth <= rr) {
|
|
|
return true;
|
|
@@ -168,18 +176,10 @@ module BABYLON {
|
|
|
* @returns intersection information if hit
|
|
|
*/
|
|
|
public intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): Nullable<IntersectionInfo> {
|
|
|
- if (!this._edge1) {
|
|
|
- this._edge1 = Vector3.Zero();
|
|
|
- this._edge2 = Vector3.Zero();
|
|
|
- this._pvec = Vector3.Zero();
|
|
|
- this._tvec = Vector3.Zero();
|
|
|
- this._qvec = Vector3.Zero();
|
|
|
- }
|
|
|
-
|
|
|
- vertex1.subtractToRef(vertex0, this._edge1);
|
|
|
- vertex2.subtractToRef(vertex0, this._edge2);
|
|
|
- Vector3.CrossToRef(this.direction, this._edge2, this._pvec);
|
|
|
- var det = Vector3.Dot(this._edge1, this._pvec);
|
|
|
+ vertex1.subtractToRef(vertex0, Ray._edge1);
|
|
|
+ vertex2.subtractToRef(vertex0, Ray._edge2);
|
|
|
+ Vector3.CrossToRef(this.direction, Ray._edge2, Ray._pvec);
|
|
|
+ var det = Vector3.Dot(Ray._edge1, Ray._pvec);
|
|
|
|
|
|
if (det === 0) {
|
|
|
return null;
|
|
@@ -187,24 +187,24 @@ module BABYLON {
|
|
|
|
|
|
var invdet = 1 / det;
|
|
|
|
|
|
- this.origin.subtractToRef(vertex0, this._tvec);
|
|
|
+ this.origin.subtractToRef(vertex0, Ray._tvec);
|
|
|
|
|
|
- var bu = Vector3.Dot(this._tvec, this._pvec) * invdet;
|
|
|
+ var bu = Vector3.Dot(Ray._tvec, Ray._pvec) * invdet;
|
|
|
|
|
|
if (bu < 0 || bu > 1.0) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- Vector3.CrossToRef(this._tvec, this._edge1, this._qvec);
|
|
|
+ Vector3.CrossToRef(Ray._tvec, Ray._edge1, Ray._qvec);
|
|
|
|
|
|
- var bv = Vector3.Dot(this.direction, this._qvec) * invdet;
|
|
|
+ var bv = Vector3.Dot(this.direction, Ray._qvec) * invdet;
|
|
|
|
|
|
if (bv < 0 || bu + bv > 1.0) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
//check if the distance is longer than the predefined length.
|
|
|
- var distance = Vector3.Dot(this._edge2, this._qvec) * invdet;
|
|
|
+ var distance = Vector3.Dot(Ray._edge2, Ray._qvec) * invdet;
|
|
|
if (distance > this.length) {
|
|
|
return null;
|
|
|
}
|
|
@@ -353,7 +353,7 @@ module BABYLON {
|
|
|
if (-d < 0.0) {
|
|
|
sN = 0.0;
|
|
|
} else if (-d > a) {
|
|
|
- sN = sD;
|
|
|
+ sN = sD;
|
|
|
}
|
|
|
else {
|
|
|
sN = -d;
|
|
@@ -441,7 +441,7 @@ module BABYLON {
|
|
|
* @param world a matrix to transform the ray to. Default is the identity matrix.
|
|
|
* @returns the new ray
|
|
|
*/
|
|
|
- public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Matrix = Matrix.Identity()): Ray {
|
|
|
+ public static CreateNewFromTo(origin: Vector3, end: Vector3, world: Matrix = Matrix.IdentityReadOnly): Ray {
|
|
|
var direction = end.subtract(origin);
|
|
|
var length = Math.sqrt((direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z));
|
|
|
direction.normalize();
|