Options
All
  • Public
  • Public/Protected
  • All
Menu

External module geometry

几何工具模块

Index

Variables

Const LOOK_FORWARD

LOOK_FORWARD: 3 = 3

Const WrapMode

WrapMode: object = Enum({Default: 0,Once: 1,Loop: 2,PingPong: 3,ClampForever: 4,})

Type declaration

  • ClampForever: number
  • Default: number
  • Loop: number
  • Once: number
  • PingPong: number

Const X

X: Vec3 = new Vec3()

Const Y

Y: Vec3 = new Vec3()

Const Z

Z: Vec3 = new Vec3()

Const _m3_tmp

_m3_tmp: Mat3 = new Mat3()

Const _m3_tmp

_m3_tmp: Mat3 = new Mat3()

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);};})()
en

aabb-aabb intersect detect.

zh

轴对齐包围盒和轴对齐包围盒的相交性检测。

param

轴对齐包围盒1

param

轴对齐包围盒2

returns

0 或 非0

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;};})()
en

aabb-frustum intersect, handles most of the false positives correctly.

zh

轴对齐包围盒和锥台相交性检测,正确处理大多数错误情况。

param

轴对齐包围盒

param

锥台

returns

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;};})()
en

aabb-obb intersect detect.

zh

轴对齐包围盒和方向包围盒的相交性检测。

param

轴对齐包围盒

param

方向包围盒

returns

0 或 非0

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;};})()
en

capsule-capsule intersect detect.

zh

胶囊体和胶囊体的相交性检测。

Const d

d: Vec3 = new Vec3()

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;};})()
en

line-plane intersect detect.

zh

线段与平面的相交性检测。

param

线段

param

平面

returns

0 或 非0

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;};})()
en

line-triangle intersect detect.

zh

线段与三角形的相交性检测。

param

线段

param

三角形

param

可选,相交点

returns

0 或 非0

Const max

max: Vec3 = new Vec3()

Const min

min: Vec3 = new Vec3()

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;}};})()
en

obb-capsule intersect detect.

zh

方向包围盒和胶囊体的相交性检测。

param

方向包围盒

param

胶囊体

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;};})()
en

obb-frustum intersect, handles most of the false positives correctly.

zh

方向包围盒和锥台相交性检测,正确处理大多数错误情况。

param

方向包围盒

param

锥台

returns

0 或 非0

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;};})()
en

obb-obb intersect detect.

zh

方向包围盒和方向包围盒的相交性检测。

param

方向包围盒1

param

方向包围盒2

returns

0 或 非0

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;};})()
en

obb-plane intersect detect.

zh

方向包围盒和平面的相交性检测。

param

方向包围盒

param

平面

returns

inside(back) = -1, outside(front) = 0, intersect = 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);};})()
en

obb contains the point.

zh

方向包围盒和点的相交性检测。

param

方向包围盒

param

returns

true or false

Const r_t

r_t: ray = new ray()

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);};})()
en

ray-aabb intersect detect.

zh

射线和轴对齐包围盒的相交性检测。

param

射线

param

轴对齐包围盒

returns

0 或 非0

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;}}};})()
en

ray-capsule intersect detect.

zh

射线和胶囊体的相交性检测。

param

射线

param

胶囊体

returns

0 或 非0

Const ray_mesh

ray_mesh: (Anonymous function) = (function () {const deOpt: IRayMeshOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY, doNotZeroMin: true };return function (ray: ray, mesh: Mesh, option?: IRayMeshOptions) {const opt = option == undefined ? deOpt : option;const length = mesh.renderingSubMeshes.length;let result = false;const min = mesh.struct.minPosition;const max = mesh.struct.maxPosition;if (min && max && !ray_aabb2(ray, min, max)) return false;for (let i = 0; i < length; i++) {const sm = mesh.renderingSubMeshes[i];if (ray_subMesh(ray, sm, opt)) {result = true;if (opt.subIndices) opt.subIndices.push(i);if (opt.mode == ERaycastMode.ANY) {return true;}}}return result;}})()
en

ray-mesh intersect detect.

zh

射线和三角网格资源的相交性检测。

