Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+99
View File
@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _v1 = /* @__PURE__ */ new THREE.Vector3();
const _v2 = /* @__PURE__ */ new THREE.Vector3();
const _v3 = /* @__PURE__ */ new THREE.Vector3();
const EPS = 1e-10;
class Capsule {
constructor(start = new THREE.Vector3(0, 0, 0), end = new THREE.Vector3(0, 1, 0), radius = 1) {
this.start = start;
this.end = end;
this.radius = radius;
}
clone() {
return new Capsule(this.start.clone(), this.end.clone(), this.radius);
}
set(start, end, radius) {
this.start.copy(start);
this.end.copy(end);
this.radius = radius;
}
copy(capsule) {
this.start.copy(capsule.start);
this.end.copy(capsule.end);
this.radius = capsule.radius;
}
getCenter(target) {
return target.copy(this.end).add(this.start).multiplyScalar(0.5);
}
translate(v) {
this.start.add(v);
this.end.add(v);
}
checkAABBAxis(p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius) {
return (minx - p1x < radius || minx - p2x < radius) && (p1x - maxx < radius || p2x - maxx < radius) && (miny - p1y < radius || miny - p2y < radius) && (p1y - maxy < radius || p2y - maxy < radius);
}
intersectsBox(box) {
return this.checkAABBAxis(
this.start.x,
this.start.y,
this.end.x,
this.end.y,
box.min.x,
box.max.x,
box.min.y,
box.max.y,
this.radius
) && this.checkAABBAxis(
this.start.x,
this.start.z,
this.end.x,
this.end.z,
box.min.x,
box.max.x,
box.min.z,
box.max.z,
this.radius
) && this.checkAABBAxis(
this.start.y,
this.start.z,
this.end.y,
this.end.z,
box.min.y,
box.max.y,
box.min.z,
box.max.z,
this.radius
);
}
lineLineMinimumPoints(line1, line2) {
const r = _v1.copy(line1.end).sub(line1.start);
const s = _v2.copy(line2.end).sub(line2.start);
const w = _v3.copy(line2.start).sub(line1.start);
const a = r.dot(s), b = r.dot(r), c = s.dot(s), d = s.dot(w), e = r.dot(w);
let t1, t2;
const divisor = b * c - a * a;
if (Math.abs(divisor) < EPS) {
const d1 = -d / c;
const d2 = (a - d) / c;
if (Math.abs(d1 - 0.5) < Math.abs(d2 - 0.5)) {
t1 = 0;
t2 = d1;
} else {
t1 = 1;
t2 = d2;
}
} else {
t1 = (d * a + e * c) / divisor;
t2 = (t1 * a - d) / c;
}
t2 = Math.max(0, Math.min(1, t2));
t1 = Math.max(0, Math.min(1, t1));
const point1 = r.multiplyScalar(t1).add(line1.start);
const point2 = s.multiplyScalar(t2).add(line2.start);
return [point1, point2];
}
}
exports.Capsule = Capsule;
//# sourceMappingURL=Capsule.cjs.map
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
import { Vector3, Line3, Box3 } from 'three'
export class Capsule {
constructor(start?: Vector3, end?: Vector3, radius?: number)
start: Vector3
end: Vector3
radius: number
set(start: Vector3, end: Vector3, radius: number): this
clone(): Capsule
copy(capsule: Capsule): this
getCenter(target: Vector3): Vector3
translate(v: Vector3): this
checkAABBAxis(
p1x: number,
p1y: number,
p2x: number,
p2y: number,
minx: number,
maxx: number,
miny: number,
maxy: number,
radius: number,
): boolean
intersectsBox(box: Box3): boolean
lineLineMinimumPoints(line1: Line3, line2: Line3): Vector3[]
}
+99
View File
@@ -0,0 +1,99 @@
import { Vector3 } from "three";
const _v1 = /* @__PURE__ */ new Vector3();
const _v2 = /* @__PURE__ */ new Vector3();
const _v3 = /* @__PURE__ */ new Vector3();
const EPS = 1e-10;
class Capsule {
constructor(start = new Vector3(0, 0, 0), end = new Vector3(0, 1, 0), radius = 1) {
this.start = start;
this.end = end;
this.radius = radius;
}
clone() {
return new Capsule(this.start.clone(), this.end.clone(), this.radius);
}
set(start, end, radius) {
this.start.copy(start);
this.end.copy(end);
this.radius = radius;
}
copy(capsule) {
this.start.copy(capsule.start);
this.end.copy(capsule.end);
this.radius = capsule.radius;
}
getCenter(target) {
return target.copy(this.end).add(this.start).multiplyScalar(0.5);
}
translate(v) {
this.start.add(v);
this.end.add(v);
}
checkAABBAxis(p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius) {
return (minx - p1x < radius || minx - p2x < radius) && (p1x - maxx < radius || p2x - maxx < radius) && (miny - p1y < radius || miny - p2y < radius) && (p1y - maxy < radius || p2y - maxy < radius);
}
intersectsBox(box) {
return this.checkAABBAxis(
this.start.x,
this.start.y,
this.end.x,
this.end.y,
box.min.x,
box.max.x,
box.min.y,
box.max.y,
this.radius
) && this.checkAABBAxis(
this.start.x,
this.start.z,
this.end.x,
this.end.z,
box.min.x,
box.max.x,
box.min.z,
box.max.z,
this.radius
) && this.checkAABBAxis(
this.start.y,
this.start.z,
this.end.y,
this.end.z,
box.min.y,
box.max.y,
box.min.z,
box.max.z,
this.radius
);
}
lineLineMinimumPoints(line1, line2) {
const r = _v1.copy(line1.end).sub(line1.start);
const s = _v2.copy(line2.end).sub(line2.start);
const w = _v3.copy(line2.start).sub(line1.start);
const a = r.dot(s), b = r.dot(r), c = s.dot(s), d = s.dot(w), e = r.dot(w);
let t1, t2;
const divisor = b * c - a * a;
if (Math.abs(divisor) < EPS) {
const d1 = -d / c;
const d2 = (a - d) / c;
if (Math.abs(d1 - 0.5) < Math.abs(d2 - 0.5)) {
t1 = 0;
t2 = d1;
} else {
t1 = 1;
t2 = d2;
}
} else {
t1 = (d * a + e * c) / divisor;
t2 = (t1 * a - d) / c;
}
t2 = Math.max(0, Math.min(1, t2));
t1 = Math.max(0, Math.min(1, t1));
const point1 = r.multiplyScalar(t1).add(line1.start);
const point2 = s.multiplyScalar(t2).add(line2.start);
return [point1, point2];
}
}
export {
Capsule
};
//# sourceMappingURL=Capsule.js.map
File diff suppressed because one or more lines are too long
+43
View File
@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _hsl = {};
const ColorConverter = {
setHSV(color, h, s, v) {
h = THREE.MathUtils.euclideanModulo(h, 1);
s = THREE.MathUtils.clamp(s, 0, 1);
v = THREE.MathUtils.clamp(v, 0, 1);
return color.setHSL(h, s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h), h * 0.5);
},
getHSV(color, target) {
color.getHSL(_hsl);
_hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l;
target.h = _hsl.h;
target.s = 2 * _hsl.s / (_hsl.l + _hsl.s);
target.v = _hsl.l + _hsl.s;
return target;
},
// where c, m, y, k is between 0 and 1
setCMYK(color, c, m, y, k) {
const r = (1 - c) * (1 - k);
const g = (1 - m) * (1 - k);
const b = (1 - y) * (1 - k);
return color.setRGB(r, g, b);
},
getCMYK(color, target) {
const r = color.r;
const g = color.g;
const b = color.b;
const k = 1 - Math.max(r, g, b);
const c = (1 - r - k) / (1 - k);
const m = (1 - g - k) / (1 - k);
const y = (1 - b - k) / (1 - k);
target.c = c;
target.m = m;
target.y = y;
target.k = k;
return target;
}
};
exports.ColorConverter = ColorConverter;
//# sourceMappingURL=ColorConverter.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ColorConverter.cjs","sources":["../../src/math/ColorConverter.js"],"sourcesContent":["import { MathUtils } from 'three'\n\nconst _hsl = {}\n\nconst ColorConverter = {\n setHSV(color, h, s, v) {\n // https://gist.github.com/xpansive/1337890#file-index-js\n\n h = MathUtils.euclideanModulo(h, 1)\n s = MathUtils.clamp(s, 0, 1)\n v = MathUtils.clamp(v, 0, 1)\n\n return color.setHSL(h, (s * v) / ((h = (2 - s) * v) < 1 ? h : 2 - h), h * 0.5)\n },\n\n getHSV(color, target) {\n color.getHSL(_hsl)\n\n // based on https://gist.github.com/xpansive/1337890#file-index-js\n _hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l\n\n target.h = _hsl.h\n target.s = (2 * _hsl.s) / (_hsl.l + _hsl.s)\n target.v = _hsl.l + _hsl.s\n\n return target\n },\n\n // where c, m, y, k is between 0 and 1\n\n setCMYK(color, c, m, y, k) {\n const r = (1 - c) * (1 - k)\n const g = (1 - m) * (1 - k)\n const b = (1 - y) * (1 - k)\n\n return color.setRGB(r, g, b)\n },\n\n getCMYK(color, target) {\n const r = color.r\n const g = color.g\n const b = color.b\n\n const k = 1 - Math.max(r, g, b)\n const c = (1 - r - k) / (1 - k)\n const m = (1 - g - k) / (1 - k)\n const y = (1 - b - k) / (1 - k)\n\n target.c = c\n target.m = m\n target.y = y\n target.k = k\n\n return target\n },\n}\n\nexport { ColorConverter }\n"],"names":["MathUtils"],"mappings":";;;AAEA,MAAM,OAAO,CAAE;AAEV,MAAC,iBAAiB;AAAA,EACrB,OAAO,OAAO,GAAG,GAAG,GAAG;AAGrB,QAAIA,MAAS,UAAC,gBAAgB,GAAG,CAAC;AAClC,QAAIA,MAAAA,UAAU,MAAM,GAAG,GAAG,CAAC;AAC3B,QAAIA,MAAAA,UAAU,MAAM,GAAG,GAAG,CAAC;AAE3B,WAAO,MAAM,OAAO,GAAI,IAAI,MAAO,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAAA,EAC9E;AAAA,EAED,OAAO,OAAO,QAAQ;AACpB,UAAM,OAAO,IAAI;AAGjB,SAAK,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;AAE3C,WAAO,IAAI,KAAK;AAChB,WAAO,IAAK,IAAI,KAAK,KAAM,KAAK,IAAI,KAAK;AACzC,WAAO,IAAI,KAAK,IAAI,KAAK;AAEzB,WAAO;AAAA,EACR;AAAA;AAAA,EAID,QAAQ,OAAO,GAAG,GAAG,GAAG,GAAG;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AAEzB,WAAO,MAAM,OAAO,GAAG,GAAG,CAAC;AAAA,EAC5B;AAAA,EAED,QAAQ,OAAO,QAAQ;AACrB,UAAM,IAAI,MAAM;AAChB,UAAM,IAAI,MAAM;AAChB,UAAM,IAAI,MAAM;AAEhB,UAAM,IAAI,IAAI,KAAK,IAAI,GAAG,GAAG,CAAC;AAC9B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAC7B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAC7B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAE7B,WAAO,IAAI;AACX,WAAO,IAAI;AACX,WAAO,IAAI;AACX,WAAO,IAAI;AAEX,WAAO;AAAA,EACR;AACH;;"}
+21
View File
@@ -0,0 +1,21 @@
import { Color } from 'three'
export interface HSL {
h: number
s: number
l: number
}
export interface CMYK {
c: number
m: number
y: number
k: number
}
export namespace ColorConverter {
function setHSV(color: Color, h: number, s: number, v: number): Color
function getHSV(color: Color, target: HSL): HSL
function setCMYK(color: Color, c: number, m: number, y: number, k: number): Color
function getCMYK(color: Color, target: CMYK): CMYK
}
+43
View File
@@ -0,0 +1,43 @@
import { MathUtils } from "three";
const _hsl = {};
const ColorConverter = {
setHSV(color, h, s, v) {
h = MathUtils.euclideanModulo(h, 1);
s = MathUtils.clamp(s, 0, 1);
v = MathUtils.clamp(v, 0, 1);
return color.setHSL(h, s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h), h * 0.5);
},
getHSV(color, target) {
color.getHSL(_hsl);
_hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l;
target.h = _hsl.h;
target.s = 2 * _hsl.s / (_hsl.l + _hsl.s);
target.v = _hsl.l + _hsl.s;
return target;
},
// where c, m, y, k is between 0 and 1
setCMYK(color, c, m, y, k) {
const r = (1 - c) * (1 - k);
const g = (1 - m) * (1 - k);
const b = (1 - y) * (1 - k);
return color.setRGB(r, g, b);
},
getCMYK(color, target) {
const r = color.r;
const g = color.g;
const b = color.b;
const k = 1 - Math.max(r, g, b);
const c = (1 - r - k) / (1 - k);
const m = (1 - g - k) / (1 - k);
const y = (1 - b - k) / (1 - k);
target.c = c;
target.m = m;
target.y = y;
target.k = k;
return target;
}
};
export {
ColorConverter
};
//# sourceMappingURL=ColorConverter.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ColorConverter.js","sources":["../../src/math/ColorConverter.js"],"sourcesContent":["import { MathUtils } from 'three'\n\nconst _hsl = {}\n\nconst ColorConverter = {\n setHSV(color, h, s, v) {\n // https://gist.github.com/xpansive/1337890#file-index-js\n\n h = MathUtils.euclideanModulo(h, 1)\n s = MathUtils.clamp(s, 0, 1)\n v = MathUtils.clamp(v, 0, 1)\n\n return color.setHSL(h, (s * v) / ((h = (2 - s) * v) < 1 ? h : 2 - h), h * 0.5)\n },\n\n getHSV(color, target) {\n color.getHSL(_hsl)\n\n // based on https://gist.github.com/xpansive/1337890#file-index-js\n _hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l\n\n target.h = _hsl.h\n target.s = (2 * _hsl.s) / (_hsl.l + _hsl.s)\n target.v = _hsl.l + _hsl.s\n\n return target\n },\n\n // where c, m, y, k is between 0 and 1\n\n setCMYK(color, c, m, y, k) {\n const r = (1 - c) * (1 - k)\n const g = (1 - m) * (1 - k)\n const b = (1 - y) * (1 - k)\n\n return color.setRGB(r, g, b)\n },\n\n getCMYK(color, target) {\n const r = color.r\n const g = color.g\n const b = color.b\n\n const k = 1 - Math.max(r, g, b)\n const c = (1 - r - k) / (1 - k)\n const m = (1 - g - k) / (1 - k)\n const y = (1 - b - k) / (1 - k)\n\n target.c = c\n target.m = m\n target.y = y\n target.k = k\n\n return target\n },\n}\n\nexport { ColorConverter }\n"],"names":[],"mappings":";AAEA,MAAM,OAAO,CAAE;AAEV,MAAC,iBAAiB;AAAA,EACrB,OAAO,OAAO,GAAG,GAAG,GAAG;AAGrB,QAAI,UAAU,gBAAgB,GAAG,CAAC;AAClC,QAAI,UAAU,MAAM,GAAG,GAAG,CAAC;AAC3B,QAAI,UAAU,MAAM,GAAG,GAAG,CAAC;AAE3B,WAAO,MAAM,OAAO,GAAI,IAAI,MAAO,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAAA,EAC9E;AAAA,EAED,OAAO,OAAO,QAAQ;AACpB,UAAM,OAAO,IAAI;AAGjB,SAAK,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;AAE3C,WAAO,IAAI,KAAK;AAChB,WAAO,IAAK,IAAI,KAAK,KAAM,KAAK,IAAI,KAAK;AACzC,WAAO,IAAI,KAAK,IAAI,KAAK;AAEzB,WAAO;AAAA,EACR;AAAA;AAAA,EAID,QAAQ,OAAO,GAAG,GAAG,GAAG,GAAG;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,IAAI,MAAM,IAAI;AAEzB,WAAO,MAAM,OAAO,GAAG,GAAG,CAAC;AAAA,EAC5B;AAAA,EAED,QAAQ,OAAO,QAAQ;AACrB,UAAM,IAAI,MAAM;AAChB,UAAM,IAAI,MAAM;AAChB,UAAM,IAAI,MAAM;AAEhB,UAAM,IAAI,IAAI,KAAK,IAAI,GAAG,GAAG,CAAC;AAC9B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAC7B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAC7B,UAAM,KAAK,IAAI,IAAI,MAAM,IAAI;AAE7B,WAAO,IAAI;AACX,WAAO,IAAI;AACX,WAAO,IAAI;AACX,WAAO,IAAI;AAEX,WAAO;AAAA,EACR;AACH;"}
+600
View File
@@ -0,0 +1,600 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const Visible = 0;
const Deleted = 1;
const _v1 = /* @__PURE__ */ new THREE.Vector3();
const _line3 = /* @__PURE__ */ new THREE.Line3();
const _plane = /* @__PURE__ */ new THREE.Plane();
const _closestPoint = /* @__PURE__ */ new THREE.Vector3();
const _triangle = /* @__PURE__ */ new THREE.Triangle();
class ConvexHull {
constructor() {
this.tolerance = -1;
this.faces = [];
this.newFaces = [];
this.assigned = new VertexList();
this.unassigned = new VertexList();
this.vertices = [];
}
setFromPoints(points) {
if (points.length >= 4) {
this.makeEmpty();
for (let i = 0, l = points.length; i < l; i++) {
this.vertices.push(new VertexNode(points[i]));
}
this.compute();
}
return this;
}
setFromObject(object) {
const points = [];
object.updateMatrixWorld(true);
object.traverse(function(node) {
const geometry = node.geometry;
if (geometry !== void 0) {
const attribute = geometry.attributes.position;
if (attribute !== void 0) {
for (let i = 0, l = attribute.count; i < l; i++) {
const point = new THREE.Vector3();
point.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld);
points.push(point);
}
}
}
});
return this.setFromPoints(points);
}
containsPoint(point) {
const faces = this.faces;
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
if (face.distanceToPoint(point) > this.tolerance)
return false;
}
return true;
}
intersectRay(ray, target) {
const faces = this.faces;
let tNear = -Infinity;
let tFar = Infinity;
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
const vN = face.distanceToPoint(ray.origin);
const vD = face.normal.dot(ray.direction);
if (vN > 0 && vD >= 0)
return null;
const t = vD !== 0 ? -vN / vD : 0;
if (t <= 0)
continue;
if (vD > 0) {
tFar = Math.min(t, tFar);
} else {
tNear = Math.max(t, tNear);
}
if (tNear > tFar) {
return null;
}
}
if (tNear !== -Infinity) {
ray.at(tNear, target);
} else {
ray.at(tFar, target);
}
return target;
}
intersectsRay(ray) {
return this.intersectRay(ray, _v1) !== null;
}
makeEmpty() {
this.faces = [];
this.vertices = [];
return this;
}
// Adds a vertex to the 'assigned' list of vertices and assigns it to the given face
addVertexToFace(vertex, face) {
vertex.face = face;
if (face.outside === null) {
this.assigned.append(vertex);
} else {
this.assigned.insertBefore(face.outside, vertex);
}
face.outside = vertex;
return this;
}
// Removes a vertex from the 'assigned' list of vertices and from the given face
removeVertexFromFace(vertex, face) {
if (vertex === face.outside) {
if (vertex.next !== null && vertex.next.face === face) {
face.outside = vertex.next;
} else {
face.outside = null;
}
}
this.assigned.remove(vertex);
return this;
}
// Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertex list
removeAllVerticesFromFace(face) {
if (face.outside !== null) {
const start = face.outside;
let end = face.outside;
while (end.next !== null && end.next.face === face) {
end = end.next;
}
this.assigned.removeSubList(start, end);
start.prev = end.next = null;
face.outside = null;
return start;
}
}
// Removes all the visible vertices that 'face' is able to see
deleteFaceVertices(face, absorbingFace) {
const faceVertices = this.removeAllVerticesFromFace(face);
if (faceVertices !== void 0) {
if (absorbingFace === void 0) {
this.unassigned.appendChain(faceVertices);
} else {
let vertex = faceVertices;
do {
const nextVertex = vertex.next;
const distance = absorbingFace.distanceToPoint(vertex.point);
if (distance > this.tolerance) {
this.addVertexToFace(vertex, absorbingFace);
} else {
this.unassigned.append(vertex);
}
vertex = nextVertex;
} while (vertex !== null);
}
}
return this;
}
// Reassigns as many vertices as possible from the unassigned list to the new faces
resolveUnassignedPoints(newFaces) {
if (this.unassigned.isEmpty() === false) {
let vertex = this.unassigned.first();
do {
const nextVertex = vertex.next;
let maxDistance = this.tolerance;
let maxFace = null;
for (let i = 0; i < newFaces.length; i++) {
const face = newFaces[i];
if (face.mark === Visible) {
const distance = face.distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
maxFace = face;
}
if (maxDistance > 1e3 * this.tolerance)
break;
}
}
if (maxFace !== null) {
this.addVertexToFace(vertex, maxFace);
}
vertex = nextVertex;
} while (vertex !== null);
}
return this;
}
// Computes the extremes of a simplex which will be the initial hull
computeExtremes() {
const min = new THREE.Vector3();
const max = new THREE.Vector3();
const minVertices = [];
const maxVertices = [];
for (let i = 0; i < 3; i++) {
minVertices[i] = maxVertices[i] = this.vertices[0];
}
min.copy(this.vertices[0].point);
max.copy(this.vertices[0].point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = this.vertices[i];
const point = vertex.point;
for (let j = 0; j < 3; j++) {
if (point.getComponent(j) < min.getComponent(j)) {
min.setComponent(j, point.getComponent(j));
minVertices[j] = vertex;
}
}
for (let j = 0; j < 3; j++) {
if (point.getComponent(j) > max.getComponent(j)) {
max.setComponent(j, point.getComponent(j));
maxVertices[j] = vertex;
}
}
}
this.tolerance = 3 * Number.EPSILON * (Math.max(Math.abs(min.x), Math.abs(max.x)) + Math.max(Math.abs(min.y), Math.abs(max.y)) + Math.max(Math.abs(min.z), Math.abs(max.z)));
return { min: minVertices, max: maxVertices };
}
// Computes the initial simplex assigning to its faces all the points
// that are candidates to form part of the hull
computeInitialHull() {
const vertices = this.vertices;
const extremes = this.computeExtremes();
const min = extremes.min;
const max = extremes.max;
let maxDistance = 0;
let index = 0;
for (let i = 0; i < 3; i++) {
const distance = max[i].point.getComponent(i) - min[i].point.getComponent(i);
if (distance > maxDistance) {
maxDistance = distance;
index = i;
}
}
const v0 = min[index];
const v1 = max[index];
let v2;
let v3;
maxDistance = 0;
_line3.set(v0.point, v1.point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1) {
_line3.closestPointToPoint(vertex.point, true, _closestPoint);
const distance = _closestPoint.distanceToSquared(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
v2 = vertex;
}
}
}
maxDistance = -1;
_plane.setFromCoplanarPoints(v0.point, v1.point, v2.point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
const distance = Math.abs(_plane.distanceToPoint(vertex.point));
if (distance > maxDistance) {
maxDistance = distance;
v3 = vertex;
}
}
}
const faces = [];
if (_plane.distanceToPoint(v3.point) < 0) {
faces.push(Face.create(v0, v1, v2), Face.create(v3, v1, v0), Face.create(v3, v2, v1), Face.create(v3, v0, v2));
for (let i = 0; i < 3; i++) {
const j = (i + 1) % 3;
faces[i + 1].getEdge(2).setTwin(faces[0].getEdge(j));
faces[i + 1].getEdge(1).setTwin(faces[j + 1].getEdge(0));
}
} else {
faces.push(Face.create(v0, v2, v1), Face.create(v3, v0, v1), Face.create(v3, v1, v2), Face.create(v3, v2, v0));
for (let i = 0; i < 3; i++) {
const j = (i + 1) % 3;
faces[i + 1].getEdge(2).setTwin(faces[0].getEdge((3 - i) % 3));
faces[i + 1].getEdge(0).setTwin(faces[j + 1].getEdge(1));
}
}
for (let i = 0; i < 4; i++) {
this.faces.push(faces[i]);
}
for (let i = 0, l = vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) {
maxDistance = this.tolerance;
let maxFace = null;
for (let j = 0; j < 4; j++) {
const distance = this.faces[j].distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
maxFace = this.faces[j];
}
}
if (maxFace !== null) {
this.addVertexToFace(vertex, maxFace);
}
}
}
return this;
}
// Removes inactive faces
reindexFaces() {
const activeFaces = [];
for (let i = 0; i < this.faces.length; i++) {
const face = this.faces[i];
if (face.mark === Visible) {
activeFaces.push(face);
}
}
this.faces = activeFaces;
return this;
}
// Finds the next vertex to create faces with the current hull
nextVertexToAdd() {
if (this.assigned.isEmpty() === false) {
let eyeVertex, maxDistance = 0;
const eyeFace = this.assigned.first().face;
let vertex = eyeFace.outside;
do {
const distance = eyeFace.distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
eyeVertex = vertex;
}
vertex = vertex.next;
} while (vertex !== null && vertex.face === eyeFace);
return eyeVertex;
}
}
// Computes a chain of half edges in CCW order called the 'horizon'.
// For an edge to be part of the horizon it must join a face that can see
// 'eyePoint' and a face that cannot see 'eyePoint'.
computeHorizon(eyePoint, crossEdge, face, horizon) {
this.deleteFaceVertices(face);
face.mark = Deleted;
let edge;
if (crossEdge === null) {
edge = crossEdge = face.getEdge(0);
} else {
edge = crossEdge.next;
}
do {
const twinEdge = edge.twin;
const oppositeFace = twinEdge.face;
if (oppositeFace.mark === Visible) {
if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) {
this.computeHorizon(eyePoint, twinEdge, oppositeFace, horizon);
} else {
horizon.push(edge);
}
}
edge = edge.next;
} while (edge !== crossEdge);
return this;
}
// Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order
addAdjoiningFace(eyeVertex, horizonEdge) {
const face = Face.create(eyeVertex, horizonEdge.tail(), horizonEdge.head());
this.faces.push(face);
face.getEdge(-1).setTwin(horizonEdge.twin);
return face.getEdge(0);
}
// Adds 'horizon.length' faces to the hull, each face will be linked with the
// horizon opposite face and the face on the left/right
addNewFaces(eyeVertex, horizon) {
this.newFaces = [];
let firstSideEdge = null;
let previousSideEdge = null;
for (let i = 0; i < horizon.length; i++) {
const horizonEdge = horizon[i];
const sideEdge = this.addAdjoiningFace(eyeVertex, horizonEdge);
if (firstSideEdge === null) {
firstSideEdge = sideEdge;
} else {
sideEdge.next.setTwin(previousSideEdge);
}
this.newFaces.push(sideEdge.face);
previousSideEdge = sideEdge;
}
firstSideEdge.next.setTwin(previousSideEdge);
return this;
}
// Adds a vertex to the hull
addVertexToHull(eyeVertex) {
const horizon = [];
this.unassigned.clear();
this.removeVertexFromFace(eyeVertex, eyeVertex.face);
this.computeHorizon(eyeVertex.point, null, eyeVertex.face, horizon);
this.addNewFaces(eyeVertex, horizon);
this.resolveUnassignedPoints(this.newFaces);
return this;
}
cleanup() {
this.assigned.clear();
this.unassigned.clear();
this.newFaces = [];
return this;
}
compute() {
let vertex;
this.computeInitialHull();
while ((vertex = this.nextVertexToAdd()) !== void 0) {
this.addVertexToHull(vertex);
}
this.reindexFaces();
this.cleanup();
return this;
}
}
const Face = /* @__PURE__ */ (() => {
class Face2 {
constructor() {
this.normal = new THREE.Vector3();
this.midpoint = new THREE.Vector3();
this.area = 0;
this.constant = 0;
this.outside = null;
this.mark = Visible;
this.edge = null;
}
static create(a, b, c) {
const face = new Face2();
const e0 = new HalfEdge(a, face);
const e1 = new HalfEdge(b, face);
const e2 = new HalfEdge(c, face);
e0.next = e2.prev = e1;
e1.next = e0.prev = e2;
e2.next = e1.prev = e0;
face.edge = e0;
return face.compute();
}
getEdge(i) {
let edge = this.edge;
while (i > 0) {
edge = edge.next;
i--;
}
while (i < 0) {
edge = edge.prev;
i++;
}
return edge;
}
compute() {
const a = this.edge.tail();
const b = this.edge.head();
const c = this.edge.next.head();
_triangle.set(a.point, b.point, c.point);
_triangle.getNormal(this.normal);
_triangle.getMidpoint(this.midpoint);
this.area = _triangle.getArea();
this.constant = this.normal.dot(this.midpoint);
return this;
}
distanceToPoint(point) {
return this.normal.dot(point) - this.constant;
}
}
return Face2;
})();
class HalfEdge {
constructor(vertex, face) {
this.vertex = vertex;
this.prev = null;
this.next = null;
this.twin = null;
this.face = face;
}
head() {
return this.vertex;
}
tail() {
return this.prev ? this.prev.vertex : null;
}
length() {
const head = this.head();
const tail = this.tail();
if (tail !== null) {
return tail.point.distanceTo(head.point);
}
return -1;
}
lengthSquared() {
const head = this.head();
const tail = this.tail();
if (tail !== null) {
return tail.point.distanceToSquared(head.point);
}
return -1;
}
setTwin(edge) {
this.twin = edge;
edge.twin = this;
return this;
}
}
class VertexNode {
constructor(point) {
this.point = point;
this.prev = null;
this.next = null;
this.face = null;
}
}
class VertexList {
constructor() {
this.head = null;
this.tail = null;
}
first() {
return this.head;
}
last() {
return this.tail;
}
clear() {
this.head = this.tail = null;
return this;
}
// Inserts a vertex before the target vertex
insertBefore(target, vertex) {
vertex.prev = target.prev;
vertex.next = target;
if (vertex.prev === null) {
this.head = vertex;
} else {
vertex.prev.next = vertex;
}
target.prev = vertex;
return this;
}
// Inserts a vertex after the target vertex
insertAfter(target, vertex) {
vertex.prev = target;
vertex.next = target.next;
if (vertex.next === null) {
this.tail = vertex;
} else {
vertex.next.prev = vertex;
}
target.next = vertex;
return this;
}
// Appends a vertex to the end of the linked list
append(vertex) {
if (this.head === null) {
this.head = vertex;
} else {
this.tail.next = vertex;
}
vertex.prev = this.tail;
vertex.next = null;
this.tail = vertex;
return this;
}
// Appends a chain of vertices where 'vertex' is the head.
appendChain(vertex) {
if (this.head === null) {
this.head = vertex;
} else {
this.tail.next = vertex;
}
vertex.prev = this.tail;
while (vertex.next !== null) {
vertex = vertex.next;
}
this.tail = vertex;
return this;
}
// Removes a vertex from the linked list
remove(vertex) {
if (vertex.prev === null) {
this.head = vertex.next;
} else {
vertex.prev.next = vertex.next;
}
if (vertex.next === null) {
this.tail = vertex.prev;
} else {
vertex.next.prev = vertex.prev;
}
return this;
}
// Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b
removeSubList(a, b) {
if (a.prev === null) {
this.head = b.next;
} else {
a.prev.next = b.next;
}
if (b.next === null) {
this.tail = a.prev;
} else {
b.next.prev = a.prev;
}
return this;
}
isEmpty() {
return this.head === null;
}
}
exports.ConvexHull = ConvexHull;
exports.Face = Face;
exports.HalfEdge = HalfEdge;
exports.VertexList = VertexList;
exports.VertexNode = VertexNode;
//# sourceMappingURL=ConvexHull.cjs.map
File diff suppressed because one or more lines are too long
+89
View File
@@ -0,0 +1,89 @@
import { Object3D, Ray, Vector3 } from 'three'
export class Face {
constructor()
normal: Vector3
midpoint: Vector3
area: number
constant: number
outside: VertexNode
mark: number
edge: HalfEdge
static create(a: VertexNode, b: VertexNode, c: VertexNode): Face
compute(): this
getEdge(i: number): HalfEdge
}
export class HalfEdge {
constructor(vertex: VertexNode, face: Face)
vertex: VertexNode
prev: HalfEdge
next: HalfEdge
twin: HalfEdge
face: Face
head(): VertexNode
length(): number
lengthSquared(): number
setTwin(edge: HalfEdge): this
tail(): VertexNode
}
export class VertexNode {
constructor(point: Vector3)
point: Vector3
prev: VertexNode
next: VertexNode
face: Face
}
export class VertexList {
constructor()
head: VertexNode
tail: VertexNode
append(vertex: VertexNode): this
appendChain(vertex: VertexNode): this
clear(): this
first(): VertexNode
insertAfter(target: VertexNode, vertex: VertexNode): this
insertBefore(target: VertexNode, vertex: VertexNode): this
isEmpty(): boolean
last(): VertexNode
remove(vertex: VertexNode): this
removeSubList(a: VertexNode, b: VertexNode): this
}
export class ConvexHull {
constructor()
tolerance: number
faces: Face[]
newFaces: Face[]
assigned: VertexList
unassigned: VertexList
vertices: VertexNode[]
addAdjoiningFace(eyeVertex: VertexNode, horizonEdge: HalfEdge): HalfEdge
addNewFaces(eyeVertex: VertexNode, horizon: HalfEdge[]): this
addVertexToFace(vertex: VertexNode, face: Face): this
addVertexToHull(eyeVertex: VertexNode): this
cleanup(): this
compute(): this
computeExtremes(): object
computeHorizon(eyePoint: Vector3, crossEdge: HalfEdge, face: Face, horizon: HalfEdge[]): this
computeInitialHull(): this
containsPoint(point: Vector3): boolean
deleteFaceVertices(face: Face, absorbingFace: Face): this
intersectRay(ray: Ray, target: Vector3): Vector3 | null
intersectsRay(ray: Ray): boolean
makeEmpty(): this
nextVertexToAdd(): VertexNode | undefined
reindexFaces(): this
removeAllVerticesFromFace(face: Face): VertexNode | undefined
removeVertexFromFace(vertex: VertexNode, face: Face): this
resolveUnassignedPoints(newFaces: Face[]): this
setFromPoints(points: Vector3[]): this
setFromObject(object: Object3D): this
}
+600
View File
@@ -0,0 +1,600 @@
import { Vector3, Line3, Plane, Triangle } from "three";
const Visible = 0;
const Deleted = 1;
const _v1 = /* @__PURE__ */ new Vector3();
const _line3 = /* @__PURE__ */ new Line3();
const _plane = /* @__PURE__ */ new Plane();
const _closestPoint = /* @__PURE__ */ new Vector3();
const _triangle = /* @__PURE__ */ new Triangle();
class ConvexHull {
constructor() {
this.tolerance = -1;
this.faces = [];
this.newFaces = [];
this.assigned = new VertexList();
this.unassigned = new VertexList();
this.vertices = [];
}
setFromPoints(points) {
if (points.length >= 4) {
this.makeEmpty();
for (let i = 0, l = points.length; i < l; i++) {
this.vertices.push(new VertexNode(points[i]));
}
this.compute();
}
return this;
}
setFromObject(object) {
const points = [];
object.updateMatrixWorld(true);
object.traverse(function(node) {
const geometry = node.geometry;
if (geometry !== void 0) {
const attribute = geometry.attributes.position;
if (attribute !== void 0) {
for (let i = 0, l = attribute.count; i < l; i++) {
const point = new Vector3();
point.fromBufferAttribute(attribute, i).applyMatrix4(node.matrixWorld);
points.push(point);
}
}
}
});
return this.setFromPoints(points);
}
containsPoint(point) {
const faces = this.faces;
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
if (face.distanceToPoint(point) > this.tolerance)
return false;
}
return true;
}
intersectRay(ray, target) {
const faces = this.faces;
let tNear = -Infinity;
let tFar = Infinity;
for (let i = 0, l = faces.length; i < l; i++) {
const face = faces[i];
const vN = face.distanceToPoint(ray.origin);
const vD = face.normal.dot(ray.direction);
if (vN > 0 && vD >= 0)
return null;
const t = vD !== 0 ? -vN / vD : 0;
if (t <= 0)
continue;
if (vD > 0) {
tFar = Math.min(t, tFar);
} else {
tNear = Math.max(t, tNear);
}
if (tNear > tFar) {
return null;
}
}
if (tNear !== -Infinity) {
ray.at(tNear, target);
} else {
ray.at(tFar, target);
}
return target;
}
intersectsRay(ray) {
return this.intersectRay(ray, _v1) !== null;
}
makeEmpty() {
this.faces = [];
this.vertices = [];
return this;
}
// Adds a vertex to the 'assigned' list of vertices and assigns it to the given face
addVertexToFace(vertex, face) {
vertex.face = face;
if (face.outside === null) {
this.assigned.append(vertex);
} else {
this.assigned.insertBefore(face.outside, vertex);
}
face.outside = vertex;
return this;
}
// Removes a vertex from the 'assigned' list of vertices and from the given face
removeVertexFromFace(vertex, face) {
if (vertex === face.outside) {
if (vertex.next !== null && vertex.next.face === face) {
face.outside = vertex.next;
} else {
face.outside = null;
}
}
this.assigned.remove(vertex);
return this;
}
// Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertex list
removeAllVerticesFromFace(face) {
if (face.outside !== null) {
const start = face.outside;
let end = face.outside;
while (end.next !== null && end.next.face === face) {
end = end.next;
}
this.assigned.removeSubList(start, end);
start.prev = end.next = null;
face.outside = null;
return start;
}
}
// Removes all the visible vertices that 'face' is able to see
deleteFaceVertices(face, absorbingFace) {
const faceVertices = this.removeAllVerticesFromFace(face);
if (faceVertices !== void 0) {
if (absorbingFace === void 0) {
this.unassigned.appendChain(faceVertices);
} else {
let vertex = faceVertices;
do {
const nextVertex = vertex.next;
const distance = absorbingFace.distanceToPoint(vertex.point);
if (distance > this.tolerance) {
this.addVertexToFace(vertex, absorbingFace);
} else {
this.unassigned.append(vertex);
}
vertex = nextVertex;
} while (vertex !== null);
}
}
return this;
}
// Reassigns as many vertices as possible from the unassigned list to the new faces
resolveUnassignedPoints(newFaces) {
if (this.unassigned.isEmpty() === false) {
let vertex = this.unassigned.first();
do {
const nextVertex = vertex.next;
let maxDistance = this.tolerance;
let maxFace = null;
for (let i = 0; i < newFaces.length; i++) {
const face = newFaces[i];
if (face.mark === Visible) {
const distance = face.distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
maxFace = face;
}
if (maxDistance > 1e3 * this.tolerance)
break;
}
}
if (maxFace !== null) {
this.addVertexToFace(vertex, maxFace);
}
vertex = nextVertex;
} while (vertex !== null);
}
return this;
}
// Computes the extremes of a simplex which will be the initial hull
computeExtremes() {
const min = new Vector3();
const max = new Vector3();
const minVertices = [];
const maxVertices = [];
for (let i = 0; i < 3; i++) {
minVertices[i] = maxVertices[i] = this.vertices[0];
}
min.copy(this.vertices[0].point);
max.copy(this.vertices[0].point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = this.vertices[i];
const point = vertex.point;
for (let j = 0; j < 3; j++) {
if (point.getComponent(j) < min.getComponent(j)) {
min.setComponent(j, point.getComponent(j));
minVertices[j] = vertex;
}
}
for (let j = 0; j < 3; j++) {
if (point.getComponent(j) > max.getComponent(j)) {
max.setComponent(j, point.getComponent(j));
maxVertices[j] = vertex;
}
}
}
this.tolerance = 3 * Number.EPSILON * (Math.max(Math.abs(min.x), Math.abs(max.x)) + Math.max(Math.abs(min.y), Math.abs(max.y)) + Math.max(Math.abs(min.z), Math.abs(max.z)));
return { min: minVertices, max: maxVertices };
}
// Computes the initial simplex assigning to its faces all the points
// that are candidates to form part of the hull
computeInitialHull() {
const vertices = this.vertices;
const extremes = this.computeExtremes();
const min = extremes.min;
const max = extremes.max;
let maxDistance = 0;
let index = 0;
for (let i = 0; i < 3; i++) {
const distance = max[i].point.getComponent(i) - min[i].point.getComponent(i);
if (distance > maxDistance) {
maxDistance = distance;
index = i;
}
}
const v0 = min[index];
const v1 = max[index];
let v2;
let v3;
maxDistance = 0;
_line3.set(v0.point, v1.point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1) {
_line3.closestPointToPoint(vertex.point, true, _closestPoint);
const distance = _closestPoint.distanceToSquared(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
v2 = vertex;
}
}
}
maxDistance = -1;
_plane.setFromCoplanarPoints(v0.point, v1.point, v2.point);
for (let i = 0, l = this.vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1 && vertex !== v2) {
const distance = Math.abs(_plane.distanceToPoint(vertex.point));
if (distance > maxDistance) {
maxDistance = distance;
v3 = vertex;
}
}
}
const faces = [];
if (_plane.distanceToPoint(v3.point) < 0) {
faces.push(Face.create(v0, v1, v2), Face.create(v3, v1, v0), Face.create(v3, v2, v1), Face.create(v3, v0, v2));
for (let i = 0; i < 3; i++) {
const j = (i + 1) % 3;
faces[i + 1].getEdge(2).setTwin(faces[0].getEdge(j));
faces[i + 1].getEdge(1).setTwin(faces[j + 1].getEdge(0));
}
} else {
faces.push(Face.create(v0, v2, v1), Face.create(v3, v0, v1), Face.create(v3, v1, v2), Face.create(v3, v2, v0));
for (let i = 0; i < 3; i++) {
const j = (i + 1) % 3;
faces[i + 1].getEdge(2).setTwin(faces[0].getEdge((3 - i) % 3));
faces[i + 1].getEdge(0).setTwin(faces[j + 1].getEdge(1));
}
}
for (let i = 0; i < 4; i++) {
this.faces.push(faces[i]);
}
for (let i = 0, l = vertices.length; i < l; i++) {
const vertex = vertices[i];
if (vertex !== v0 && vertex !== v1 && vertex !== v2 && vertex !== v3) {
maxDistance = this.tolerance;
let maxFace = null;
for (let j = 0; j < 4; j++) {
const distance = this.faces[j].distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
maxFace = this.faces[j];
}
}
if (maxFace !== null) {
this.addVertexToFace(vertex, maxFace);
}
}
}
return this;
}
// Removes inactive faces
reindexFaces() {
const activeFaces = [];
for (let i = 0; i < this.faces.length; i++) {
const face = this.faces[i];
if (face.mark === Visible) {
activeFaces.push(face);
}
}
this.faces = activeFaces;
return this;
}
// Finds the next vertex to create faces with the current hull
nextVertexToAdd() {
if (this.assigned.isEmpty() === false) {
let eyeVertex, maxDistance = 0;
const eyeFace = this.assigned.first().face;
let vertex = eyeFace.outside;
do {
const distance = eyeFace.distanceToPoint(vertex.point);
if (distance > maxDistance) {
maxDistance = distance;
eyeVertex = vertex;
}
vertex = vertex.next;
} while (vertex !== null && vertex.face === eyeFace);
return eyeVertex;
}
}
// Computes a chain of half edges in CCW order called the 'horizon'.
// For an edge to be part of the horizon it must join a face that can see
// 'eyePoint' and a face that cannot see 'eyePoint'.
computeHorizon(eyePoint, crossEdge, face, horizon) {
this.deleteFaceVertices(face);
face.mark = Deleted;
let edge;
if (crossEdge === null) {
edge = crossEdge = face.getEdge(0);
} else {
edge = crossEdge.next;
}
do {
const twinEdge = edge.twin;
const oppositeFace = twinEdge.face;
if (oppositeFace.mark === Visible) {
if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) {
this.computeHorizon(eyePoint, twinEdge, oppositeFace, horizon);
} else {
horizon.push(edge);
}
}
edge = edge.next;
} while (edge !== crossEdge);
return this;
}
// Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order
addAdjoiningFace(eyeVertex, horizonEdge) {
const face = Face.create(eyeVertex, horizonEdge.tail(), horizonEdge.head());
this.faces.push(face);
face.getEdge(-1).setTwin(horizonEdge.twin);
return face.getEdge(0);
}
// Adds 'horizon.length' faces to the hull, each face will be linked with the
// horizon opposite face and the face on the left/right
addNewFaces(eyeVertex, horizon) {
this.newFaces = [];
let firstSideEdge = null;
let previousSideEdge = null;
for (let i = 0; i < horizon.length; i++) {
const horizonEdge = horizon[i];
const sideEdge = this.addAdjoiningFace(eyeVertex, horizonEdge);
if (firstSideEdge === null) {
firstSideEdge = sideEdge;
} else {
sideEdge.next.setTwin(previousSideEdge);
}
this.newFaces.push(sideEdge.face);
previousSideEdge = sideEdge;
}
firstSideEdge.next.setTwin(previousSideEdge);
return this;
}
// Adds a vertex to the hull
addVertexToHull(eyeVertex) {
const horizon = [];
this.unassigned.clear();
this.removeVertexFromFace(eyeVertex, eyeVertex.face);
this.computeHorizon(eyeVertex.point, null, eyeVertex.face, horizon);
this.addNewFaces(eyeVertex, horizon);
this.resolveUnassignedPoints(this.newFaces);
return this;
}
cleanup() {
this.assigned.clear();
this.unassigned.clear();
this.newFaces = [];
return this;
}
compute() {
let vertex;
this.computeInitialHull();
while ((vertex = this.nextVertexToAdd()) !== void 0) {
this.addVertexToHull(vertex);
}
this.reindexFaces();
this.cleanup();
return this;
}
}
const Face = /* @__PURE__ */ (() => {
class Face2 {
constructor() {
this.normal = new Vector3();
this.midpoint = new Vector3();
this.area = 0;
this.constant = 0;
this.outside = null;
this.mark = Visible;
this.edge = null;
}
static create(a, b, c) {
const face = new Face2();
const e0 = new HalfEdge(a, face);
const e1 = new HalfEdge(b, face);
const e2 = new HalfEdge(c, face);
e0.next = e2.prev = e1;
e1.next = e0.prev = e2;
e2.next = e1.prev = e0;
face.edge = e0;
return face.compute();
}
getEdge(i) {
let edge = this.edge;
while (i > 0) {
edge = edge.next;
i--;
}
while (i < 0) {
edge = edge.prev;
i++;
}
return edge;
}
compute() {
const a = this.edge.tail();
const b = this.edge.head();
const c = this.edge.next.head();
_triangle.set(a.point, b.point, c.point);
_triangle.getNormal(this.normal);
_triangle.getMidpoint(this.midpoint);
this.area = _triangle.getArea();
this.constant = this.normal.dot(this.midpoint);
return this;
}
distanceToPoint(point) {
return this.normal.dot(point) - this.constant;
}
}
return Face2;
})();
class HalfEdge {
constructor(vertex, face) {
this.vertex = vertex;
this.prev = null;
this.next = null;
this.twin = null;
this.face = face;
}
head() {
return this.vertex;
}
tail() {
return this.prev ? this.prev.vertex : null;
}
length() {
const head = this.head();
const tail = this.tail();
if (tail !== null) {
return tail.point.distanceTo(head.point);
}
return -1;
}
lengthSquared() {
const head = this.head();
const tail = this.tail();
if (tail !== null) {
return tail.point.distanceToSquared(head.point);
}
return -1;
}
setTwin(edge) {
this.twin = edge;
edge.twin = this;
return this;
}
}
class VertexNode {
constructor(point) {
this.point = point;
this.prev = null;
this.next = null;
this.face = null;
}
}
class VertexList {
constructor() {
this.head = null;
this.tail = null;
}
first() {
return this.head;
}
last() {
return this.tail;
}
clear() {
this.head = this.tail = null;
return this;
}
// Inserts a vertex before the target vertex
insertBefore(target, vertex) {
vertex.prev = target.prev;
vertex.next = target;
if (vertex.prev === null) {
this.head = vertex;
} else {
vertex.prev.next = vertex;
}
target.prev = vertex;
return this;
}
// Inserts a vertex after the target vertex
insertAfter(target, vertex) {
vertex.prev = target;
vertex.next = target.next;
if (vertex.next === null) {
this.tail = vertex;
} else {
vertex.next.prev = vertex;
}
target.next = vertex;
return this;
}
// Appends a vertex to the end of the linked list
append(vertex) {
if (this.head === null) {
this.head = vertex;
} else {
this.tail.next = vertex;
}
vertex.prev = this.tail;
vertex.next = null;
this.tail = vertex;
return this;
}
// Appends a chain of vertices where 'vertex' is the head.
appendChain(vertex) {
if (this.head === null) {
this.head = vertex;
} else {
this.tail.next = vertex;
}
vertex.prev = this.tail;
while (vertex.next !== null) {
vertex = vertex.next;
}
this.tail = vertex;
return this;
}
// Removes a vertex from the linked list
remove(vertex) {
if (vertex.prev === null) {
this.head = vertex.next;
} else {
vertex.prev.next = vertex.next;
}
if (vertex.next === null) {
this.tail = vertex.prev;
} else {
vertex.next.prev = vertex.prev;
}
return this;
}
// Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b
removeSubList(a, b) {
if (a.prev === null) {
this.head = b.next;
} else {
a.prev.next = b.next;
}
if (b.next === null) {
this.tail = a.prev;
} else {
b.next.prev = a.prev;
}
return this;
}
isEmpty() {
return this.head === null;
}
}
export {
ConvexHull,
Face,
HalfEdge,
VertexList,
VertexNode
};
//# sourceMappingURL=ConvexHull.js.map
File diff suppressed because one or more lines are too long
+305
View File
@@ -0,0 +1,305 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
function init() {
const _p2 = [
151,
160,
137,
91,
90,
15,
131,
13,
201,
95,
96,
53,
194,
233,
7,
225,
140,
36,
103,
30,
69,
142,
8,
99,
37,
240,
21,
10,
23,
190,
6,
148,
247,
120,
234,
75,
0,
26,
197,
62,
94,
252,
219,
203,
117,
35,
11,
32,
57,
177,
33,
88,
237,
149,
56,
87,
174,
20,
125,
136,
171,
168,
68,
175,
74,
165,
71,
134,
139,
48,
27,
166,
77,
146,
158,
231,
83,
111,
229,
122,
60,
211,
133,
230,
220,
105,
92,
41,
55,
46,
245,
40,
244,
102,
143,
54,
65,
25,
63,
161,
1,
216,
80,
73,
209,
76,
132,
187,
208,
89,
18,
169,
200,
196,
135,
130,
116,
188,
159,
86,
164,
100,
109,
198,
173,
186,
3,
64,
52,
217,
226,
250,
124,
123,
5,
202,
38,
147,
118,
126,
255,
82,
85,
212,
207,
206,
59,
227,
47,
16,
58,
17,
182,
189,
28,
42,
223,
183,
170,
213,
119,
248,
152,
2,
44,
154,
163,
70,
221,
153,
101,
155,
167,
43,
172,
9,
129,
22,
39,
253,
19,
98,
108,
110,
79,
113,
224,
232,
178,
185,
112,
104,
218,
246,
97,
228,
251,
34,
242,
193,
238,
210,
144,
12,
191,
179,
162,
241,
81,
51,
145,
235,
249,
14,
239,
107,
49,
192,
214,
31,
181,
199,
106,
157,
184,
84,
204,
176,
115,
121,
50,
45,
127,
4,
150,
254,
138,
236,
205,
93,
222,
114,
67,
29,
24,
72,
243,
141,
128,
195,
78,
66,
215,
61,
156,
180
];
for (let i = 0; i < 256; i++) {
_p2[256 + i] = _p2[i];
}
return _p2;
}
const _p = /* @__PURE__ */ init();
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
function grad(hash, x, y, z) {
const h = hash & 15;
const u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
class ImprovedNoise {
noise(x, y, z) {
const floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
const X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
x -= floorX;
y -= floorY;
z -= floorZ;
const xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
const u = fade(x), v = fade(y), w = fade(z);
const A = _p[X] + Y, AA = _p[A] + Z, AB = _p[A + 1] + Z, B = _p[X + 1] + Y, BA = _p[B] + Z, BB = _p[B + 1] + Z;
return lerp(
w,
lerp(
v,
lerp(u, grad(_p[AA], x, y, z), grad(_p[BA], xMinus1, y, z)),
lerp(u, grad(_p[AB], x, yMinus1, z), grad(_p[BB], xMinus1, yMinus1, z))
),
lerp(
v,
lerp(u, grad(_p[AA + 1], x, y, zMinus1), grad(_p[BA + 1], xMinus1, y, zMinus1)),
lerp(u, grad(_p[AB + 1], x, yMinus1, zMinus1), grad(_p[BB + 1], xMinus1, yMinus1, zMinus1))
)
);
}
}
exports.ImprovedNoise = ImprovedNoise;
//# sourceMappingURL=ImprovedNoise.cjs.map
File diff suppressed because one or more lines are too long
+4
View File
@@ -0,0 +1,4 @@
export class ImprovedNoise {
constructor()
noise(x: number, y: number, z: number): number
}
+305
View File
@@ -0,0 +1,305 @@
function init() {
const _p2 = [
151,
160,
137,
91,
90,
15,
131,
13,
201,
95,
96,
53,
194,
233,
7,
225,
140,
36,
103,
30,
69,
142,
8,
99,
37,
240,
21,
10,
23,
190,
6,
148,
247,
120,
234,
75,
0,
26,
197,
62,
94,
252,
219,
203,
117,
35,
11,
32,
57,
177,
33,
88,
237,
149,
56,
87,
174,
20,
125,
136,
171,
168,
68,
175,
74,
165,
71,
134,
139,
48,
27,
166,
77,
146,
158,
231,
83,
111,
229,
122,
60,
211,
133,
230,
220,
105,
92,
41,
55,
46,
245,
40,
244,
102,
143,
54,
65,
25,
63,
161,
1,
216,
80,
73,
209,
76,
132,
187,
208,
89,
18,
169,
200,
196,
135,
130,
116,
188,
159,
86,
164,
100,
109,
198,
173,
186,
3,
64,
52,
217,
226,
250,
124,
123,
5,
202,
38,
147,
118,
126,
255,
82,
85,
212,
207,
206,
59,
227,
47,
16,
58,
17,
182,
189,
28,
42,
223,
183,
170,
213,
119,
248,
152,
2,
44,
154,
163,
70,
221,
153,
101,
155,
167,
43,
172,
9,
129,
22,
39,
253,
19,
98,
108,
110,
79,
113,
224,
232,
178,
185,
112,
104,
218,
246,
97,
228,
251,
34,
242,
193,
238,
210,
144,
12,
191,
179,
162,
241,
81,
51,
145,
235,
249,
14,
239,
107,
49,
192,
214,
31,
181,
199,
106,
157,
184,
84,
204,
176,
115,
121,
50,
45,
127,
4,
150,
254,
138,
236,
205,
93,
222,
114,
67,
29,
24,
72,
243,
141,
128,
195,
78,
66,
215,
61,
156,
180
];
for (let i = 0; i < 256; i++) {
_p2[256 + i] = _p2[i];
}
return _p2;
}
const _p = /* @__PURE__ */ init();
function fade(t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
function lerp(t, a, b) {
return a + t * (b - a);
}
function grad(hash, x, y, z) {
const h = hash & 15;
const u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
class ImprovedNoise {
noise(x, y, z) {
const floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
const X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
x -= floorX;
y -= floorY;
z -= floorZ;
const xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
const u = fade(x), v = fade(y), w = fade(z);
const A = _p[X] + Y, AA = _p[A] + Z, AB = _p[A + 1] + Z, B = _p[X + 1] + Y, BA = _p[B] + Z, BB = _p[B + 1] + Z;
return lerp(
w,
lerp(
v,
lerp(u, grad(_p[AA], x, y, z), grad(_p[BA], xMinus1, y, z)),
lerp(u, grad(_p[AB], x, yMinus1, z), grad(_p[BB], xMinus1, yMinus1, z))
),
lerp(
v,
lerp(u, grad(_p[AA + 1], x, y, zMinus1), grad(_p[BA + 1], xMinus1, y, zMinus1)),
lerp(u, grad(_p[AB + 1], x, yMinus1, zMinus1), grad(_p[BB + 1], xMinus1, yMinus1, zMinus1))
)
);
}
}
export {
ImprovedNoise
};
//# sourceMappingURL=ImprovedNoise.js.map
File diff suppressed because one or more lines are too long
+138
View File
@@ -0,0 +1,138 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class Lut {
constructor(colormap, count = 32) {
this.isLut = true;
this.lut = [];
this.map = [];
this.n = 0;
this.minV = 0;
this.maxV = 1;
this.setColorMap(colormap, count);
}
set(value) {
if (value.isLut === true) {
this.copy(value);
}
return this;
}
setMin(min) {
this.minV = min;
return this;
}
setMax(max) {
this.maxV = max;
return this;
}
setColorMap(colormap, count = 32) {
this.map = ColorMapKeywords[colormap] || ColorMapKeywords.rainbow;
this.n = count;
const step = 1 / this.n;
const minColor = new THREE.Color();
const maxColor = new THREE.Color();
this.lut.length = 0;
this.lut.push(new THREE.Color(this.map[0][1]));
for (let i = 1; i < count; i++) {
const alpha = i * step;
for (let j = 0; j < this.map.length - 1; j++) {
if (alpha > this.map[j][0] && alpha <= this.map[j + 1][0]) {
const min = this.map[j][0];
const max = this.map[j + 1][0];
minColor.setHex(this.map[j][1], "srgb-linear");
maxColor.setHex(this.map[j + 1][1], "srgb-linear");
const color = new THREE.Color().lerpColors(minColor, maxColor, (alpha - min) / (max - min));
this.lut.push(color);
}
}
}
this.lut.push(new THREE.Color(this.map[this.map.length - 1][1]));
return this;
}
copy(lut) {
this.lut = lut.lut;
this.map = lut.map;
this.n = lut.n;
this.minV = lut.minV;
this.maxV = lut.maxV;
return this;
}
getColor(alpha) {
alpha = THREE.MathUtils.clamp(alpha, this.minV, this.maxV);
alpha = (alpha - this.minV) / (this.maxV - this.minV);
const colorPosition = Math.round(alpha * this.n);
return this.lut[colorPosition];
}
addColorMap(name, arrayOfColors) {
ColorMapKeywords[name] = arrayOfColors;
return this;
}
createCanvas() {
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = this.n;
this.updateCanvas(canvas);
return canvas;
}
updateCanvas(canvas) {
const ctx = canvas.getContext("2d", { alpha: false });
const imageData = ctx.getImageData(0, 0, 1, this.n);
const data = imageData.data;
let k = 0;
const step = 1 / this.n;
const minColor = new THREE.Color();
const maxColor = new THREE.Color();
const finalColor = new THREE.Color();
for (let i = 1; i >= 0; i -= step) {
for (let j = this.map.length - 1; j >= 0; j--) {
if (i < this.map[j][0] && i >= this.map[j - 1][0]) {
const min = this.map[j - 1][0];
const max = this.map[j][0];
minColor.setHex(this.map[j - 1][1], "srgb-linear");
maxColor.setHex(this.map[j][1], "srgb-linear");
finalColor.lerpColors(minColor, maxColor, (i - min) / (max - min));
data[k * 4] = Math.round(finalColor.r * 255);
data[k * 4 + 1] = Math.round(finalColor.g * 255);
data[k * 4 + 2] = Math.round(finalColor.b * 255);
data[k * 4 + 3] = 255;
k += 1;
}
}
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
}
const ColorMapKeywords = {
rainbow: [
[0, 255],
[0.2, 65535],
[0.5, 65280],
[0.8, 16776960],
[1, 16711680]
],
cooltowarm: [
[0, 3952322],
[0.2, 10206463],
[0.5, 14474460],
[0.8, 16163717],
[1, 11797542]
],
blackbody: [
[0, 0],
[0.2, 7864320],
[0.5, 15086080],
[0.8, 16776960],
[1, 16777215]
],
grayscale: [
[0, 0],
[0.2, 4210752],
[0.5, 8355712],
[0.8, 12566463],
[1, 16777215]
]
};
exports.ColorMapKeywords = ColorMapKeywords;
exports.Lut = Lut;
//# sourceMappingURL=Lut.cjs.map
+1
View File
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
import { Color } from 'three'
export class Lut {
constructor(colormap?: string, numberofcolors?: number)
lut: Color[]
map: object[]
n: number
minV: number
maxV: number
set(value: Lut): this
setMin(min: number): this
setMax(max: number): this
setColorMap(colormap?: string, numberofcolors?: number): this
copy(lut: Lut): this
getColor(alpha: number): Color
addColorMap(colormapName: string, arrayOfColors: number[][]): void
createCanvas(): HTMLCanvasElement
updateCanvas(canvas: HTMLCanvasElement): HTMLCanvasElement
}
export interface ColorMapKeywords {
rainbow: number[][]
cooltowarm: number[][]
blackbody: number[][]
grayscale: number[][]
}
+138
View File
@@ -0,0 +1,138 @@
import { Color, MathUtils } from "three";
class Lut {
constructor(colormap, count = 32) {
this.isLut = true;
this.lut = [];
this.map = [];
this.n = 0;
this.minV = 0;
this.maxV = 1;
this.setColorMap(colormap, count);
}
set(value) {
if (value.isLut === true) {
this.copy(value);
}
return this;
}
setMin(min) {
this.minV = min;
return this;
}
setMax(max) {
this.maxV = max;
return this;
}
setColorMap(colormap, count = 32) {
this.map = ColorMapKeywords[colormap] || ColorMapKeywords.rainbow;
this.n = count;
const step = 1 / this.n;
const minColor = new Color();
const maxColor = new Color();
this.lut.length = 0;
this.lut.push(new Color(this.map[0][1]));
for (let i = 1; i < count; i++) {
const alpha = i * step;
for (let j = 0; j < this.map.length - 1; j++) {
if (alpha > this.map[j][0] && alpha <= this.map[j + 1][0]) {
const min = this.map[j][0];
const max = this.map[j + 1][0];
minColor.setHex(this.map[j][1], "srgb-linear");
maxColor.setHex(this.map[j + 1][1], "srgb-linear");
const color = new Color().lerpColors(minColor, maxColor, (alpha - min) / (max - min));
this.lut.push(color);
}
}
}
this.lut.push(new Color(this.map[this.map.length - 1][1]));
return this;
}
copy(lut) {
this.lut = lut.lut;
this.map = lut.map;
this.n = lut.n;
this.minV = lut.minV;
this.maxV = lut.maxV;
return this;
}
getColor(alpha) {
alpha = MathUtils.clamp(alpha, this.minV, this.maxV);
alpha = (alpha - this.minV) / (this.maxV - this.minV);
const colorPosition = Math.round(alpha * this.n);
return this.lut[colorPosition];
}
addColorMap(name, arrayOfColors) {
ColorMapKeywords[name] = arrayOfColors;
return this;
}
createCanvas() {
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = this.n;
this.updateCanvas(canvas);
return canvas;
}
updateCanvas(canvas) {
const ctx = canvas.getContext("2d", { alpha: false });
const imageData = ctx.getImageData(0, 0, 1, this.n);
const data = imageData.data;
let k = 0;
const step = 1 / this.n;
const minColor = new Color();
const maxColor = new Color();
const finalColor = new Color();
for (let i = 1; i >= 0; i -= step) {
for (let j = this.map.length - 1; j >= 0; j--) {
if (i < this.map[j][0] && i >= this.map[j - 1][0]) {
const min = this.map[j - 1][0];
const max = this.map[j][0];
minColor.setHex(this.map[j - 1][1], "srgb-linear");
maxColor.setHex(this.map[j][1], "srgb-linear");
finalColor.lerpColors(minColor, maxColor, (i - min) / (max - min));
data[k * 4] = Math.round(finalColor.r * 255);
data[k * 4 + 1] = Math.round(finalColor.g * 255);
data[k * 4 + 2] = Math.round(finalColor.b * 255);
data[k * 4 + 3] = 255;
k += 1;
}
}
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
}
const ColorMapKeywords = {
rainbow: [
[0, 255],
[0.2, 65535],
[0.5, 65280],
[0.8, 16776960],
[1, 16711680]
],
cooltowarm: [
[0, 3952322],
[0.2, 10206463],
[0.5, 14474460],
[0.8, 16163717],
[1, 11797542]
],
blackbody: [
[0, 0],
[0.2, 7864320],
[0.5, 15086080],
[0.8, 16776960],
[1, 16777215]
],
grayscale: [
[0, 0],
[0.2, 4210752],
[0.5, 8355712],
[0.8, 12566463],
[1, 16777215]
]
};
export {
ColorMapKeywords,
Lut
};
//# sourceMappingURL=Lut.js.map
+1
View File
File diff suppressed because one or more lines are too long
+104
View File
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _face = /* @__PURE__ */ new THREE.Triangle();
const _color = /* @__PURE__ */ new THREE.Vector3();
class MeshSurfaceSampler {
constructor(mesh) {
let geometry = mesh.geometry;
if (geometry.index) {
console.warn("THREE.MeshSurfaceSampler: Converting geometry to non-indexed BufferGeometry.");
geometry = geometry.toNonIndexed();
}
this.geometry = geometry;
this.randomFunction = Math.random;
this.positionAttribute = this.geometry.getAttribute("position");
this.colorAttribute = this.geometry.getAttribute("color");
this.weightAttribute = null;
this.distribution = null;
}
setWeightAttribute(name) {
this.weightAttribute = name ? this.geometry.getAttribute(name) : null;
return this;
}
build() {
const positionAttribute = this.positionAttribute;
const weightAttribute = this.weightAttribute;
const faceWeights = new Float32Array(positionAttribute.count / 3);
for (let i = 0; i < positionAttribute.count; i += 3) {
let faceWeight = 1;
if (weightAttribute) {
faceWeight = weightAttribute.getX(i) + weightAttribute.getX(i + 1) + weightAttribute.getX(i + 2);
}
_face.a.fromBufferAttribute(positionAttribute, i);
_face.b.fromBufferAttribute(positionAttribute, i + 1);
_face.c.fromBufferAttribute(positionAttribute, i + 2);
faceWeight *= _face.getArea();
faceWeights[i / 3] = faceWeight;
}
this.distribution = new Float32Array(positionAttribute.count / 3);
let cumulativeTotal = 0;
for (let i = 0; i < faceWeights.length; i++) {
cumulativeTotal += faceWeights[i];
this.distribution[i] = cumulativeTotal;
}
return this;
}
setRandomGenerator(randomFunction) {
this.randomFunction = randomFunction;
return this;
}
sample(targetPosition, targetNormal, targetColor) {
const faceIndex = this.sampleFaceIndex();
return this.sampleFace(faceIndex, targetPosition, targetNormal, targetColor);
}
sampleFaceIndex() {
const cumulativeTotal = this.distribution[this.distribution.length - 1];
return this.binarySearch(this.randomFunction() * cumulativeTotal);
}
binarySearch(x) {
const dist = this.distribution;
let start = 0;
let end = dist.length - 1;
let index = -1;
while (start <= end) {
const mid = Math.ceil((start + end) / 2);
if (mid === 0 || dist[mid - 1] <= x && dist[mid] > x) {
index = mid;
break;
} else if (x < dist[mid]) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return index;
}
sampleFace(faceIndex, targetPosition, targetNormal, targetColor) {
let u = this.randomFunction();
let v = this.randomFunction();
if (u + v > 1) {
u = 1 - u;
v = 1 - v;
}
_face.a.fromBufferAttribute(this.positionAttribute, faceIndex * 3);
_face.b.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 1);
_face.c.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 2);
targetPosition.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));
if (targetNormal !== void 0) {
_face.getNormal(targetNormal);
}
if (targetColor !== void 0 && this.colorAttribute !== void 0) {
_face.a.fromBufferAttribute(this.colorAttribute, faceIndex * 3);
_face.b.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 1);
_face.c.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 2);
_color.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));
targetColor.r = _color.x;
targetColor.g = _color.y;
targetColor.b = _color.z;
}
return this;
}
}
exports.MeshSurfaceSampler = MeshSurfaceSampler;
//# sourceMappingURL=MeshSurfaceSampler.cjs.map
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
import { BufferGeometry, Color, Mesh, Vector3 } from 'three'
export class MeshSurfaceSampler {
distribution: Float32Array | null
geometry: BufferGeometry
positionAttribute: Float32Array
weightAttribute: string | null
randomFunction: () => number
setRandomGenerator(randomFunction: () => number): this
constructor(mesh: Mesh)
binarySearch(x: number): number
build(): this
sample(targetPosition: Vector3, targetNormal?: Vector3, targetColor?: Color): this
sampleFace(faceIndex: number, targetPosition: Vector3, targetNormal?: Vector3, targetColor?: Color): this
sampleFaceIndex(): number
setWeightAttribute(name: string | null): this
}
+104
View File
@@ -0,0 +1,104 @@
import { Triangle, Vector3 } from "three";
const _face = /* @__PURE__ */ new Triangle();
const _color = /* @__PURE__ */ new Vector3();
class MeshSurfaceSampler {
constructor(mesh) {
let geometry = mesh.geometry;
if (geometry.index) {
console.warn("THREE.MeshSurfaceSampler: Converting geometry to non-indexed BufferGeometry.");
geometry = geometry.toNonIndexed();
}
this.geometry = geometry;
this.randomFunction = Math.random;
this.positionAttribute = this.geometry.getAttribute("position");
this.colorAttribute = this.geometry.getAttribute("color");
this.weightAttribute = null;
this.distribution = null;
}
setWeightAttribute(name) {
this.weightAttribute = name ? this.geometry.getAttribute(name) : null;
return this;
}
build() {
const positionAttribute = this.positionAttribute;
const weightAttribute = this.weightAttribute;
const faceWeights = new Float32Array(positionAttribute.count / 3);
for (let i = 0; i < positionAttribute.count; i += 3) {
let faceWeight = 1;
if (weightAttribute) {
faceWeight = weightAttribute.getX(i) + weightAttribute.getX(i + 1) + weightAttribute.getX(i + 2);
}
_face.a.fromBufferAttribute(positionAttribute, i);
_face.b.fromBufferAttribute(positionAttribute, i + 1);
_face.c.fromBufferAttribute(positionAttribute, i + 2);
faceWeight *= _face.getArea();
faceWeights[i / 3] = faceWeight;
}
this.distribution = new Float32Array(positionAttribute.count / 3);
let cumulativeTotal = 0;
for (let i = 0; i < faceWeights.length; i++) {
cumulativeTotal += faceWeights[i];
this.distribution[i] = cumulativeTotal;
}
return this;
}
setRandomGenerator(randomFunction) {
this.randomFunction = randomFunction;
return this;
}
sample(targetPosition, targetNormal, targetColor) {
const faceIndex = this.sampleFaceIndex();
return this.sampleFace(faceIndex, targetPosition, targetNormal, targetColor);
}
sampleFaceIndex() {
const cumulativeTotal = this.distribution[this.distribution.length - 1];
return this.binarySearch(this.randomFunction() * cumulativeTotal);
}
binarySearch(x) {
const dist = this.distribution;
let start = 0;
let end = dist.length - 1;
let index = -1;
while (start <= end) {
const mid = Math.ceil((start + end) / 2);
if (mid === 0 || dist[mid - 1] <= x && dist[mid] > x) {
index = mid;
break;
} else if (x < dist[mid]) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return index;
}
sampleFace(faceIndex, targetPosition, targetNormal, targetColor) {
let u = this.randomFunction();
let v = this.randomFunction();
if (u + v > 1) {
u = 1 - u;
v = 1 - v;
}
_face.a.fromBufferAttribute(this.positionAttribute, faceIndex * 3);
_face.b.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 1);
_face.c.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 2);
targetPosition.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));
if (targetNormal !== void 0) {
_face.getNormal(targetNormal);
}
if (targetColor !== void 0 && this.colorAttribute !== void 0) {
_face.a.fromBufferAttribute(this.colorAttribute, faceIndex * 3);
_face.b.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 1);
_face.c.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 2);
_color.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));
targetColor.r = _color.x;
targetColor.g = _color.y;
targetColor.b = _color.z;
}
return this;
}
}
export {
MeshSurfaceSampler
};
//# sourceMappingURL=MeshSurfaceSampler.js.map
File diff suppressed because one or more lines are too long
+243
View File
@@ -0,0 +1,243 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const a = {
c: null,
// center
u: [/* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3()],
// basis vectors
e: []
// half width
};
const b = {
c: null,
// center
u: [/* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3(), /* @__PURE__ */ new THREE.Vector3()],
// basis vectors
e: []
// half width
};
const R = [[], [], []];
const AbsR = [[], [], []];
const t = [];
const xAxis = /* @__PURE__ */ new THREE.Vector3();
const yAxis = /* @__PURE__ */ new THREE.Vector3();
const zAxis = /* @__PURE__ */ new THREE.Vector3();
const v1 = /* @__PURE__ */ new THREE.Vector3();
const size = /* @__PURE__ */ new THREE.Vector3();
const closestPoint = /* @__PURE__ */ new THREE.Vector3();
const rotationMatrix = /* @__PURE__ */ new THREE.Matrix3();
const aabb = /* @__PURE__ */ new THREE.Box3();
const matrix = /* @__PURE__ */ new THREE.Matrix4();
const inverse = /* @__PURE__ */ new THREE.Matrix4();
const localRay = /* @__PURE__ */ new THREE.Ray();
class OBB {
constructor(center = new THREE.Vector3(), halfSize = new THREE.Vector3(), rotation = new THREE.Matrix3()) {
this.center = center;
this.halfSize = halfSize;
this.rotation = rotation;
}
set(center, halfSize, rotation) {
this.center = center;
this.halfSize = halfSize;
this.rotation = rotation;
return this;
}
copy(obb2) {
this.center.copy(obb2.center);
this.halfSize.copy(obb2.halfSize);
this.rotation.copy(obb2.rotation);
return this;
}
clone() {
return new this.constructor().copy(this);
}
getSize(result) {
return result.copy(this.halfSize).multiplyScalar(2);
}
/**
* Reference: Closest Point on OBB to Point in Real-Time Collision Detection
* by Christer Ericson (chapter 5.1.4)
*/
clampPoint(point, result) {
const halfSize = this.halfSize;
v1.subVectors(point, this.center);
this.rotation.extractBasis(xAxis, yAxis, zAxis);
result.copy(this.center);
const x = THREE.MathUtils.clamp(v1.dot(xAxis), -halfSize.x, halfSize.x);
result.add(xAxis.multiplyScalar(x));
const y = THREE.MathUtils.clamp(v1.dot(yAxis), -halfSize.y, halfSize.y);
result.add(yAxis.multiplyScalar(y));
const z = THREE.MathUtils.clamp(v1.dot(zAxis), -halfSize.z, halfSize.z);
result.add(zAxis.multiplyScalar(z));
return result;
}
containsPoint(point) {
v1.subVectors(point, this.center);
this.rotation.extractBasis(xAxis, yAxis, zAxis);
return Math.abs(v1.dot(xAxis)) <= this.halfSize.x && Math.abs(v1.dot(yAxis)) <= this.halfSize.y && Math.abs(v1.dot(zAxis)) <= this.halfSize.z;
}
intersectsBox3(box3) {
return this.intersectsOBB(obb.fromBox3(box3));
}
intersectsSphere(sphere) {
this.clampPoint(sphere.center, closestPoint);
return closestPoint.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;
}
/**
* Reference: OBB-OBB Intersection in Real-Time Collision Detection
* by Christer Ericson (chapter 4.4.1)
*
*/
intersectsOBB(obb2, epsilon = Number.EPSILON) {
a.c = this.center;
a.e[0] = this.halfSize.x;
a.e[1] = this.halfSize.y;
a.e[2] = this.halfSize.z;
this.rotation.extractBasis(a.u[0], a.u[1], a.u[2]);
b.c = obb2.center;
b.e[0] = obb2.halfSize.x;
b.e[1] = obb2.halfSize.y;
b.e[2] = obb2.halfSize.z;
obb2.rotation.extractBasis(b.u[0], b.u[1], b.u[2]);
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
R[i][j] = a.u[i].dot(b.u[j]);
}
}
v1.subVectors(b.c, a.c);
t[0] = v1.dot(a.u[0]);
t[1] = v1.dot(a.u[1]);
t[2] = v1.dot(a.u[2]);
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
AbsR[i][j] = Math.abs(R[i][j]) + epsilon;
}
}
let ra, rb;
for (let i = 0; i < 3; i++) {
ra = a.e[i];
rb = b.e[0] * AbsR[i][0] + b.e[1] * AbsR[i][1] + b.e[2] * AbsR[i][2];
if (Math.abs(t[i]) > ra + rb)
return false;
}
for (let i = 0; i < 3; i++) {
ra = a.e[0] * AbsR[0][i] + a.e[1] * AbsR[1][i] + a.e[2] * AbsR[2][i];
rb = b.e[i];
if (Math.abs(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb)
return false;
}
ra = a.e[1] * AbsR[2][0] + a.e[2] * AbsR[1][0];
rb = b.e[1] * AbsR[0][2] + b.e[2] * AbsR[0][1];
if (Math.abs(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb)
return false;
ra = a.e[1] * AbsR[2][1] + a.e[2] * AbsR[1][1];
rb = b.e[0] * AbsR[0][2] + b.e[2] * AbsR[0][0];
if (Math.abs(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb)
return false;
ra = a.e[1] * AbsR[2][2] + a.e[2] * AbsR[1][2];
rb = b.e[0] * AbsR[0][1] + b.e[1] * AbsR[0][0];
if (Math.abs(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][0] + a.e[2] * AbsR[0][0];
rb = b.e[1] * AbsR[1][2] + b.e[2] * AbsR[1][1];
if (Math.abs(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][1] + a.e[2] * AbsR[0][1];
rb = b.e[0] * AbsR[1][2] + b.e[2] * AbsR[1][0];
if (Math.abs(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][2] + a.e[2] * AbsR[0][2];
rb = b.e[0] * AbsR[1][1] + b.e[1] * AbsR[1][0];
if (Math.abs(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][0] + a.e[1] * AbsR[0][0];
rb = b.e[1] * AbsR[2][2] + b.e[2] * AbsR[2][1];
if (Math.abs(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][1] + a.e[1] * AbsR[0][1];
rb = b.e[0] * AbsR[2][2] + b.e[2] * AbsR[2][0];
if (Math.abs(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][2] + a.e[1] * AbsR[0][2];
rb = b.e[0] * AbsR[2][1] + b.e[1] * AbsR[2][0];
if (Math.abs(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb)
return false;
return true;
}
/**
* Reference: Testing Box Against Plane in Real-Time Collision Detection
* by Christer Ericson (chapter 5.2.3)
*/
intersectsPlane(plane) {
this.rotation.extractBasis(xAxis, yAxis, zAxis);
const r = this.halfSize.x * Math.abs(plane.normal.dot(xAxis)) + this.halfSize.y * Math.abs(plane.normal.dot(yAxis)) + this.halfSize.z * Math.abs(plane.normal.dot(zAxis));
const d = plane.normal.dot(this.center) - plane.constant;
return Math.abs(d) <= r;
}
/**
* Performs a ray/OBB intersection test and stores the intersection point
* to the given 3D vector. If no intersection is detected, *null* is returned.
*/
intersectRay(ray, result) {
this.getSize(size);
aabb.setFromCenterAndSize(v1.set(0, 0, 0), size);
matrix.setFromMatrix3(this.rotation);
matrix.setPosition(this.center);
inverse.copy(matrix).invert();
localRay.copy(ray).applyMatrix4(inverse);
if (localRay.intersectBox(aabb, result)) {
return result.applyMatrix4(matrix);
} else {
return null;
}
}
/**
* Performs a ray/OBB intersection test. Returns either true or false if
* there is a intersection or not.
*/
intersectsRay(ray) {
return this.intersectRay(ray, v1) !== null;
}
fromBox3(box3) {
box3.getCenter(this.center);
box3.getSize(this.halfSize).multiplyScalar(0.5);
this.rotation.identity();
return this;
}
equals(obb2) {
return obb2.center.equals(this.center) && obb2.halfSize.equals(this.halfSize) && obb2.rotation.equals(this.rotation);
}
applyMatrix4(matrix2) {
const e = matrix2.elements;
let sx = v1.set(e[0], e[1], e[2]).length();
const sy = v1.set(e[4], e[5], e[6]).length();
const sz = v1.set(e[8], e[9], e[10]).length();
const det = matrix2.determinant();
if (det < 0)
sx = -sx;
rotationMatrix.setFromMatrix4(matrix2);
const invSX = 1 / sx;
const invSY = 1 / sy;
const invSZ = 1 / sz;
rotationMatrix.elements[0] *= invSX;
rotationMatrix.elements[1] *= invSX;
rotationMatrix.elements[2] *= invSX;
rotationMatrix.elements[3] *= invSY;
rotationMatrix.elements[4] *= invSY;
rotationMatrix.elements[5] *= invSY;
rotationMatrix.elements[6] *= invSZ;
rotationMatrix.elements[7] *= invSZ;
rotationMatrix.elements[8] *= invSZ;
this.rotation.multiply(rotationMatrix);
this.halfSize.x *= sx;
this.halfSize.y *= sy;
this.halfSize.z *= sz;
v1.setFromMatrixPosition(matrix2);
this.center.add(v1);
return this;
}
}
const obb = /* @__PURE__ */ new OBB();
exports.OBB = OBB;
//# sourceMappingURL=OBB.cjs.map
+1
View File
File diff suppressed because one or more lines are too long
+24
View File
@@ -0,0 +1,24 @@
import { Box3, Matrix3, Matrix4, Plane, Ray, Sphere, Vector3 } from 'three'
export class OBB {
center: Vector3
halfSize: Vector3
rotation: Matrix3
constructor(center?: Vector3, halfSize?: Vector3, rotation?: Matrix3)
set(center: Vector3, halfSize: Vector3, rotation: Matrix3): this
copy(obb: OBB): this
clone(): this
getSize(result: Vector3): Vector3
clampPoint(point: Vector3, result: Vector3): Vector3
containsPoint(point: Vector3): boolean
intersectsBox3(box3: Box3): boolean
intersectsSphere(sphere: Sphere): boolean
intersectsOBB(obb: OBB, epsilon?: number): boolean
intersectsPlane(plane: Plane): boolean
intersectRay(ray: Ray, result: Vector3): Vector3 | null
intersectsRay(ray: Ray): boolean
fromBox3(box3: Box3): this
equals(obb: OBB): boolean
applyMatrix4(matrix: Matrix4): this
}
+243
View File
@@ -0,0 +1,243 @@
import { Vector3, Matrix3, MathUtils, Box3, Matrix4, Ray } from "three";
const a = {
c: null,
// center
u: [/* @__PURE__ */ new Vector3(), /* @__PURE__ */ new Vector3(), /* @__PURE__ */ new Vector3()],
// basis vectors
e: []
// half width
};
const b = {
c: null,
// center
u: [/* @__PURE__ */ new Vector3(), /* @__PURE__ */ new Vector3(), /* @__PURE__ */ new Vector3()],
// basis vectors
e: []
// half width
};
const R = [[], [], []];
const AbsR = [[], [], []];
const t = [];
const xAxis = /* @__PURE__ */ new Vector3();
const yAxis = /* @__PURE__ */ new Vector3();
const zAxis = /* @__PURE__ */ new Vector3();
const v1 = /* @__PURE__ */ new Vector3();
const size = /* @__PURE__ */ new Vector3();
const closestPoint = /* @__PURE__ */ new Vector3();
const rotationMatrix = /* @__PURE__ */ new Matrix3();
const aabb = /* @__PURE__ */ new Box3();
const matrix = /* @__PURE__ */ new Matrix4();
const inverse = /* @__PURE__ */ new Matrix4();
const localRay = /* @__PURE__ */ new Ray();
class OBB {
constructor(center = new Vector3(), halfSize = new Vector3(), rotation = new Matrix3()) {
this.center = center;
this.halfSize = halfSize;
this.rotation = rotation;
}
set(center, halfSize, rotation) {
this.center = center;
this.halfSize = halfSize;
this.rotation = rotation;
return this;
}
copy(obb2) {
this.center.copy(obb2.center);
this.halfSize.copy(obb2.halfSize);
this.rotation.copy(obb2.rotation);
return this;
}
clone() {
return new this.constructor().copy(this);
}
getSize(result) {
return result.copy(this.halfSize).multiplyScalar(2);
}
/**
* Reference: Closest Point on OBB to Point in Real-Time Collision Detection
* by Christer Ericson (chapter 5.1.4)
*/
clampPoint(point, result) {
const halfSize = this.halfSize;
v1.subVectors(point, this.center);
this.rotation.extractBasis(xAxis, yAxis, zAxis);
result.copy(this.center);
const x = MathUtils.clamp(v1.dot(xAxis), -halfSize.x, halfSize.x);
result.add(xAxis.multiplyScalar(x));
const y = MathUtils.clamp(v1.dot(yAxis), -halfSize.y, halfSize.y);
result.add(yAxis.multiplyScalar(y));
const z = MathUtils.clamp(v1.dot(zAxis), -halfSize.z, halfSize.z);
result.add(zAxis.multiplyScalar(z));
return result;
}
containsPoint(point) {
v1.subVectors(point, this.center);
this.rotation.extractBasis(xAxis, yAxis, zAxis);
return Math.abs(v1.dot(xAxis)) <= this.halfSize.x && Math.abs(v1.dot(yAxis)) <= this.halfSize.y && Math.abs(v1.dot(zAxis)) <= this.halfSize.z;
}
intersectsBox3(box3) {
return this.intersectsOBB(obb.fromBox3(box3));
}
intersectsSphere(sphere) {
this.clampPoint(sphere.center, closestPoint);
return closestPoint.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius;
}
/**
* Reference: OBB-OBB Intersection in Real-Time Collision Detection
* by Christer Ericson (chapter 4.4.1)
*
*/
intersectsOBB(obb2, epsilon = Number.EPSILON) {
a.c = this.center;
a.e[0] = this.halfSize.x;
a.e[1] = this.halfSize.y;
a.e[2] = this.halfSize.z;
this.rotation.extractBasis(a.u[0], a.u[1], a.u[2]);
b.c = obb2.center;
b.e[0] = obb2.halfSize.x;
b.e[1] = obb2.halfSize.y;
b.e[2] = obb2.halfSize.z;
obb2.rotation.extractBasis(b.u[0], b.u[1], b.u[2]);
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
R[i][j] = a.u[i].dot(b.u[j]);
}
}
v1.subVectors(b.c, a.c);
t[0] = v1.dot(a.u[0]);
t[1] = v1.dot(a.u[1]);
t[2] = v1.dot(a.u[2]);
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
AbsR[i][j] = Math.abs(R[i][j]) + epsilon;
}
}
let ra, rb;
for (let i = 0; i < 3; i++) {
ra = a.e[i];
rb = b.e[0] * AbsR[i][0] + b.e[1] * AbsR[i][1] + b.e[2] * AbsR[i][2];
if (Math.abs(t[i]) > ra + rb)
return false;
}
for (let i = 0; i < 3; i++) {
ra = a.e[0] * AbsR[0][i] + a.e[1] * AbsR[1][i] + a.e[2] * AbsR[2][i];
rb = b.e[i];
if (Math.abs(t[0] * R[0][i] + t[1] * R[1][i] + t[2] * R[2][i]) > ra + rb)
return false;
}
ra = a.e[1] * AbsR[2][0] + a.e[2] * AbsR[1][0];
rb = b.e[1] * AbsR[0][2] + b.e[2] * AbsR[0][1];
if (Math.abs(t[2] * R[1][0] - t[1] * R[2][0]) > ra + rb)
return false;
ra = a.e[1] * AbsR[2][1] + a.e[2] * AbsR[1][1];
rb = b.e[0] * AbsR[0][2] + b.e[2] * AbsR[0][0];
if (Math.abs(t[2] * R[1][1] - t[1] * R[2][1]) > ra + rb)
return false;
ra = a.e[1] * AbsR[2][2] + a.e[2] * AbsR[1][2];
rb = b.e[0] * AbsR[0][1] + b.e[1] * AbsR[0][0];
if (Math.abs(t[2] * R[1][2] - t[1] * R[2][2]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][0] + a.e[2] * AbsR[0][0];
rb = b.e[1] * AbsR[1][2] + b.e[2] * AbsR[1][1];
if (Math.abs(t[0] * R[2][0] - t[2] * R[0][0]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][1] + a.e[2] * AbsR[0][1];
rb = b.e[0] * AbsR[1][2] + b.e[2] * AbsR[1][0];
if (Math.abs(t[0] * R[2][1] - t[2] * R[0][1]) > ra + rb)
return false;
ra = a.e[0] * AbsR[2][2] + a.e[2] * AbsR[0][2];
rb = b.e[0] * AbsR[1][1] + b.e[1] * AbsR[1][0];
if (Math.abs(t[0] * R[2][2] - t[2] * R[0][2]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][0] + a.e[1] * AbsR[0][0];
rb = b.e[1] * AbsR[2][2] + b.e[2] * AbsR[2][1];
if (Math.abs(t[1] * R[0][0] - t[0] * R[1][0]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][1] + a.e[1] * AbsR[0][1];
rb = b.e[0] * AbsR[2][2] + b.e[2] * AbsR[2][0];
if (Math.abs(t[1] * R[0][1] - t[0] * R[1][1]) > ra + rb)
return false;
ra = a.e[0] * AbsR[1][2] + a.e[1] * AbsR[0][2];
rb = b.e[0] * AbsR[2][1] + b.e[1] * AbsR[2][0];
if (Math.abs(t[1] * R[0][2] - t[0] * R[1][2]) > ra + rb)
return false;
return true;
}
/**
* Reference: Testing Box Against Plane in Real-Time Collision Detection
* by Christer Ericson (chapter 5.2.3)
*/
intersectsPlane(plane) {
this.rotation.extractBasis(xAxis, yAxis, zAxis);
const r = this.halfSize.x * Math.abs(plane.normal.dot(xAxis)) + this.halfSize.y * Math.abs(plane.normal.dot(yAxis)) + this.halfSize.z * Math.abs(plane.normal.dot(zAxis));
const d = plane.normal.dot(this.center) - plane.constant;
return Math.abs(d) <= r;
}
/**
* Performs a ray/OBB intersection test and stores the intersection point
* to the given 3D vector. If no intersection is detected, *null* is returned.
*/
intersectRay(ray, result) {
this.getSize(size);
aabb.setFromCenterAndSize(v1.set(0, 0, 0), size);
matrix.setFromMatrix3(this.rotation);
matrix.setPosition(this.center);
inverse.copy(matrix).invert();
localRay.copy(ray).applyMatrix4(inverse);
if (localRay.intersectBox(aabb, result)) {
return result.applyMatrix4(matrix);
} else {
return null;
}
}
/**
* Performs a ray/OBB intersection test. Returns either true or false if
* there is a intersection or not.
*/
intersectsRay(ray) {
return this.intersectRay(ray, v1) !== null;
}
fromBox3(box3) {
box3.getCenter(this.center);
box3.getSize(this.halfSize).multiplyScalar(0.5);
this.rotation.identity();
return this;
}
equals(obb2) {
return obb2.center.equals(this.center) && obb2.halfSize.equals(this.halfSize) && obb2.rotation.equals(this.rotation);
}
applyMatrix4(matrix2) {
const e = matrix2.elements;
let sx = v1.set(e[0], e[1], e[2]).length();
const sy = v1.set(e[4], e[5], e[6]).length();
const sz = v1.set(e[8], e[9], e[10]).length();
const det = matrix2.determinant();
if (det < 0)
sx = -sx;
rotationMatrix.setFromMatrix4(matrix2);
const invSX = 1 / sx;
const invSY = 1 / sy;
const invSZ = 1 / sz;
rotationMatrix.elements[0] *= invSX;
rotationMatrix.elements[1] *= invSX;
rotationMatrix.elements[2] *= invSX;
rotationMatrix.elements[3] *= invSY;
rotationMatrix.elements[4] *= invSY;
rotationMatrix.elements[5] *= invSY;
rotationMatrix.elements[6] *= invSZ;
rotationMatrix.elements[7] *= invSZ;
rotationMatrix.elements[8] *= invSZ;
this.rotation.multiply(rotationMatrix);
this.halfSize.x *= sx;
this.halfSize.y *= sy;
this.halfSize.z *= sz;
v1.setFromMatrixPosition(matrix2);
this.center.add(v1);
return this;
}
}
const obb = /* @__PURE__ */ new OBB();
export {
OBB
};
//# sourceMappingURL=OBB.js.map
+1
View File
File diff suppressed because one or more lines are too long
+274
View File
@@ -0,0 +1,274 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const Capsule = require("./Capsule.cjs");
const _v1 = /* @__PURE__ */ new THREE.Vector3();
const _v2 = /* @__PURE__ */ new THREE.Vector3();
const _plane = /* @__PURE__ */ new THREE.Plane();
const _line1 = /* @__PURE__ */ new THREE.Line3();
const _line2 = /* @__PURE__ */ new THREE.Line3();
const _sphere = /* @__PURE__ */ new THREE.Sphere();
const _capsule = /* @__PURE__ */ new Capsule.Capsule();
class Octree {
constructor(box) {
this.triangles = [];
this.box = box;
this.subTrees = [];
}
addTriangle(triangle) {
if (!this.bounds)
this.bounds = new THREE.Box3();
this.bounds.min.x = Math.min(this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x);
this.bounds.min.y = Math.min(this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y);
this.bounds.min.z = Math.min(this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z);
this.bounds.max.x = Math.max(this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x);
this.bounds.max.y = Math.max(this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y);
this.bounds.max.z = Math.max(this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z);
this.triangles.push(triangle);
return this;
}
calcBox() {
this.box = this.bounds.clone();
this.box.min.x -= 0.01;
this.box.min.y -= 0.01;
this.box.min.z -= 0.01;
return this;
}
split(level) {
if (!this.box)
return;
const subTrees = [];
const halfsize = _v2.copy(this.box.max).sub(this.box.min).multiplyScalar(0.5);
for (let x = 0; x < 2; x++) {
for (let y = 0; y < 2; y++) {
for (let z = 0; z < 2; z++) {
const box = new THREE.Box3();
const v = _v1.set(x, y, z);
box.min.copy(this.box.min).add(v.multiply(halfsize));
box.max.copy(box.min).add(halfsize);
subTrees.push(new Octree(box));
}
}
}
let triangle;
while (triangle = this.triangles.pop()) {
for (let i = 0; i < subTrees.length; i++) {
if (subTrees[i].box.intersectsTriangle(triangle)) {
subTrees[i].triangles.push(triangle);
}
}
}
for (let i = 0; i < subTrees.length; i++) {
const len = subTrees[i].triangles.length;
if (len > 8 && level < 16) {
subTrees[i].split(level + 1);
}
if (len !== 0) {
this.subTrees.push(subTrees[i]);
}
}
return this;
}
build() {
this.calcBox();
this.split(0);
return this;
}
getRayTriangles(ray, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!ray.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getRayTriangles(ray, triangles);
}
}
return triangles;
}
triangleCapsuleIntersect(capsule, triangle) {
triangle.getPlane(_plane);
const d1 = _plane.distanceToPoint(capsule.start) - capsule.radius;
const d2 = _plane.distanceToPoint(capsule.end) - capsule.radius;
if (d1 > 0 && d2 > 0 || d1 < -capsule.radius && d2 < -capsule.radius) {
return false;
}
const delta = Math.abs(d1 / (Math.abs(d1) + Math.abs(d2)));
const intersectPoint = _v1.copy(capsule.start).lerp(capsule.end, delta);
if (triangle.containsPoint(intersectPoint)) {
return { normal: _plane.normal.clone(), point: intersectPoint.clone(), depth: Math.abs(Math.min(d1, d2)) };
}
const r2 = capsule.radius * capsule.radius;
const line1 = _line1.set(capsule.start, capsule.end);
const lines = [
[triangle.a, triangle.b],
[triangle.b, triangle.c],
[triangle.c, triangle.a]
];
for (let i = 0; i < lines.length; i++) {
const line2 = _line2.set(lines[i][0], lines[i][1]);
const [point1, point2] = capsule.lineLineMinimumPoints(line1, line2);
if (point1.distanceToSquared(point2) < r2) {
return {
normal: point1.clone().sub(point2).normalize(),
point: point2.clone(),
depth: capsule.radius - point1.distanceTo(point2)
};
}
}
return false;
}
triangleSphereIntersect(sphere, triangle) {
triangle.getPlane(_plane);
if (!sphere.intersectsPlane(_plane))
return false;
const depth = Math.abs(_plane.distanceToSphere(sphere));
const r2 = sphere.radius * sphere.radius - depth * depth;
const plainPoint = _plane.projectPoint(sphere.center, _v1);
if (triangle.containsPoint(sphere.center)) {
return {
normal: _plane.normal.clone(),
point: plainPoint.clone(),
depth: Math.abs(_plane.distanceToSphere(sphere))
};
}
const lines = [
[triangle.a, triangle.b],
[triangle.b, triangle.c],
[triangle.c, triangle.a]
];
for (let i = 0; i < lines.length; i++) {
_line1.set(lines[i][0], lines[i][1]);
_line1.closestPointToPoint(plainPoint, true, _v2);
const d = _v2.distanceToSquared(sphere.center);
if (d < r2) {
return {
normal: sphere.center.clone().sub(_v2).normalize(),
point: _v2.clone(),
depth: sphere.radius - Math.sqrt(d)
};
}
}
return false;
}
getSphereTriangles(sphere, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!sphere.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getSphereTriangles(sphere, triangles);
}
}
}
getCapsuleTriangles(capsule, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!capsule.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getCapsuleTriangles(capsule, triangles);
}
}
}
sphereIntersect(sphere) {
_sphere.copy(sphere);
const triangles = [];
let result, hit = false;
this.getSphereTriangles(sphere, triangles);
for (let i = 0; i < triangles.length; i++) {
if (result = this.triangleSphereIntersect(_sphere, triangles[i])) {
hit = true;
_sphere.center.add(result.normal.multiplyScalar(result.depth));
}
}
if (hit) {
const collisionVector = _sphere.center.clone().sub(sphere.center);
const depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth };
}
return false;
}
capsuleIntersect(capsule) {
_capsule.copy(capsule);
const triangles = [];
let result, hit = false;
this.getCapsuleTriangles(_capsule, triangles);
for (let i = 0; i < triangles.length; i++) {
if (result = this.triangleCapsuleIntersect(_capsule, triangles[i])) {
hit = true;
_capsule.translate(result.normal.multiplyScalar(result.depth));
}
}
if (hit) {
const collisionVector = _capsule.getCenter(new THREE.Vector3()).sub(capsule.getCenter(_v1));
const depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth };
}
return false;
}
rayIntersect(ray) {
if (ray.direction.length() === 0)
return;
const triangles = [];
let triangle, position, distance = 1e100;
this.getRayTriangles(ray, triangles);
for (let i = 0; i < triangles.length; i++) {
const result = ray.intersectTriangle(triangles[i].a, triangles[i].b, triangles[i].c, true, _v1);
if (result) {
const newdistance = result.sub(ray.origin).length();
if (distance > newdistance) {
position = result.clone().add(ray.origin);
distance = newdistance;
triangle = triangles[i];
}
}
}
return distance < 1e100 ? { distance, triangle, position } : false;
}
fromGraphNode(group) {
group.updateWorldMatrix(true, true);
group.traverse((obj) => {
if (obj.isMesh === true) {
let geometry, isTemp = false;
if (obj.geometry.index !== null) {
isTemp = true;
geometry = obj.geometry.toNonIndexed();
} else {
geometry = obj.geometry;
}
const positionAttribute = geometry.getAttribute("position");
for (let i = 0; i < positionAttribute.count; i += 3) {
const v1 = new THREE.Vector3().fromBufferAttribute(positionAttribute, i);
const v2 = new THREE.Vector3().fromBufferAttribute(positionAttribute, i + 1);
const v3 = new THREE.Vector3().fromBufferAttribute(positionAttribute, i + 2);
v1.applyMatrix4(obj.matrixWorld);
v2.applyMatrix4(obj.matrixWorld);
v3.applyMatrix4(obj.matrixWorld);
this.addTriangle(new THREE.Triangle(v1, v2, v3));
}
if (isTemp) {
geometry.dispose();
}
}
});
this.build();
return this;
}
}
exports.Octree = Octree;
//# sourceMappingURL=Octree.cjs.map
File diff suppressed because one or more lines are too long
+24
View File
@@ -0,0 +1,24 @@
import { Triangle, Box3, Ray, Sphere, Object3D } from 'three'
import { Capsule } from './Capsule'
export class Octree {
constructor(box?: Box3)
triangles: Triangle[]
box: Box3
subTrees: Octree[]
addTriangle(triangle: Triangle): this
calcBox(): this
split(level: number): this
build(): this
getRayTriangles(ray: Ray, triangles: Triangle[]): Triangle[]
triangleCapsuleIntersect(capsule: Capsule, triangle: Triangle): any
triangleSphereIntersect(sphere: Sphere, triangle: Triangle): any
getSphereTriangles(sphere: Sphere, triangles: Triangle[]): Triangle[]
getCapsuleTriangles(capsule: Capsule, triangles: Triangle[]): Triangle[]
sphereIntersect(sphere: Sphere): any
capsuleIntersect(capsule: Capsule): any
rayIntersect(ray: Ray): any
fromGraphNode(group: Object3D): this
}
+274
View File
@@ -0,0 +1,274 @@
import { Box3, Vector3, Triangle, Plane, Line3, Sphere } from "three";
import { Capsule } from "./Capsule.js";
const _v1 = /* @__PURE__ */ new Vector3();
const _v2 = /* @__PURE__ */ new Vector3();
const _plane = /* @__PURE__ */ new Plane();
const _line1 = /* @__PURE__ */ new Line3();
const _line2 = /* @__PURE__ */ new Line3();
const _sphere = /* @__PURE__ */ new Sphere();
const _capsule = /* @__PURE__ */ new Capsule();
class Octree {
constructor(box) {
this.triangles = [];
this.box = box;
this.subTrees = [];
}
addTriangle(triangle) {
if (!this.bounds)
this.bounds = new Box3();
this.bounds.min.x = Math.min(this.bounds.min.x, triangle.a.x, triangle.b.x, triangle.c.x);
this.bounds.min.y = Math.min(this.bounds.min.y, triangle.a.y, triangle.b.y, triangle.c.y);
this.bounds.min.z = Math.min(this.bounds.min.z, triangle.a.z, triangle.b.z, triangle.c.z);
this.bounds.max.x = Math.max(this.bounds.max.x, triangle.a.x, triangle.b.x, triangle.c.x);
this.bounds.max.y = Math.max(this.bounds.max.y, triangle.a.y, triangle.b.y, triangle.c.y);
this.bounds.max.z = Math.max(this.bounds.max.z, triangle.a.z, triangle.b.z, triangle.c.z);
this.triangles.push(triangle);
return this;
}
calcBox() {
this.box = this.bounds.clone();
this.box.min.x -= 0.01;
this.box.min.y -= 0.01;
this.box.min.z -= 0.01;
return this;
}
split(level) {
if (!this.box)
return;
const subTrees = [];
const halfsize = _v2.copy(this.box.max).sub(this.box.min).multiplyScalar(0.5);
for (let x = 0; x < 2; x++) {
for (let y = 0; y < 2; y++) {
for (let z = 0; z < 2; z++) {
const box = new Box3();
const v = _v1.set(x, y, z);
box.min.copy(this.box.min).add(v.multiply(halfsize));
box.max.copy(box.min).add(halfsize);
subTrees.push(new Octree(box));
}
}
}
let triangle;
while (triangle = this.triangles.pop()) {
for (let i = 0; i < subTrees.length; i++) {
if (subTrees[i].box.intersectsTriangle(triangle)) {
subTrees[i].triangles.push(triangle);
}
}
}
for (let i = 0; i < subTrees.length; i++) {
const len = subTrees[i].triangles.length;
if (len > 8 && level < 16) {
subTrees[i].split(level + 1);
}
if (len !== 0) {
this.subTrees.push(subTrees[i]);
}
}
return this;
}
build() {
this.calcBox();
this.split(0);
return this;
}
getRayTriangles(ray, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!ray.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getRayTriangles(ray, triangles);
}
}
return triangles;
}
triangleCapsuleIntersect(capsule, triangle) {
triangle.getPlane(_plane);
const d1 = _plane.distanceToPoint(capsule.start) - capsule.radius;
const d2 = _plane.distanceToPoint(capsule.end) - capsule.radius;
if (d1 > 0 && d2 > 0 || d1 < -capsule.radius && d2 < -capsule.radius) {
return false;
}
const delta = Math.abs(d1 / (Math.abs(d1) + Math.abs(d2)));
const intersectPoint = _v1.copy(capsule.start).lerp(capsule.end, delta);
if (triangle.containsPoint(intersectPoint)) {
return { normal: _plane.normal.clone(), point: intersectPoint.clone(), depth: Math.abs(Math.min(d1, d2)) };
}
const r2 = capsule.radius * capsule.radius;
const line1 = _line1.set(capsule.start, capsule.end);
const lines = [
[triangle.a, triangle.b],
[triangle.b, triangle.c],
[triangle.c, triangle.a]
];
for (let i = 0; i < lines.length; i++) {
const line2 = _line2.set(lines[i][0], lines[i][1]);
const [point1, point2] = capsule.lineLineMinimumPoints(line1, line2);
if (point1.distanceToSquared(point2) < r2) {
return {
normal: point1.clone().sub(point2).normalize(),
point: point2.clone(),
depth: capsule.radius - point1.distanceTo(point2)
};
}
}
return false;
}
triangleSphereIntersect(sphere, triangle) {
triangle.getPlane(_plane);
if (!sphere.intersectsPlane(_plane))
return false;
const depth = Math.abs(_plane.distanceToSphere(sphere));
const r2 = sphere.radius * sphere.radius - depth * depth;
const plainPoint = _plane.projectPoint(sphere.center, _v1);
if (triangle.containsPoint(sphere.center)) {
return {
normal: _plane.normal.clone(),
point: plainPoint.clone(),
depth: Math.abs(_plane.distanceToSphere(sphere))
};
}
const lines = [
[triangle.a, triangle.b],
[triangle.b, triangle.c],
[triangle.c, triangle.a]
];
for (let i = 0; i < lines.length; i++) {
_line1.set(lines[i][0], lines[i][1]);
_line1.closestPointToPoint(plainPoint, true, _v2);
const d = _v2.distanceToSquared(sphere.center);
if (d < r2) {
return {
normal: sphere.center.clone().sub(_v2).normalize(),
point: _v2.clone(),
depth: sphere.radius - Math.sqrt(d)
};
}
}
return false;
}
getSphereTriangles(sphere, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!sphere.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getSphereTriangles(sphere, triangles);
}
}
}
getCapsuleTriangles(capsule, triangles) {
for (let i = 0; i < this.subTrees.length; i++) {
const subTree = this.subTrees[i];
if (!capsule.intersectsBox(subTree.box))
continue;
if (subTree.triangles.length > 0) {
for (let j = 0; j < subTree.triangles.length; j++) {
if (triangles.indexOf(subTree.triangles[j]) === -1)
triangles.push(subTree.triangles[j]);
}
} else {
subTree.getCapsuleTriangles(capsule, triangles);
}
}
}
sphereIntersect(sphere) {
_sphere.copy(sphere);
const triangles = [];
let result, hit = false;
this.getSphereTriangles(sphere, triangles);
for (let i = 0; i < triangles.length; i++) {
if (result = this.triangleSphereIntersect(_sphere, triangles[i])) {
hit = true;
_sphere.center.add(result.normal.multiplyScalar(result.depth));
}
}
if (hit) {
const collisionVector = _sphere.center.clone().sub(sphere.center);
const depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth };
}
return false;
}
capsuleIntersect(capsule) {
_capsule.copy(capsule);
const triangles = [];
let result, hit = false;
this.getCapsuleTriangles(_capsule, triangles);
for (let i = 0; i < triangles.length; i++) {
if (result = this.triangleCapsuleIntersect(_capsule, triangles[i])) {
hit = true;
_capsule.translate(result.normal.multiplyScalar(result.depth));
}
}
if (hit) {
const collisionVector = _capsule.getCenter(new Vector3()).sub(capsule.getCenter(_v1));
const depth = collisionVector.length();
return { normal: collisionVector.normalize(), depth };
}
return false;
}
rayIntersect(ray) {
if (ray.direction.length() === 0)
return;
const triangles = [];
let triangle, position, distance = 1e100;
this.getRayTriangles(ray, triangles);
for (let i = 0; i < triangles.length; i++) {
const result = ray.intersectTriangle(triangles[i].a, triangles[i].b, triangles[i].c, true, _v1);
if (result) {
const newdistance = result.sub(ray.origin).length();
if (distance > newdistance) {
position = result.clone().add(ray.origin);
distance = newdistance;
triangle = triangles[i];
}
}
}
return distance < 1e100 ? { distance, triangle, position } : false;
}
fromGraphNode(group) {
group.updateWorldMatrix(true, true);
group.traverse((obj) => {
if (obj.isMesh === true) {
let geometry, isTemp = false;
if (obj.geometry.index !== null) {
isTemp = true;
geometry = obj.geometry.toNonIndexed();
} else {
geometry = obj.geometry;
}
const positionAttribute = geometry.getAttribute("position");
for (let i = 0; i < positionAttribute.count; i += 3) {
const v1 = new Vector3().fromBufferAttribute(positionAttribute, i);
const v2 = new Vector3().fromBufferAttribute(positionAttribute, i + 1);
const v3 = new Vector3().fromBufferAttribute(positionAttribute, i + 2);
v1.applyMatrix4(obj.matrixWorld);
v2.applyMatrix4(obj.matrixWorld);
v3.applyMatrix4(obj.matrixWorld);
this.addTriangle(new Triangle(v1, v2, v3));
}
if (isTemp) {
geometry.dispose();
}
}
});
this.build();
return this;
}
}
export {
Octree
};
//# sourceMappingURL=Octree.js.map
+1
View File
File diff suppressed because one or more lines are too long
+441
View File
@@ -0,0 +1,441 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class SimplexNoise {
/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
*/
constructor(r = Math) {
__publicField(this, "grad3", [
[1, 1, 0],
[-1, 1, 0],
[1, -1, 0],
[-1, -1, 0],
[1, 0, 1],
[-1, 0, 1],
[1, 0, -1],
[-1, 0, -1],
[0, 1, 1],
[0, -1, 1],
[0, 1, -1],
[0, -1, -1]
]);
__publicField(this, "grad4", [
[0, 1, 1, 1],
[0, 1, 1, -1],
[0, 1, -1, 1],
[0, 1, -1, -1],
[0, -1, 1, 1],
[0, -1, 1, -1],
[0, -1, -1, 1],
[0, -1, -1, -1],
[1, 0, 1, 1],
[1, 0, 1, -1],
[1, 0, -1, 1],
[1, 0, -1, -1],
[-1, 0, 1, 1],
[-1, 0, 1, -1],
[-1, 0, -1, 1],
[-1, 0, -1, -1],
[1, 1, 0, 1],
[1, 1, 0, -1],
[1, -1, 0, 1],
[1, -1, 0, -1],
[-1, 1, 0, 1],
[-1, 1, 0, -1],
[-1, -1, 0, 1],
[-1, -1, 0, -1],
[1, 1, 1, 0],
[1, 1, -1, 0],
[1, -1, 1, 0],
[1, -1, -1, 0],
[-1, 1, 1, 0],
[-1, 1, -1, 0],
[-1, -1, 1, 0],
[-1, -1, -1, 0]
]);
__publicField(this, "p", []);
// To remove the need for index wrapping, double the permutation table length
__publicField(this, "perm", []);
// A lookup table to traverse the simplex around a given point in 4D.
// Details can be found where this table is used, in the 4D noise method.
__publicField(this, "simplex", [
[0, 1, 2, 3],
[0, 1, 3, 2],
[0, 0, 0, 0],
[0, 2, 3, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 2, 3, 0],
[0, 2, 1, 3],
[0, 0, 0, 0],
[0, 3, 1, 2],
[0, 3, 2, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 3, 2, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 2, 0, 3],
[0, 0, 0, 0],
[1, 3, 0, 2],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 3, 0, 1],
[2, 3, 1, 0],
[1, 0, 2, 3],
[1, 0, 3, 2],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 0, 3, 1],
[0, 0, 0, 0],
[2, 1, 3, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 0, 1, 3],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[3, 0, 1, 2],
[3, 0, 2, 1],
[0, 0, 0, 0],
[3, 1, 2, 0],
[2, 1, 0, 3],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[3, 1, 0, 2],
[0, 0, 0, 0],
[3, 2, 0, 1],
[3, 2, 1, 0]
]);
__publicField(this, "dot", (g, x, y) => {
return g[0] * x + g[1] * y;
});
__publicField(this, "dot3", (g, x, y, z) => {
return g[0] * x + g[1] * y + g[2] * z;
});
__publicField(this, "dot4", (g, x, y, z, w) => {
return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
});
__publicField(this, "noise", (xin, yin) => {
let n0;
let n1;
let n2;
const F2 = 0.5 * (Math.sqrt(3) - 1);
const s = (xin + yin) * F2;
const i = Math.floor(xin + s);
const j = Math.floor(yin + s);
const G2 = (3 - Math.sqrt(3)) / 6;
const t = (i + j) * G2;
const X0 = i - t;
const Y0 = j - t;
const x0 = xin - X0;
const y0 = yin - Y0;
let i1 = 0;
let j1 = 1;
if (x0 > y0) {
i1 = 1;
j1 = 0;
}
const x1 = x0 - i1 + G2;
const y1 = y0 - j1 + G2;
const x2 = x0 - 1 + 2 * G2;
const y2 = y0 - 1 + 2 * G2;
const ii = i & 255;
const jj = j & 255;
const gi0 = this.perm[ii + this.perm[jj]] % 12;
const gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12;
const gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12;
let t0 = 0.5 - x0 * x0 - y0 * y0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0);
}
let t1 = 0.5 - x1 * x1 - y1 * y1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
}
let t2 = 0.5 - x2 * x2 - y2 * y2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
}
return 70 * (n0 + n1 + n2);
});
// 3D simplex noise
__publicField(this, "noise3d", (xin, yin, zin) => {
let n0;
let n1;
let n2;
let n3;
const F3 = 1 / 3;
const s = (xin + yin + zin) * F3;
const i = Math.floor(xin + s);
const j = Math.floor(yin + s);
const k = Math.floor(zin + s);
const G3 = 1 / 6;
const t = (i + j + k) * G3;
const X0 = i - t;
const Y0 = j - t;
const Z0 = k - t;
const x0 = xin - X0;
const y0 = yin - Y0;
const z0 = zin - Z0;
let i1;
let j1;
let k1;
let i2;
let j2;
let k2;
if (x0 >= y0) {
if (y0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} else if (x0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
} else {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
} else {
if (y0 < z0) {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
} else if (x0 < z0) {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
} else {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
const x1 = x0 - i1 + G3;
const y1 = y0 - j1 + G3;
const z1 = z0 - k1 + G3;
const x2 = x0 - i2 + 2 * G3;
const y2 = y0 - j2 + 2 * G3;
const z2 = z0 - k2 + 2 * G3;
const x3 = x0 - 1 + 3 * G3;
const y3 = y0 - 1 + 3 * G3;
const z3 = z0 - 1 + 3 * G3;
const ii = i & 255;
const jj = j & 255;
const kk = k & 255;
const gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12;
const gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12;
const gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12;
const gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12;
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0);
}
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1);
}
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2);
}
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
if (t3 < 0) {
n3 = 0;
} else {
t3 *= t3;
n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3);
}
return 32 * (n0 + n1 + n2 + n3);
});
// 4D simplex noise
__publicField(this, "noise4d", (x, y, z, w) => {
const grad4 = this.grad4;
const simplex = this.simplex;
const perm = this.perm;
const F4 = (Math.sqrt(5) - 1) / 4;
const G4 = (5 - Math.sqrt(5)) / 20;
let n0;
let n1;
let n2;
let n3;
let n4;
const s = (x + y + z + w) * F4;
const i = Math.floor(x + s);
const j = Math.floor(y + s);
const k = Math.floor(z + s);
const l = Math.floor(w + s);
const t = (i + j + k + l) * G4;
const X0 = i - t;
const Y0 = j - t;
const Z0 = k - t;
const W0 = l - t;
const x0 = x - X0;
const y0 = y - Y0;
const z0 = z - Z0;
const w0 = w - W0;
const c1 = x0 > y0 ? 32 : 0;
const c2 = x0 > z0 ? 16 : 0;
const c3 = y0 > z0 ? 8 : 0;
const c4 = x0 > w0 ? 4 : 0;
const c5 = y0 > w0 ? 2 : 0;
const c6 = z0 > w0 ? 1 : 0;
const c = c1 + c2 + c3 + c4 + c5 + c6;
let i1;
let j1;
let k1;
let l1;
let i2;
let j2;
let k2;
let l2;
let i3;
let j3;
let k3;
let l3;
i1 = simplex[c][0] >= 3 ? 1 : 0;
j1 = simplex[c][1] >= 3 ? 1 : 0;
k1 = simplex[c][2] >= 3 ? 1 : 0;
l1 = simplex[c][3] >= 3 ? 1 : 0;
i2 = simplex[c][0] >= 2 ? 1 : 0;
j2 = simplex[c][1] >= 2 ? 1 : 0;
k2 = simplex[c][2] >= 2 ? 1 : 0;
l2 = simplex[c][3] >= 2 ? 1 : 0;
i3 = simplex[c][0] >= 1 ? 1 : 0;
j3 = simplex[c][1] >= 1 ? 1 : 0;
k3 = simplex[c][2] >= 1 ? 1 : 0;
l3 = simplex[c][3] >= 1 ? 1 : 0;
const x1 = x0 - i1 + G4;
const y1 = y0 - j1 + G4;
const z1 = z0 - k1 + G4;
const w1 = w0 - l1 + G4;
const x2 = x0 - i2 + 2 * G4;
const y2 = y0 - j2 + 2 * G4;
const z2 = z0 - k2 + 2 * G4;
const w2 = w0 - l2 + 2 * G4;
const x3 = x0 - i3 + 3 * G4;
const y3 = y0 - j3 + 3 * G4;
const z3 = z0 - k3 + 3 * G4;
const w3 = w0 - l3 + 3 * G4;
const x4 = x0 - 1 + 4 * G4;
const y4 = y0 - 1 + 4 * G4;
const z4 = z0 - 1 + 4 * G4;
const w4 = w0 - 1 + 4 * G4;
const ii = i & 255;
const jj = j & 255;
const kk = k & 255;
const ll = l & 255;
const gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
const gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
const gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
const gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
const gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
}
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
}
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
}
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
if (t3 < 0) {
n3 = 0;
} else {
t3 *= t3;
n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
}
let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
if (t4 < 0) {
n4 = 0;
} else {
t4 *= t4;
n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
}
return 27 * (n0 + n1 + n2 + n3 + n4);
});
for (let i = 0; i < 256; i++) {
this.p[i] = Math.floor(r.random() * 256);
}
for (let i = 0; i < 512; i++) {
this.perm[i] = this.p[i & 255];
}
}
}
exports.SimplexNoise = SimplexNoise;
//# sourceMappingURL=SimplexNoise.cjs.map
File diff suppressed because one or more lines are too long
+21
View File
@@ -0,0 +1,21 @@
export interface NumberGenerator {
random: () => number;
}
export declare class SimplexNoise {
private grad3;
private grad4;
private p;
private perm;
private simplex;
/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
*/
constructor(r?: NumberGenerator);
dot: (g: number[], x: number, y: number) => number;
dot3: (g: number[], x: number, y: number, z: number) => number;
dot4: (g: number[], x: number, y: number, z: number, w: number) => number;
noise: (xin: number, yin: number) => number;
private noise3d;
noise4d: (x: number, y: number, z: number, w: number) => number;
}
+441
View File
@@ -0,0 +1,441 @@
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class SimplexNoise {
/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
*/
constructor(r = Math) {
__publicField(this, "grad3", [
[1, 1, 0],
[-1, 1, 0],
[1, -1, 0],
[-1, -1, 0],
[1, 0, 1],
[-1, 0, 1],
[1, 0, -1],
[-1, 0, -1],
[0, 1, 1],
[0, -1, 1],
[0, 1, -1],
[0, -1, -1]
]);
__publicField(this, "grad4", [
[0, 1, 1, 1],
[0, 1, 1, -1],
[0, 1, -1, 1],
[0, 1, -1, -1],
[0, -1, 1, 1],
[0, -1, 1, -1],
[0, -1, -1, 1],
[0, -1, -1, -1],
[1, 0, 1, 1],
[1, 0, 1, -1],
[1, 0, -1, 1],
[1, 0, -1, -1],
[-1, 0, 1, 1],
[-1, 0, 1, -1],
[-1, 0, -1, 1],
[-1, 0, -1, -1],
[1, 1, 0, 1],
[1, 1, 0, -1],
[1, -1, 0, 1],
[1, -1, 0, -1],
[-1, 1, 0, 1],
[-1, 1, 0, -1],
[-1, -1, 0, 1],
[-1, -1, 0, -1],
[1, 1, 1, 0],
[1, 1, -1, 0],
[1, -1, 1, 0],
[1, -1, -1, 0],
[-1, 1, 1, 0],
[-1, 1, -1, 0],
[-1, -1, 1, 0],
[-1, -1, -1, 0]
]);
__publicField(this, "p", []);
// To remove the need for index wrapping, double the permutation table length
__publicField(this, "perm", []);
// A lookup table to traverse the simplex around a given point in 4D.
// Details can be found where this table is used, in the 4D noise method.
__publicField(this, "simplex", [
[0, 1, 2, 3],
[0, 1, 3, 2],
[0, 0, 0, 0],
[0, 2, 3, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 2, 3, 0],
[0, 2, 1, 3],
[0, 0, 0, 0],
[0, 3, 1, 2],
[0, 3, 2, 1],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 3, 2, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[1, 2, 0, 3],
[0, 0, 0, 0],
[1, 3, 0, 2],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 3, 0, 1],
[2, 3, 1, 0],
[1, 0, 2, 3],
[1, 0, 3, 2],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 0, 3, 1],
[0, 0, 0, 0],
[2, 1, 3, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[2, 0, 1, 3],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[3, 0, 1, 2],
[3, 0, 2, 1],
[0, 0, 0, 0],
[3, 1, 2, 0],
[2, 1, 0, 3],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[3, 1, 0, 2],
[0, 0, 0, 0],
[3, 2, 0, 1],
[3, 2, 1, 0]
]);
__publicField(this, "dot", (g, x, y) => {
return g[0] * x + g[1] * y;
});
__publicField(this, "dot3", (g, x, y, z) => {
return g[0] * x + g[1] * y + g[2] * z;
});
__publicField(this, "dot4", (g, x, y, z, w) => {
return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
});
__publicField(this, "noise", (xin, yin) => {
let n0;
let n1;
let n2;
const F2 = 0.5 * (Math.sqrt(3) - 1);
const s = (xin + yin) * F2;
const i = Math.floor(xin + s);
const j = Math.floor(yin + s);
const G2 = (3 - Math.sqrt(3)) / 6;
const t = (i + j) * G2;
const X0 = i - t;
const Y0 = j - t;
const x0 = xin - X0;
const y0 = yin - Y0;
let i1 = 0;
let j1 = 1;
if (x0 > y0) {
i1 = 1;
j1 = 0;
}
const x1 = x0 - i1 + G2;
const y1 = y0 - j1 + G2;
const x2 = x0 - 1 + 2 * G2;
const y2 = y0 - 1 + 2 * G2;
const ii = i & 255;
const jj = j & 255;
const gi0 = this.perm[ii + this.perm[jj]] % 12;
const gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12;
const gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12;
let t0 = 0.5 - x0 * x0 - y0 * y0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0);
}
let t1 = 0.5 - x1 * x1 - y1 * y1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
}
let t2 = 0.5 - x2 * x2 - y2 * y2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
}
return 70 * (n0 + n1 + n2);
});
// 3D simplex noise
__publicField(this, "noise3d", (xin, yin, zin) => {
let n0;
let n1;
let n2;
let n3;
const F3 = 1 / 3;
const s = (xin + yin + zin) * F3;
const i = Math.floor(xin + s);
const j = Math.floor(yin + s);
const k = Math.floor(zin + s);
const G3 = 1 / 6;
const t = (i + j + k) * G3;
const X0 = i - t;
const Y0 = j - t;
const Z0 = k - t;
const x0 = xin - X0;
const y0 = yin - Y0;
const z0 = zin - Z0;
let i1;
let j1;
let k1;
let i2;
let j2;
let k2;
if (x0 >= y0) {
if (y0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} else if (x0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
} else {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
}
} else {
if (y0 < z0) {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 0;
j2 = 1;
k2 = 1;
} else if (x0 < z0) {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 0;
j2 = 1;
k2 = 1;
} else {
i1 = 0;
j1 = 1;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
}
}
const x1 = x0 - i1 + G3;
const y1 = y0 - j1 + G3;
const z1 = z0 - k1 + G3;
const x2 = x0 - i2 + 2 * G3;
const y2 = y0 - j2 + 2 * G3;
const z2 = z0 - k2 + 2 * G3;
const x3 = x0 - 1 + 3 * G3;
const y3 = y0 - 1 + 3 * G3;
const z3 = z0 - 1 + 3 * G3;
const ii = i & 255;
const jj = j & 255;
const kk = k & 255;
const gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12;
const gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12;
const gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12;
const gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12;
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0);
}
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1);
}
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2);
}
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
if (t3 < 0) {
n3 = 0;
} else {
t3 *= t3;
n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3);
}
return 32 * (n0 + n1 + n2 + n3);
});
// 4D simplex noise
__publicField(this, "noise4d", (x, y, z, w) => {
const grad4 = this.grad4;
const simplex = this.simplex;
const perm = this.perm;
const F4 = (Math.sqrt(5) - 1) / 4;
const G4 = (5 - Math.sqrt(5)) / 20;
let n0;
let n1;
let n2;
let n3;
let n4;
const s = (x + y + z + w) * F4;
const i = Math.floor(x + s);
const j = Math.floor(y + s);
const k = Math.floor(z + s);
const l = Math.floor(w + s);
const t = (i + j + k + l) * G4;
const X0 = i - t;
const Y0 = j - t;
const Z0 = k - t;
const W0 = l - t;
const x0 = x - X0;
const y0 = y - Y0;
const z0 = z - Z0;
const w0 = w - W0;
const c1 = x0 > y0 ? 32 : 0;
const c2 = x0 > z0 ? 16 : 0;
const c3 = y0 > z0 ? 8 : 0;
const c4 = x0 > w0 ? 4 : 0;
const c5 = y0 > w0 ? 2 : 0;
const c6 = z0 > w0 ? 1 : 0;
const c = c1 + c2 + c3 + c4 + c5 + c6;
let i1;
let j1;
let k1;
let l1;
let i2;
let j2;
let k2;
let l2;
let i3;
let j3;
let k3;
let l3;
i1 = simplex[c][0] >= 3 ? 1 : 0;
j1 = simplex[c][1] >= 3 ? 1 : 0;
k1 = simplex[c][2] >= 3 ? 1 : 0;
l1 = simplex[c][3] >= 3 ? 1 : 0;
i2 = simplex[c][0] >= 2 ? 1 : 0;
j2 = simplex[c][1] >= 2 ? 1 : 0;
k2 = simplex[c][2] >= 2 ? 1 : 0;
l2 = simplex[c][3] >= 2 ? 1 : 0;
i3 = simplex[c][0] >= 1 ? 1 : 0;
j3 = simplex[c][1] >= 1 ? 1 : 0;
k3 = simplex[c][2] >= 1 ? 1 : 0;
l3 = simplex[c][3] >= 1 ? 1 : 0;
const x1 = x0 - i1 + G4;
const y1 = y0 - j1 + G4;
const z1 = z0 - k1 + G4;
const w1 = w0 - l1 + G4;
const x2 = x0 - i2 + 2 * G4;
const y2 = y0 - j2 + 2 * G4;
const z2 = z0 - k2 + 2 * G4;
const w2 = w0 - l2 + 2 * G4;
const x3 = x0 - i3 + 3 * G4;
const y3 = y0 - j3 + 3 * G4;
const z3 = z0 - k3 + 3 * G4;
const w3 = w0 - l3 + 3 * G4;
const x4 = x0 - 1 + 4 * G4;
const y4 = y0 - 1 + 4 * G4;
const z4 = z0 - 1 + 4 * G4;
const w4 = w0 - 1 + 4 * G4;
const ii = i & 255;
const jj = j & 255;
const kk = k & 255;
const ll = l & 255;
const gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
const gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
const gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
const gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
const gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
if (t0 < 0) {
n0 = 0;
} else {
t0 *= t0;
n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
}
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
if (t1 < 0) {
n1 = 0;
} else {
t1 *= t1;
n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
}
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
if (t2 < 0) {
n2 = 0;
} else {
t2 *= t2;
n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
}
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
if (t3 < 0) {
n3 = 0;
} else {
t3 *= t3;
n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
}
let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
if (t4 < 0) {
n4 = 0;
} else {
t4 *= t4;
n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
}
return 27 * (n0 + n1 + n2 + n3 + n4);
});
for (let i = 0; i < 256; i++) {
this.p[i] = Math.floor(r.random() * 256);
}
for (let i = 0; i < 512; i++) {
this.perm[i] = this.p[i & 255];
}
}
}
export {
SimplexNoise
};
//# sourceMappingURL=SimplexNoise.js.map
File diff suppressed because one or more lines are too long