UNPKG

4.96 kBJavaScriptView Raw
1import { vec3 } from 'gl-matrix';
2var tmpVecA = vec3.create();
3var tmpVecB = vec3.create();
4var tmpVecC = vec3.create();
5var tmpVecD = vec3.create();
6var tmpVecE = vec3.create();
7/**
8 * 包含求交方法:
9 * * intersectsShape(Shape, intersection) 返回交点和求交结果
10 * @see https://github.com/playcanvas/engine/blob/master/src/shape/bounding-box.js#L161
11 * @see https://github.com/mrdoob/three.js/blob/dev/src/math/Ray.js
12 */
13
14var Ray =
15/** @class */
16function () {
17 function Ray(origin, direction) {
18 this.origin = origin || vec3.create();
19 this.direction = direction || vec3.fromValues(0, 0, -1);
20 }
21
22 Ray.prototype.intersectsAABB = function (aabb, intersection) {
23 return intersection ? this.intersectAABBWithIntersection(aabb, intersection) : this.intersectsAABBWithoutIntersection(aabb);
24 };
25
26 Ray.prototype.intersectsSphere = function (sphere, intersection) {
27 var m = vec3.sub(tmpVecA, this.origin, sphere.center);
28 vec3.normalize(tmpVecB, vec3.copy(tmpVecB, this.direction));
29 var b = vec3.dot(m, tmpVecB);
30 var c = vec3.dot(m, m) - sphere.radius * sphere.radius; // exit if ray's origin outside of sphere (c > 0) and ray pointing away from s (b > 0)
31
32 if (c > 0 && b > 0) {
33 return null;
34 }
35
36 var discr = b * b - c; // a negative discriminant corresponds to ray missing sphere
37
38 if (discr < 0) {
39 return false;
40 } // ray intersects sphere, compute smallest t value of intersection
41
42
43 var t = Math.abs(-b - Math.sqrt(discr)); // if t is negative, ray started inside sphere so clamp t to zero
44
45 if (intersection) {
46 vec3.copy(intersection, this.direction);
47 vec3.scaleAndAdd(intersection, this.origin, intersection, t);
48 }
49
50 return true;
51 };
52
53 Ray.prototype.intersectsPlane = function (plane, intersection) {
54 var t = (plane.distance - vec3.dot(plane.normal, this.origin)) / vec3.dot(plane.normal, this.direction);
55 var intersects = t >= 0;
56
57 if (intersects && intersection) {
58 vec3.scaleAndAdd(intersection, this.origin, this.direction, t);
59 }
60
61 return intersects;
62 };
63 /**
64 * faster than implements like Three.js
65 * @see https://github.com/playcanvas/engine/blob/master/src/shape/bounding-box.js#L161
66 */
67
68
69 Ray.prototype.intersectsAABBWithoutIntersection = function (aabb) {
70 var diff = tmpVecA;
71 var cross = tmpVecB;
72 var prod = tmpVecC;
73 var absDiff = tmpVecD;
74 var absDir = tmpVecE;
75 var rayDir = this.direction;
76 vec3.sub(diff, this.origin, aabb.center);
77 vec3.set(absDiff, Math.abs(diff[0]), Math.abs(diff[1]), Math.abs(diff[2]));
78 vec3.mul(prod, diff, rayDir);
79
80 if (absDiff[0] > aabb.halfExtents[0] && prod[0] >= 0 || absDiff[1] > aabb.halfExtents[1] && prod[1] >= 0 || absDiff[2] > aabb.halfExtents[2] && prod[2] >= 0) {
81 return false;
82 }
83
84 vec3.set(absDir, Math.abs(rayDir[0]), Math.abs(rayDir[1]), Math.abs(rayDir[2]));
85 vec3.cross(cross, rayDir, diff);
86 vec3.set(cross, Math.abs(cross[0]), Math.abs(cross[1]), Math.abs(cross[2]));
87 return !(cross[0] > aabb.halfExtents[1] * absDir[2] + aabb.halfExtents[2] * absDir[1] || cross[1] > aabb.halfExtents[0] * absDir[2] + aabb.halfExtents[2] * absDir[0] || cross[2] > aabb.halfExtents[0] * absDir[1] + aabb.halfExtents[1] * absDir[0]);
88 };
89
90 Ray.prototype.intersectAABBWithIntersection = function (aabb, intersection) {
91 var tMin = vec3.copy(vec3.create(), aabb.getMin());
92 vec3.sub(tMin, tMin, this.origin);
93 var tMax = vec3.copy(vec3.create(), aabb.getMax());
94 vec3.sub(tMax, tMax, this.origin);
95 var dir = this.direction; // Ensure that we are not dividing it by zero
96
97 if (dir[0] === 0) {
98 tMin[0] = tMin[0] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
99 tMax[0] = tMax[0] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
100 } else {
101 tMin[0] /= dir[0];
102 tMax[0] /= dir[0];
103 }
104
105 if (dir[1] === 0) {
106 tMin[1] = tMin[1] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
107 tMax[1] = tMax[1] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
108 } else {
109 tMin[1] /= dir[1];
110 tMax[1] /= dir[1];
111 }
112
113 if (dir[2] === 0) {
114 tMin[2] = tMin[2] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
115 tMax[2] = tMax[2] < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;
116 } else {
117 tMin[2] /= dir[2];
118 tMax[2] /= dir[2];
119 }
120
121 var realMin = vec3.set(tmpVecC, Math.min(tMin[0], tMax[0]), Math.min(tMin[1], tMax[1]), Math.min(tMin[2], tMax[2]));
122 var realMax = vec3.set(tmpVecD, Math.max(tMin[0], tMax[0]), Math.max(tMin[1], tMax[1]), Math.max(tMin[2], tMax[2]));
123 var minMax = Math.min(Math.min(realMax[0], realMax[1]), realMax[2]);
124 var maxMin = Math.max(Math.max(realMin[0], realMin[1]), realMin[2]);
125 var intersects = minMax >= maxMin && maxMin >= 0;
126
127 if (intersects) {
128 vec3.copy(intersection, this.direction);
129 vec3.scaleAndAdd(intersection, this.origin, intersection, maxMin);
130 }
131
132 return intersects;
133 };
134
135 return Ray;
136}();
137
138export { Ray };
\No newline at end of file