Const ray_model

ray_model: (Anonymous function) = (function () {const deOpt: IRayModelOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY, doNotZeroMin: true, doNotTransformRay: false };const modelRay = new ray();const m4 = new Mat4;return function (r: ray, model: Model, option?: IRayModelOptions) {const opt = option == undefined ? deOpt : option;const length = model.subModelNum;let result = false;ray.copy(modelRay, r);if (!opt.doNotTransformRay) {Mat4.invert(m4, model.node.getWorldMatrix(m4));Vec3.transformMat4(modelRay.o, r.o, m4);Vec3.normalize(modelRay.d, Vec3.transformMat4Normal(modelRay.d, r.d, m4));}const box = model.modelBounds;if (box && !ray_aabb(modelRay, box)) return false;for (let i = 0; i < length; i++) {const sm = model.getSubModel(i).subMeshData;if (ray_subMesh(modelRay, sm, opt)) {result = true;if (opt.subIndices) opt.subIndices.push(i);if (opt.mode == ERaycastMode.ANY) {return true;}}}return result;}})()
en

ray-model intersect detect.

zh

射线和渲染模型的相交性检测。

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};})()
en

ray-obb intersect detect.

zh

射线和方向包围盒的相交性检测。

param

射线

param

方向包围盒

returns

0 或 非0

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;};})()
en

ray-plane intersect detect.

zh

射线与平面的相交性检测。

param

射线

param

平面

returns

0 或 非0

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;};})()
en

ray-sphere intersect detect.

zh

射线和球的相交性检测。

param

射线

param

returns

0 或 非0

Const ray_subMesh

ray_subMesh: (Anonymous function) = (function () {const tri = triangle.create();const deOpt: IRaySubMeshOptions = { distance: Infinity, doubleSided: false, mode: ERaycastMode.ANY };const tr: IRaySubMeshResult = { distance: 0, vertexIndex0: 0, vertexIndex1: 0, vertexIndex2: 0 };let minDis = 0;const broadphase = (ray: ray, submesh: RenderingSubMesh) => {const min = submesh.geometricInfo.boundingBox.min;const max = submesh.geometricInfo.boundingBox.max;return ray_aabb2(ray, min, max);}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;if (opt.mode == ERaycastMode.CLOSEST) {if (minDis > dist || minDis == 0) {minDis = dist;tr.distance = dist;tr.vertexIndex0 = i0;tr.vertexIndex1 = i1;tr.vertexIndex2 = i2;if (opt.result && j + 3 < cnt)opt.result.push({ distance: tr.distance, vertexIndex0: tr.vertexIndex0, vertexIndex1: tr.vertexIndex1, vertexIndex2: tr.vertexIndex2 });}} else if (opt.mode == ERaycastMode.ALL) {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });} else {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });return minDis;}}} 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;if (opt.mode == ERaycastMode.CLOSEST) {if (minDis < dist) continue;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });} else if (opt.mode == ERaycastMode.ALL) {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });} else {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });return minDis;}}} 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;if (opt.mode == ERaycastMode.CLOSEST) {if (minDis < dist) continue;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });} else if (opt.mode == ERaycastMode.ALL) {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });} else {minDis = dist;if (opt.result) opt.result.push({ distance: dist, vertexIndex0: i0, vertexIndex1: i1, vertexIndex2: i2 });return minDis;}}}return minDis;};return function (ray: ray, submesh: RenderingSubMesh, option?: IRaySubMeshOptions) {const opt = option == undefined ? deOpt : option;if (!opt.doNotZeroMin) minDis = 0;if (submesh.geometricInfo.positions.length == 0) return;if (broadphase(ray, submesh)) {const pm = submesh.primitiveMode;const { positions: vb, indices: ib } = submesh.geometricInfo!;narrowphase(vb, ib!, pm, ray, opt);}return minDis != 0;}})()
en

ray-subMesh intersect detect.

zh

射线和子三角网格的相交性检测。

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;};})()
en

ray-triangle intersect detect.

zh

射线与三角形的相交性检测。

param

射线

param

三角形

param

三角形是否为双面

returns

0 或 非0

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;};})()
en

