Variables
Const LOOK_FORWARD
LOOK_FORWARD: 3 = 3
Const _m3_tmp
_m3_
tmp: Mat3 = new Mat3()
Const _m3_tmp
_m3_
tmp: Mat3 = new Mat3()
Const _offset
_offset
: Vec3 = new Vec3()
Const _v
_v: any[] = new Array(8)
Const _v3_tmp
_v3_
tmp: Vec3 = new Vec3()
Const _v3_tmp
_v3_
tmp: Vec3 = new Vec3()
Const _v3_tmp
_v3_
tmp: Vec3 = new Vec3()
Const _v3_tmp2
_v3_
tmp2: Vec3 = new Vec3()
Const _v3_tmp2
_v3_
tmp2: Vec3 = new Vec3()
Const _v3_tmp3
_v3_
tmp3: Vec3 = new Vec3()
Const _v3_tmp4
_v3_
tmp4: Vec3 = new Vec3()
Const aabb_aabb
aabb_aabb: (Anonymous function) = (function () {const aMin = new Vec3();const aMax = new Vec3();const bMin = new Vec3();const bMax = new Vec3();return function (aabb1: aabb, aabb2: aabb) {Vec3.subtract(aMin, aabb1.center, aabb1.halfExtents);Vec3.add(aMax, aabb1.center, aabb1.halfExtents);Vec3.subtract(bMin, aabb2.center, aabb2.halfExtents);Vec3.add(bMax, aabb2.center, aabb2.halfExtents);return (aMin.x <= bMax.x && aMax.x >= bMin.x) &&(aMin.y <= bMax.y && aMax.y >= bMin.y) &&(aMin.z <= bMax.z && aMax.z >= bMin.z);};})()
Const aabb_frustum_accurate
aabb_frustum_accurate: (Anonymous function) = (function () {const tmp = new Array(8);let out1 = 0, out2 = 0;for (let i = 0; i < tmp.length; i++) {tmp[i] = new Vec3(0, 0, 0);}return function (aabb: aabb, frustum: frustum): number {let result = 0, intersects = false;// 1. aabb inside/outside frustum testfor (let i = 0; i < frustum.planes.length; i++) {result = aabb_plane(aabb, frustum.planes[i]);// frustum plane normal points to the insideif (result === -1) { return 0; } // completely outsideelse if (result === 1) { intersects = true; }}if (!intersects) { return 1; } // completely inside// in case of false positives// 2. frustum inside/outside aabb testfor (let i = 0; i < frustum.vertices.length; i++) {Vec3.subtract(tmp[i], frustum.vertices[i], aabb.center);}out1 = 0, out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {if (tmp[i].x > aabb.halfExtents.x) { out1++; }else if (tmp[i].x < -aabb.halfExtents.x) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }out1 = 0; out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {if (tmp[i].y > aabb.halfExtents.y) { out1++; }else if (tmp[i].y < -aabb.halfExtents.y) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }out1 = 0; out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {if (tmp[i].z > aabb.halfExtents.z) { out1++; }else if (tmp[i].z < -aabb.halfExtents.z) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }return 1;};})()
Const aabb_obb
aabb_obb: (Anonymous function) = (function () {const test = new Array(15);for (let i = 0; i < 15; i++) {test[i] = new Vec3(0, 0, 0);}const vertices = new Array(8);const vertices2 = new Array(8);for (let i = 0; i < 8; i++) {vertices[i] = new Vec3(0, 0, 0);vertices2[i] = new Vec3(0, 0, 0);}const min = new Vec3();const max = new Vec3();return function (aabb: aabb, obb: obb): number {Vec3.set(test[0], 1, 0, 0);Vec3.set(test[1], 0, 1, 0);Vec3.set(test[2], 0, 0, 1);Vec3.set(test[3], obb.orientation.m00, obb.orientation.m01, obb.orientation.m02);Vec3.set(test[4], obb.orientation.m03, obb.orientation.m04, obb.orientation.m05);Vec3.set(test[5], obb.orientation.m06, obb.orientation.m07, obb.orientation.m08);for (let i = 0; i < 3; ++i) { // Fill out rest of axisVec3.cross(test[6 + i * 3 + 0], test[i], test[0]);Vec3.cross(test[6 + i * 3 + 1], test[i], test[1]);Vec3.cross(test[6 + i * 3 + 1], test[i], test[2]);}Vec3.subtract(min, aabb.center, aabb.halfExtents);Vec3.add(max, aabb.center, aabb.halfExtents);getAABBVertices(min, max, vertices);getOBBVertices(obb.center, obb.halfExtents, test[3], test[4], test[5], vertices2);for (let j = 0; j < 15; ++j) {const a = getInterval(vertices, test[j]);const b = getInterval(vertices2, test[j]);if (b[0] > a[1] || a[0] > b[1]) {return 0; // Seperating axis found}}return 1;};})()
Const capsule_capsule
capsule_
capsule: capsule_capsule = (function () {const v3_0 = new Vec3();const v3_1 = new Vec3();const v3_2 = new Vec3();const v3_3 = new Vec3();const v3_4 = new Vec3();const v3_5 = new Vec3();return function capsule_capsule (capsuleA: capsule, capsuleB: capsule) {const u = Vec3.subtract(v3_0, capsuleA.ellipseCenter1, capsuleA.ellipseCenter0);const v = Vec3.subtract(v3_1, capsuleB.ellipseCenter1, capsuleB.ellipseCenter0);const w = Vec3.subtract(v3_2, capsuleA.ellipseCenter0, capsuleB.ellipseCenter0);const a = Vec3.dot(u, u); // always >= 0const b = Vec3.dot(u, v);const c = Vec3.dot(v, v); // always >= 0const d = Vec3.dot(u, w);const e = Vec3.dot(v, w);const D = a * c - b * b; // always >= 0let sc: number;let sN: number;let sD = D; // sc = sN / sD, default sD = D >= 0let tc: number;let tN: number;let tD = D; // tc = tN / tD, default tD = D >= 0// compute the line parameters of the two closest pointsif (D < EPSILON) { // the lines are almost parallelsN = 0.0; // force using point P0 on segment S1sD = 1.0; // to prevent possible division by 0.0 latertN = e;tD = c;}else { // get the closest points on the infinite linessN = (b * e - c * d);tN = (a * e - b * d);if (sN < 0.0) { // sc < 0 => the s=0 edge is visiblesN = 0.0;tN = e;tD = c;}else if (sN > sD) { // sc > 1 => the s=1 edge is visiblesN = sD;tN = e + b;tD = c;}}if (tN < 0.0) { // tc < 0 => the t=0 edge is visibletN = 0.0;// recompute sc for this edgeif (-d < 0.0) {sN = 0.0;}else if (-d > a) {sN = sD;}else {sN = -d;sD = a;}}else if (tN > tD) { // tc > 1 => the t=1 edge is visibletN = tD;// recompute sc for this edgeif ((-d + b) < 0.0) {sN = 0;}else if ((-d + b) > a) {sN = sD;}else {sN = (-d + b);sD = a;}}// finally do the division to get sc and tcsc = (Math.abs(sN) < EPSILON ? 0.0 : sN / sD);tc = (Math.abs(tN) < EPSILON ? 0.0 : tN / tD);// get the difference of the two closest pointsconst dP = v3_3;dP.set(w);dP.add(Vec3.multiplyScalar(v3_4, u, sc));dP.subtract(Vec3.multiplyScalar(v3_5, v, tc));const radius = capsuleA.radius + capsuleB.radius;return dP.lengthSqr() < radius * radius;};})()
Const e
e: any[] = new Array(3)
Const line_plane
line_plane: (Anonymous function) = (function () {const ab = new Vec3(0, 0, 0);return function (line: line, plane: plane): number {Vec3.subtract(ab, line.e, line.s);const t = (plane.d - Vec3.dot(line.s, plane.n)) / Vec3.dot(ab, plane.n);if (t < 0 || t > 1) { return 0; }return t;};})()
Const line_triangle
line_triangle: (Anonymous function) = (function () {const ab = new Vec3(0, 0, 0);const ac = new Vec3(0, 0, 0);const qp = new Vec3(0, 0, 0);const ap = new Vec3(0, 0, 0);const n = new Vec3(0, 0, 0);const e = new Vec3(0, 0, 0);return function (line: line, triangle: triangle, outPt?: Vec3): number {Vec3.subtract(ab, triangle.b, triangle.a);Vec3.subtract(ac, triangle.c, triangle.a);Vec3.subtract(qp, line.s, line.e);Vec3.cross(n, ab, ac);const det = Vec3.dot(qp, n);if (det <= 0.0) {return 0;}Vec3.subtract(ap, line.s, triangle.a);const t = Vec3.dot(ap, n);if (t < 0 || t > det) {return 0;}Vec3.cross(e, qp, ap);let v = Vec3.dot(ac, e);if (v < 0 || v > det) {return 0;}let w = -Vec3.dot(ab, e);if (w < 0.0 || v + w > det) {return 0;}if (outPt) {const invDet = 1.0 / det;v *= invDet;w *= invDet;const u = 1.0 - v - w;// outPt = u*a + v*d + w*c;Vec3.set(outPt,triangle.a.x * u + triangle.b.x * v + triangle.c.x * w,triangle.a.y * u + triangle.b.y * v + triangle.c.y * w,triangle.a.z * u + triangle.b.z * v + triangle.c.z * w,);}return 1;};})()
Const obb_capsule
obb_capsule: (Anonymous function) = (function () {const sphere_0 = new sphere();const v3_0 = new Vec3();const v3_1 = new Vec3();const v3_2 = new Vec3();const v3_verts8 = new Array<Vec3>(8);for (let i = 0; i < 8; i++) { v3_verts8[i] = new Vec3(); }const v3_axis8 = new Array<Vec3>(8);for (let i = 0; i < 8; i++) { v3_axis8[i] = new Vec3(); }return function (obb: obb, capsule: capsule) {const h = Vec3.squaredDistance(capsule.ellipseCenter0, capsule.ellipseCenter1);if (h === 0) {sphere_0.radius = capsule.radius;sphere_0.center.set(capsule.ellipseCenter0);return intersect.sphere_obb(sphere_0, obb);} else {v3_0.x = obb.orientation.m00;v3_0.y = obb.orientation.m01;v3_0.z = obb.orientation.m02;v3_1.x = obb.orientation.m03;v3_1.y = obb.orientation.m04;v3_1.z = obb.orientation.m05;v3_2.x = obb.orientation.m06;v3_2.y = obb.orientation.m07;v3_2.z = obb.orientation.m08;getOBBVertices(obb.center, obb.halfExtents, v3_0, v3_1, v3_2, v3_verts8);const axes = v3_axis8;const a0 = Vec3.copy(axes[0], v3_0);const a1 = Vec3.copy(axes[1], v3_1);const a2 = Vec3.copy(axes[2], v3_2);const C = Vec3.subtract(axes[3], capsule.center, obb.center);C.normalize();const B = Vec3.subtract(axes[4], capsule.ellipseCenter0, capsule.ellipseCenter1);B.normalize();Vec3.cross(axes[5], a0, B);Vec3.cross(axes[6], a1, B);Vec3.cross(axes[7], a2, B);for (let i = 0; i < 8; ++i) {const a = getInterval(v3_verts8, axes[i]);const d0 = Vec3.dot(axes[i], capsule.ellipseCenter0);const d1 = Vec3.dot(axes[i], capsule.ellipseCenter1);const max_d = Math.max(d0, d1);const min_d = Math.min(d0, d1);const d_min = min_d - capsule.radius;const d_max = max_d + capsule.radius;if (d_min > a[1] || a[0] > d_max) {return 0; // Seperating axis found}}return 1;}};})()
Const obb_frustum_accurate
obb_frustum_accurate: (Anonymous function) = (function () {const tmp = new Array(8);let dist = 0, out1 = 0, out2 = 0;for (let i = 0; i < tmp.length; i++) {tmp[i] = new Vec3(0, 0, 0);}const dot = function (n: Vec3, x: number, y: number, z: number): number {return n.x * x + n.y * y + n.z * z;};return function (obb: obb, frustum: frustum): number {let result = 0, intersects = false;// 1. obb inside/outside frustum testfor (let i = 0; i < frustum.planes.length; i++) {result = obb_plane(obb, frustum.planes[i]);// frustum plane normal points to the insideif (result === -1) { return 0; } // completely outsideelse if (result === 1) { intersects = true; }}if (!intersects) { return 1; } // completely inside// in case of false positives// 2. frustum inside/outside obb testfor (let i = 0; i < frustum.vertices.length; i++) {Vec3.subtract(tmp[i], frustum.vertices[i], obb.center);}out1 = 0, out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {dist = dot(tmp[i], obb.orientation.m00, obb.orientation.m01, obb.orientation.m02);if (dist > obb.halfExtents.x) { out1++; }else if (dist < -obb.halfExtents.x) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }out1 = 0; out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {dist = dot(tmp[i], obb.orientation.m03, obb.orientation.m04, obb.orientation.m05);if (dist > obb.halfExtents.y) { out1++; }else if (dist < -obb.halfExtents.y) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }out1 = 0; out2 = 0;for (let i = 0; i < frustum.vertices.length; i++) {dist = dot(tmp[i], obb.orientation.m06, obb.orientation.m07, obb.orientation.m08);if (dist > obb.halfExtents.z) { out1++; }else if (dist < -obb.halfExtents.z) { out2++; }}if (out1 === frustum.vertices.length || out2 === frustum.vertices.length) { return 0; }return 1;};})()
Const obb_obb
obb_obb: (Anonymous function) = (function () {const test = new Array(15);for (let i = 0; i < 15; i++) {test[i] = new Vec3(0, 0, 0);}const vertices = new Array(8);const vertices2 = new Array(8);for (let i = 0; i < 8; i++) {vertices[i] = new Vec3(0, 0, 0);vertices2[i] = new Vec3(0, 0, 0);}return function (obb1: obb, obb2: obb): number {Vec3.set(test[0], obb1.orientation.m00, obb1.orientation.m01, obb1.orientation.m02);Vec3.set(test[1], obb1.orientation.m03, obb1.orientation.m04, obb1.orientation.m05);Vec3.set(test[2], obb1.orientation.m06, obb1.orientation.m07, obb1.orientation.m08);Vec3.set(test[3], obb2.orientation.m00, obb2.orientation.m01, obb2.orientation.m02);Vec3.set(test[4], obb2.orientation.m03, obb2.orientation.m04, obb2.orientation.m05);Vec3.set(test[5], obb2.orientation.m06, obb2.orientation.m07, obb2.orientation.m08);for (let i = 0; i < 3; ++i) { // Fill out rest of axisVec3.cross(test[6 + i * 3 + 0], test[i], test[0]);Vec3.cross(test[6 + i * 3 + 1], test[i], test[1]);Vec3.cross(test[6 + i * 3 + 1], test[i], test[2]);}getOBBVertices(obb1.center, obb1.halfExtents, test[0], test[1], test[2], vertices);getOBBVertices(obb2.center, obb2.halfExtents, test[3], test[4], test[5], vertices2);for (let i = 0; i < 15; ++i) {const a = getInterval(vertices, test[i]);const b = getInterval(vertices2, test[i]);if (b[0] > a[1] || a[0] > b[1]) {return 0; // Seperating axis found}}return 1;};})()
Const obb_plane
obb_plane: (Anonymous function) = (function () {const absDot = function (n: Vec3, x: number, y: number, z: number) {return Math.abs(n.x * x + n.y * y + n.z * z);};return function (obb: obb, plane: plane): number {// Real-Time Collision Detection, Christer Ericson, p. 163.const r = obb.halfExtents.x * absDot(plane.n, obb.orientation.m00, obb.orientation.m01, obb.orientation.m02) +obb.halfExtents.y * absDot(plane.n, obb.orientation.m03, obb.orientation.m04, obb.orientation.m05) +obb.halfExtents.z * absDot(plane.n, obb.orientation.m06, obb.orientation.m07, obb.orientation.m08);const dot = Vec3.dot(plane.n, obb.center);if (dot + r < plane.d) { return -1; }else if (dot - r > plane.d) { return 0; }return 1;};})()
Const obb_point
obb_point: (Anonymous function) = (function () {const tmp = new Vec3(0, 0, 0), m3 = new Mat3();const lessThan = function (a: Vec3, b: Vec3): boolean { return Math.abs(a.x) < b.x && Math.abs(a.y) < b.y && Math.abs(a.z) < b.z; };return function (obb: obb, point: Vec3): boolean {Vec3.subtract(tmp, point, obb.center);Vec3.transformMat3(tmp, tmp, Mat3.transpose(m3, obb.orientation));return lessThan(tmp, obb.halfExtents);};})()
Const ray_aabb
ray_aabb: (Anonymous function) = (function () {const min = new Vec3();const max = new Vec3();return function (ray: ray, aabb: aabb): number {Vec3.subtract(min, aabb.center, aabb.halfExtents);Vec3.add(max, aabb.center, aabb.halfExtents);return ray_aabb2(ray, min, max);};})()
Const ray_capsule
ray_capsule: (Anonymous function) = (function () {const v3_0 = new Vec3();const v3_1 = new Vec3();const v3_2 = new Vec3();const v3_3 = new Vec3();const v3_4 = new Vec3();const v3_5 = new Vec3();const v3_6 = new Vec3();const sphere_0 = new sphere();return function (ray: ray, capsule: capsule) {const radiusSqr = capsule.radius * capsule.radius;const vRayNorm = Vec3.normalize(v3_0, ray.d);const A = capsule.ellipseCenter0;const B = capsule.ellipseCenter1;const BA = Vec3.subtract(v3_1, B, A);if (BA.equals(Vec3.ZERO)) {sphere_0.radius = capsule.radius;sphere_0.center.set(capsule.ellipseCenter0);return intersect.ray_sphere(ray, sphere_0);}const O = ray.o;const OA = Vec3.subtract(v3_2, O, A);const VxBA = Vec3.cross(v3_3, vRayNorm, BA);const a = VxBA.lengthSqr();if (a === 0) {sphere_0.radius = capsule.radius;const BO = Vec3.subtract(v3_4, B, O);if (OA.lengthSqr() < BO.lengthSqr()) {sphere_0.center.set(capsule.ellipseCenter0);} else {sphere_0.center.set(capsule.ellipseCenter1);}return intersect.ray_sphere(ray, sphere_0);}const OAxBA = Vec3.cross(v3_4, OA, BA);const ab2 = BA.lengthSqr();const b = 2 * Vec3.dot(VxBA, OAxBA);const c = OAxBA.lengthSqr() - (radiusSqr * ab2);const d = b * b - 4 * a * c;if (d < 0) { return 0; }const t = (-b - Math.sqrt(d)) / (2 * a);if (t < 0) {sphere_0.radius = capsule.radius;const BO = Vec3.subtract(v3_5, B, O);if (OA.lengthSqr() < BO.lengthSqr()) {sphere_0.center.set(capsule.ellipseCenter0);} else {sphere_0.center.set(capsule.ellipseCenter1);}return intersect.ray_sphere(ray, sphere_0);} else {// Limit intersection between the bounds of the cylinder's end caps.const iPos = Vec3.scaleAndAdd(v3_5, ray.o, vRayNorm, t);const iPosLen = Vec3.subtract(v3_6, iPos, A);const tLimit = Vec3.dot(iPosLen, BA) / ab2;if (tLimit >= 0 && tLimit <= 1) {return t;} else if (tLimit < 0) {sphere_0.radius = capsule.radius;sphere_0.center.set(capsule.ellipseCenter0);return intersect.ray_sphere(ray, sphere_0);} else if (tLimit > 1) {sphere_0.radius = capsule.radius;sphere_0.center.set(capsule.ellipseCenter1);return intersect.ray_sphere(ray, sphere_0);} else {return 0;}}};})()
Const ray_mesh
ray_mesh: (Anonymous function) = (function () {let minDis = 0;const deOpt: IRayMeshOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY };return function (ray: ray, mesh: Mesh, options?: IRayMeshOptions) {minDis = 0;const opt = options === undefined ? deOpt : options;const length = mesh.renderingSubMeshes.length;const min = mesh.struct.minPosition;const max = mesh.struct.maxPosition;if (min && max && !ray_aabb2(ray, min, max)) return minDis;for (let i = 0; i < length; i++) {const sm = mesh.renderingSubMeshes[i];const dis = ray_subMesh(ray, sm, opt);if (dis) {if (opt.mode === ERaycastMode.CLOSEST) {if (minDis === 0 || minDis > dis) {minDis = dis;if (opt.subIndices) opt.subIndices[0] = i;}} else {minDis = dis;if (opt.subIndices) opt.subIndices.push(i);if (opt.mode === ERaycastMode.ANY) {return dis;}}}}if (minDis && opt.mode === ERaycastMode.CLOSEST) {if (opt.result) {opt.result[0].distance = minDis;opt.result.length = 1;}if (opt.subIndices) opt.subIndices.length = 1;}return minDis;}})()
Const ray_model
ray_model: (Anonymous function) = (function () {let minDis = 0;const deOpt: IRayModelOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY };const modelRay = new ray();const m4 = new Mat4();return function (r: ray, model: scene.Model, options?: IRayModelOptions) {minDis = 0;const opt = options === undefined ? deOpt : options;const wb = model.worldBounds;if (wb && !ray_aabb(r, wb)) return minDis;ray.copy(modelRay, r);if (model.node) {Mat4.invert(m4, model.node.getWorldMatrix(m4));Vec3.transformMat4(modelRay.o, r.o, m4);Vec3.transformMat4Normal(modelRay.d, r.d, m4);}const subModels = model.subModels;for (let i = 0; i < subModels.length; i++) {const subMesh = subModels[i].subMesh;const dis = ray_subMesh(modelRay, subMesh, opt);if (dis) {if (opt.mode === ERaycastMode.CLOSEST) {if (minDis === 0 || minDis > dis) {minDis = dis;if (opt.subIndices) opt.subIndices[0] = i;}} else {minDis = dis;if (opt.subIndices) opt.subIndices.push(i);if (opt.mode === ERaycastMode.ANY) {return dis;}}}}if (minDis && opt.mode === ERaycastMode.CLOSEST) {if (opt.result) {opt.result[0].distance = minDis;opt.result.length = 1;}if (opt.subIndices) opt.subIndices.length = 1;}return minDis;}})()
Const ray_obb
ray_obb: (Anonymous function) = (function () {let center = new Vec3();let o = new Vec3();let d = new Vec3();const X = new Vec3();const Y = new Vec3();const Z = new Vec3();const p = new Vec3();const size = new Array(3);const f = new Array(3);const e = new Array(3);const t = new Array(6);return function (ray: ray, obb: obb): number {size[0] = obb.halfExtents.x;size[1] = obb.halfExtents.y;size[2] = obb.halfExtents.z;center = obb.center;o = ray.o;d = ray.d;Vec3.set(X, obb.orientation.m00, obb.orientation.m01, obb.orientation.m02);Vec3.set(Y, obb.orientation.m03, obb.orientation.m04, obb.orientation.m05);Vec3.set(Z, obb.orientation.m06, obb.orientation.m07, obb.orientation.m08);Vec3.subtract(p, center, o);// The cos values of the ray on the X, Y, Zf[0] = Vec3.dot(X, d);f[1] = Vec3.dot(Y, d);f[2] = Vec3.dot(Z, d);// The projection length of P on X, Y, Ze[0] = Vec3.dot(X, p);e[1] = Vec3.dot(Y, p);e[2] = Vec3.dot(Z, p);for (let i = 0; i < 3; ++i) {if (f[i] === 0) {if (-e[i] - size[i] > 0 || -e[i] + size[i] < 0) {return 0;}// Avoid div by 0!f[i] = 0.0000001;}// mint[i * 2 + 0] = (e[i] + size[i]) / f[i];// maxt[i * 2 + 1] = (e[i] - size[i]) / f[i];}const tmin = Math.max(Math.max(Math.min(t[0], t[1]),Math.min(t[2], t[3])),Math.min(t[4], t[5]),);const tmax = Math.min(Math.min(Math.max(t[0], t[1]),Math.max(t[2], t[3])),Math.max(t[4], t[5]),);if (tmax < 0 || tmin > tmax) {return 0;}return tmin > 0 ? tmin : tmax; // ray origin inside aabb};})()
Const ray_plane
ray_plane: (Anonymous function) = (function () {const pt = new Vec3(0, 0, 0);return function (ray: ray, plane: plane): number {const denom = Vec3.dot(ray.d, plane.n);if (Math.abs(denom) < Number.EPSILON) { return 0; }Vec3.multiplyScalar(pt, plane.n, plane.d);const t = Vec3.dot(Vec3.subtract(pt, pt, ray.o), plane.n) / denom;if (t < 0) { return 0; }return t;};})()
Const ray_sphere
ray_sphere: (Anonymous function) = (function () {const e = new Vec3(0, 0, 0);return function (ray: ray, sphere: sphere): number {const r = sphere.radius;const c = sphere.center;const o = ray.o;const d = ray.d;const rSq = r * r;Vec3.subtract(e, c, o);const eSq = e.lengthSqr();const aLength = Vec3.dot(e, d); // assume ray direction already normalizedconst fSq = rSq - (eSq - aLength * aLength);if (fSq < 0) { return 0; }const f = Math.sqrt(fSq);const t = eSq < rSq ? aLength + f : aLength - f;if (t < 0) { return 0; }return t;};})()
Const ray_subMesh
ray_subMesh: (Anonymous function) = (function () {const tri = triangle.create();const deOpt: IRaySubMeshOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY };let minDis = 0;const fillResult = (m: ERaycastMode, d: number, i0: number, i1: number, i2: number, r?: IRaySubMeshResult[]) => {if (m === ERaycastMode.CLOSEST) {if (minDis > d || minDis === 0) {minDis = d;if (r) {if (r.length === 0) {r.push({ distance: d, vertexIndex0: i0 / 3, vertexIndex1: i1 / 3, vertexIndex2: i2 / 3 });} else {r[0].distance = d; r[0].vertexIndex0 = i0 / 3; r[0].vertexIndex1 = i1 / 3; r[0].vertexIndex2 = i2 / 3;}}}} else {minDis = d;if (r) r.push({ distance: d, vertexIndex0: i0 / 3, vertexIndex1: i1 / 3, vertexIndex2: i2 / 3 });}}const narrowphase = (vb: Float32Array, ib: IBArray, pm: GFXPrimitiveMode, ray: ray, opt: IRaySubMeshOptions) => {if (pm === GFXPrimitiveMode.TRIANGLE_LIST) {const cnt = ib.length;for (let j = 0; j < cnt; j += 3) {const i0 = ib[j] * 3;const i1 = ib[j + 1] * 3;const i2 = ib[j + 2] * 3;Vec3.set(tri.a, vb[i0], vb[i0 + 1], vb[i0 + 2]);Vec3.set(tri.b, vb[i1], vb[i1 + 1], vb[i1 + 2]);Vec3.set(tri.c, vb[i2], vb[i2 + 1], vb[i2 + 2]);const dist = intersect.ray_triangle(ray, tri, opt.doubleSided);if (dist === 0 || dist > opt.distance) continue;fillResult(opt.mode, dist, i0, i1, i2, opt.result);if (opt.mode === ERaycastMode.ANY) return dist;}} else if (pm === GFXPrimitiveMode.TRIANGLE_STRIP) {const cnt = ib.length - 2;let rev = 0;for (let j = 0; j < cnt; j += 1) {const i0 = ib[j - rev] * 3;const i1 = ib[j + rev + 1] * 3;const i2 = ib[j + 2] * 3;Vec3.set(tri.a, vb[i0], vb[i0 + 1], vb[i0 + 2]);Vec3.set(tri.b, vb[i1], vb[i1 + 1], vb[i1 + 2]);Vec3.set(tri.c, vb[i2], vb[i2 + 1], vb[i2 + 2]);rev = ~rev;const dist = intersect.ray_triangle(ray, tri, opt.doubleSided);if (dist === 0 || dist > opt.distance) continue;fillResult(opt.mode, dist, i0, i1, i2, opt.result);if (opt.mode === ERaycastMode.ANY) return dist;}} else if (pm === GFXPrimitiveMode.TRIANGLE_FAN) {const cnt = ib.length - 1;const i0 = ib[0] * 3;Vec3.set(tri.a, vb[i0], vb[i0 + 1], vb[i0 + 2]);for (let j = 1; j < cnt; j += 1) {const i1 = ib[j] * 3;const i2 = ib[j + 1] * 3;Vec3.set(tri.b, vb[i1], vb[i1 + 1], vb[i1 + 2]);Vec3.set(tri.c, vb[i2], vb[i2 + 1], vb[i2 + 2]);const dist = intersect.ray_triangle(ray, tri, opt.doubleSided);if (dist === 0 || dist > opt.distance) continue;fillResult(opt.mode, dist, i0, i1, i2, opt.result);if (opt.mode === ERaycastMode.ANY) return dist;}}return minDis;};return function (ray: ray, submesh: RenderingSubMesh, options?: IRaySubMeshOptions) {minDis = 0;if (submesh.geometricInfo.positions.length === 0) return minDis;const opt = options === undefined ? deOpt : options;const min = submesh.geometricInfo.boundingBox.min;const max = submesh.geometricInfo.boundingBox.max;if (ray_aabb2(ray, min, max)) {const pm = submesh.primitiveMode;const { positions: vb, indices: ib } = submesh.geometricInfo!;narrowphase(vb, ib!, pm, ray, opt);}return minDis;}})()
Const ray_triangle
ray_triangle: (Anonymous function) = (function () {const ab = new Vec3(0, 0, 0);const ac = new Vec3(0, 0, 0);const pvec = new Vec3(0, 0, 0);const tvec = new Vec3(0, 0, 0);const qvec = new Vec3(0, 0, 0);return function (ray: ray, triangle: triangle, doubleSided?: boolean) {Vec3.subtract(ab, triangle.b, triangle.a);Vec3.subtract(ac, triangle.c, triangle.a);Vec3.cross(pvec, ray.d, ac);const det = Vec3.dot(ab, pvec);if (det < Number.EPSILON && (!doubleSided || det > -Number.EPSILON)) { return 0; }const inv_det = 1 / det;Vec3.subtract(tvec, ray.o, triangle.a);const u = Vec3.dot(tvec, pvec) * inv_det;if (u < 0 || u > 1) { return 0; }Vec3.cross(qvec, tvec, ab);const v = Vec3.dot(ray.d, qvec) * inv_det;if (v < 0 || u + v > 1) { return 0; }const t = Vec3.dot(ac, qvec) * inv_det;return t < 0 ? 0 : t;};})()
Const sphere_aabb
sphere_aabb: (Anonymous function) = (function () {const pt = new Vec3();return function (sphere: sphere, aabb: aabb): boolean {distance.pt_point_aabb(pt, sphere.center, aabb);return Vec3.squaredDistance(sphere.center, pt) < sphere.radius * sphere.radius;};})()
Const sphere_capsule
sphere_capsule: (Anonymous function) = (function () {const v3_0 = new Vec3();const v3_1 = new Vec3();return function (sphere: sphere, capsule: capsule) {const r = sphere.radius + capsule.radius;const squaredR = r * r;const h = Vec3.squaredDistance(capsule.ellipseCenter0, capsule.ellipseCenter1);if (h === 0) {return Vec3.squaredDistance(sphere.center, capsule.center) < squaredR;} else {Vec3.subtract(v3_0, sphere.center, capsule.ellipseCenter0);Vec3.subtract(v3_1, capsule.ellipseCenter1, capsule.ellipseCenter0);const t = Vec3.dot(v3_0, v3_1) / h;if (t < 0) {return Vec3.squaredDistance(sphere.center, capsule.ellipseCenter0) < squaredR;} else if (t > 1) {return Vec3.squaredDistance(sphere.center, capsule.ellipseCenter1) < squaredR;} else {Vec3.scaleAndAdd(v3_0, capsule.ellipseCenter0, v3_1, t);return Vec3.squaredDistance(sphere.center, v3_0) < squaredR;}}};})()
Const sphere_frustum_accurate
sphere_frustum_accurate: (Anonymous function) = (function () {const pt = new Vec3(0, 0, 0), map = [1, -1, 1, -1, 1, -1];return function (sphere: sphere, frustum: frustum): number {for (let i = 0; i < 6; i++) {const plane = frustum.planes[i];const r = sphere.radius, c = sphere.center;const n = plane.n, d = plane.d;const dot = Vec3.dot(n, c);// frustum plane normal points to the insideif (dot + r < d) { return 0; } // completely outsideelse if (dot - r > d) { continue; }// in case of false positives// has false negatives, still working on itVec3.add(pt, c, Vec3.multiplyScalar(pt, n, r));for (let j = 0; j < 6; j++) {if (j === i || j === i + map[i]) { continue; }const test = frustum.planes[j];if (Vec3.dot(test.n, pt) < test.d) { return 0; }}}return 1;};})()
Const sphere_obb
sphere_obb: (Anonymous function) = (function () {const pt = new Vec3();return function (sphere: sphere, obb: obb): boolean {distance.pt_point_obb(pt, sphere.center, obb);return Vec3.squaredDistance(sphere.center, pt) < sphere.radius * sphere.radius;};})()
Const temp_mat
temp_mat: any = legacyCC.mat4()
Const temp_vec4
temp_vec4: any = legacyCC.v4()
Const u
u: any[] = new Array(3)
Const v1
v1
: Vec3 = new Vec3(0, 0, 0)
Const v2
v2
: Vec3 = new Vec3(0, 0, 0)
aabb-aabb intersect detect.
轴对齐包围盒和轴对齐包围盒的相交性检测。
轴对齐包围盒1
轴对齐包围盒2
0 或 非0