sphere-aabb intersect detect.

zh

球和轴对齐包围盒的相交性检测。

param

param

轴对齐包围盒

returns

true or false

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;}}};})()
en

sphere-capsule intersect detect.

zh

球和胶囊体的相交性检测。

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;};})()
en

sphere-frustum intersect, handles the false positives correctly.

zh

球和锥台的相交性检测,正确处理大多数错误情况。

param

param

锥台

returns

0 或 非0

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;};})()
en

sphere-obb intersect detect.

zh

球和方向包围盒的相交性检测。

param

param

方向包围盒

returns

true or false

Const temp_mat

temp_mat: any = cc.mat4()

Const temp_vec4

temp_vec4: any = cc.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)

Functions

Const aabbfrustum

Const aabbplane

  • aabbplane(aabb: aabb, plane: plane): number

evalOptCurve

  • evalOptCurve(t: number, coefs: Float32Array | number[]): number

getAABBVertices

getInterval

  • getInterval(vertices: any[] | Vec3[], axis: Vec3): number[]

getOBBVertices

lineaabb

  • lineaabb(line: line, aabb: aabb): number

lineobb

  • lineobb(line: line, obb: obb): number

linesphere

maxComponent

  • maxComponent(v: Vec3): number

Const obbfrustum

pointplane

  • pointplane(point: Vec3, plane_: plane): number

ptpointaabb

ptpointline

ptpointobb

ptpointplane

rayaabb2

Const spherefrustum

Const sphereplane

Const spheresphere

Const transformextentm3

  • transformextentm3(out: Vec3, extent: Vec3, m3: Mat3): void

Const transformextentm4

  • transformextentm4(out: Vec3, extent: Vec3, m4: Mat4): void

Object literals

Const intersect

intersect: object
en

Algorithm of intersect detect for basic geometry.

zh

基础几何的相交性检测算法。

aabb_aabb

aabb_aabb: (Anonymous function)

aabb_frustum

aabb_frustum: aabbfrustum

aabb_frustum_accurate

aabb_frustum_accurate: (Anonymous function)

aabb_obb

aabb_obb: (Anonymous function)

aabb_plane

aabb_plane: aabbplane

capsule_capsule

capsule_capsule: capsule_capsule

line_aabb

line_aabb: lineaabb

line_obb

line_obb: lineobb

line_plane

line_plane: (Anonymous function)

line_sphere

line_sphere: linesphere

line_triangle

line_triangle: (Anonymous function)

obb_capsule

obb_capsule: (Anonymous function)

obb_frustum

obb_frustum: obbfrustum

obb_frustum_accurate

obb_frustum_accurate: (Anonymous function)

obb_obb

obb_obb: (Anonymous function)

obb_plane

obb_plane: (Anonymous function)

obb_point

obb_point: (Anonymous function)

ray_aabb

ray_aabb: (Anonymous function)

ray_capsule

ray_capsule: (Anonymous function)

ray_mesh

ray_mesh: (Anonymous function)

ray_model

ray_model: (Anonymous function)

ray_obb

ray_obb: (Anonymous function)

ray_plane

ray_plane: (Anonymous function)

ray_sphere

ray_sphere: (Anonymous function)

ray_subMesh

ray_subMesh: (Anonymous function)

ray_triangle

ray_triangle: (Anonymous function)

sphere_aabb

sphere_aabb: (Anonymous function)

sphere_capsule

sphere_capsule: (Anonymous function)

sphere_frustum

sphere_frustum: spherefrustum

sphere_frustum_accurate

sphere_frustum_accurate: (Anonymous function)

sphere_obb

sphere_obb: (Anonymous function)

sphere_plane

sphere_plane: sphereplane

sphere_sphere

sphere_sphere: spheresphere

resolve

  • resolve(g1: any, g2: any, outPt?: null): any
  • g1 和 g2 的相交性检测,可填入基础几何中的形状。

    Parameters

    • g1: any

      几何1

    • g2: any

      几何2

    • Default value outPt: null = null

      可选,相交点。(注:仅部分形状的检测带有这个返回值)

    Returns any

Generated using TypeDoc