@benev/math 0.1.0 → 0.2.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -23
- package/package.json +3 -1
- package/s/{concepts → core}/quat.ts +56 -16
- package/s/{concepts → core}/vec2.ts +52 -38
- package/s/{concepts → core}/vec3.ts +57 -47
- package/s/{concepts → core}/vec4.ts +13 -16
- package/s/index.ts +25 -10
- package/s/optimizers/hash-map.ts +71 -0
- package/s/optimizers/hash-set.ts +50 -0
- package/s/optimizers/zen.ts +151 -0
- package/s/physics/2d/collide2d.ts +51 -0
- package/s/physics/2d/intersect2d.ts +80 -0
- package/s/shapes/2d/circle.ts +43 -0
- package/s/shapes/2d/edge.ts +3 -0
- package/s/shapes/2d/index.ts +6 -0
- package/s/shapes/2d/pill.ts +3 -0
- package/s/shapes/2d/rect.ts +74 -0
- package/s/shapes/3d/box.ts +84 -0
- package/s/shapes/3d/capsule.ts +3 -0
- package/s/shapes/3d/index.ts +6 -0
- package/s/shapes/3d/segment.ts +48 -0
- package/s/shapes/3d/sphere.ts +3 -0
- package/s/tools/angles.ts +49 -0
- package/s/{concepts → tools}/circular.ts +5 -3
- package/s/{concepts → tools}/randy.ts +0 -14
- package/s/{concepts → tools}/scalar.ts +11 -11
- package/s/{concepts → tools}/spline.ts +11 -10
- package/x/{concepts → core}/quat.d.ts +10 -5
- package/x/{concepts → core}/quat.js +49 -12
- package/x/core/quat.js.map +1 -0
- package/x/{concepts → core}/vec2.d.ts +16 -17
- package/x/{concepts → core}/vec2.js +37 -21
- package/x/core/vec2.js.map +1 -0
- package/x/{concepts → core}/vec3.d.ts +19 -20
- package/x/{concepts → core}/vec3.js +46 -27
- package/x/core/vec3.js.map +1 -0
- package/x/{concepts → core}/vec4.d.ts +5 -7
- package/x/{concepts → core}/vec4.js +12 -12
- package/x/core/vec4.js.map +1 -0
- package/x/index.d.ts +21 -10
- package/x/index.js +21 -10
- package/x/index.js.map +1 -1
- package/x/optimizers/hash-map.d.ts +17 -0
- package/x/optimizers/hash-map.js +55 -0
- package/x/optimizers/hash-map.js.map +1 -0
- package/x/optimizers/hash-set.d.ts +13 -0
- package/x/optimizers/hash-set.js +39 -0
- package/x/optimizers/hash-set.js.map +1 -0
- package/x/optimizers/zen.d.ts +33 -0
- package/x/optimizers/zen.js +121 -0
- package/x/optimizers/zen.js.map +1 -0
- package/x/physics/2d/collide2d.d.ts +8 -0
- package/x/physics/2d/collide2d.js +36 -0
- package/x/physics/2d/collide2d.js.map +1 -0
- package/x/physics/2d/intersect2d.d.ts +13 -0
- package/x/physics/2d/intersect2d.js +57 -0
- package/x/physics/2d/intersect2d.js.map +1 -0
- package/x/shapes/2d/circle.d.ts +18 -0
- package/x/shapes/2d/circle.js +34 -0
- package/x/shapes/2d/circle.js.map +1 -0
- package/x/shapes/2d/edge.d.ts +1 -0
- package/x/shapes/2d/edge.js +3 -0
- package/x/shapes/2d/edge.js.map +1 -0
- package/x/shapes/2d/index.d.ts +4 -0
- package/x/shapes/2d/index.js +5 -0
- package/x/shapes/2d/index.js.map +1 -0
- package/x/shapes/2d/pill.d.ts +1 -0
- package/x/shapes/2d/pill.js +3 -0
- package/x/shapes/2d/pill.js.map +1 -0
- package/x/shapes/2d/rect.d.ts +23 -0
- package/x/shapes/2d/rect.js +59 -0
- package/x/shapes/2d/rect.js.map +1 -0
- package/x/shapes/3d/box.d.ts +24 -0
- package/x/shapes/3d/box.js +68 -0
- package/x/shapes/3d/box.js.map +1 -0
- package/x/shapes/3d/capsule.d.ts +1 -0
- package/x/shapes/3d/capsule.js +3 -0
- package/x/shapes/3d/capsule.js.map +1 -0
- package/x/shapes/3d/index.d.ts +4 -0
- package/x/shapes/3d/index.js +5 -0
- package/x/shapes/3d/index.js.map +1 -0
- package/x/shapes/3d/segment.d.ts +13 -0
- package/x/shapes/3d/segment.js +37 -0
- package/x/shapes/3d/segment.js.map +1 -0
- package/x/shapes/3d/sphere.d.ts +1 -0
- package/x/shapes/3d/sphere.js +3 -0
- package/x/shapes/3d/sphere.js.map +1 -0
- package/x/{concepts → tools}/angles.d.ts +3 -13
- package/x/tools/angles.js +41 -0
- package/x/tools/angles.js.map +1 -0
- package/x/{concepts → tools}/circular.js +4 -3
- package/x/tools/circular.js.map +1 -0
- package/x/tools/noise.js.map +1 -0
- package/x/{concepts → tools}/randy.d.ts +0 -8
- package/x/{concepts → tools}/randy.js +0 -10
- package/x/tools/randy.js.map +1 -0
- package/x/{concepts → tools}/scalar.d.ts +4 -4
- package/x/{concepts → tools}/scalar.js +11 -11
- package/x/tools/scalar.js.map +1 -0
- package/x/{concepts → tools}/spline.d.ts +3 -3
- package/x/{concepts → tools}/spline.js +3 -1
- package/x/tools/spline.js.map +1 -0
- package/s/concepts/angles.ts +0 -74
- package/x/concepts/angles.js +0 -62
- package/x/concepts/angles.js.map +0 -1
- package/x/concepts/circular.js.map +0 -1
- package/x/concepts/noise.js.map +0 -1
- package/x/concepts/quat.js.map +0 -1
- package/x/concepts/randy.js.map +0 -1
- package/x/concepts/scalar.js.map +0 -1
- package/x/concepts/spline.js.map +0 -1
- package/x/concepts/vec2.js.map +0 -1
- package/x/concepts/vec3.js.map +0 -1
- package/x/concepts/vec4.js.map +0 -1
- /package/s/{concepts → tools}/noise.ts +0 -0
- /package/x/{concepts → tools}/circular.d.ts +0 -0
- /package/x/{concepts → tools}/noise.d.ts +0 -0
- /package/x/{concepts → tools}/noise.js +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
import {Vec3, XyzArray, Xyz} from "../../core/vec3.js"
|
|
3
|
+
|
|
4
|
+
export type BoxJson = [min: XyzArray, max: XyzArray]
|
|
5
|
+
export type BoxLike = {min: Xyz, max: Xyz}
|
|
6
|
+
|
|
7
|
+
export class Box {
|
|
8
|
+
constructor(
|
|
9
|
+
public min: Vec3,
|
|
10
|
+
public max: Vec3,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
static from(data: BoxJson | BoxLike) {
|
|
14
|
+
return Array.isArray(data)
|
|
15
|
+
? new this(Vec3.from(data[0]), Vec3.from(data[1]))
|
|
16
|
+
: new this(Vec3.from(data.min), Vec3.from(data.max))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static fromCorner(min: Vec3, size: Vec3) {
|
|
20
|
+
return new this(min, min.clone().add(size))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static fromCenter(center: Vec3, size: Vec3) {
|
|
24
|
+
const halfSize = size.clone().half()
|
|
25
|
+
const min = center.clone().subtract(halfSize)
|
|
26
|
+
const max = center.clone().add(halfSize)
|
|
27
|
+
return new this(min, max)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
toJSON(): BoxJson {
|
|
31
|
+
return [this.min.toJSON(), this.max.toJSON()]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
clone() {
|
|
35
|
+
return new Box(this.min.clone(), this.max.clone())
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set(box: BoxLike) {
|
|
39
|
+
this.min.set(box.min)
|
|
40
|
+
this.max.set(box.max)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
size() {
|
|
44
|
+
return this.max.clone().subtract(this.min)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
center() {
|
|
48
|
+
return this.min.clone().add(this.size().half())
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
normalize() {
|
|
52
|
+
const {min, max} = this
|
|
53
|
+
this.min.set(Vec3.min(min, max))
|
|
54
|
+
this.max.set(Vec3.max(min, max))
|
|
55
|
+
return this
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
translate_(x: number, y: number, z: number) {
|
|
59
|
+
this.min.add_(x, y, z)
|
|
60
|
+
this.max.add_(x, y, z)
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
translate(delta: Vec3) {
|
|
65
|
+
this.min.add(delta)
|
|
66
|
+
this.max.add(delta)
|
|
67
|
+
return this
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
grow(increase: Vec3) {
|
|
71
|
+
const halfIncrease = increase.clone().half()
|
|
72
|
+
this.min.subtract(halfIncrease)
|
|
73
|
+
this.max.add(halfIncrease)
|
|
74
|
+
return this
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
growBy(increase: number) {
|
|
78
|
+
const halfIncrease = increase / 2
|
|
79
|
+
this.min.subtractBy(halfIncrease)
|
|
80
|
+
this.max.addBy(halfIncrease)
|
|
81
|
+
return this
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
import {Vec3} from "../../core/vec3.js"
|
|
3
|
+
|
|
4
|
+
export class Segment {
|
|
5
|
+
constructor(
|
|
6
|
+
public start: Vec3,
|
|
7
|
+
public end: Vec3,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
vector() {
|
|
11
|
+
return this.end.clone().subtract(this.start)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
length() {
|
|
15
|
+
return this.start.distance(this.end)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
center() {
|
|
19
|
+
return this.start.clone()
|
|
20
|
+
.add(this.end)
|
|
21
|
+
.half()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
clone() {
|
|
25
|
+
return new Segment(
|
|
26
|
+
this.start.clone(),
|
|
27
|
+
this.end.clone(),
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fromStart(length: number) {
|
|
32
|
+
const direction = this.vector().normalize()
|
|
33
|
+
return this.start.clone().add(direction.multiplyBy(length))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
point(fraction: number) {
|
|
37
|
+
return this.start.clone().add(this.vector().multiplyBy(fraction))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
scale(fraction: number) {
|
|
41
|
+
const {center} = this
|
|
42
|
+
const newHalfVector = this.vector().multiplyBy(fraction / 2)
|
|
43
|
+
this.start.set(center().subtract(newHalfVector))
|
|
44
|
+
this.end.set(center().add(newHalfVector))
|
|
45
|
+
return this
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import {Scalar} from "./scalar.js"
|
|
3
|
+
|
|
4
|
+
const pi = Math.PI
|
|
5
|
+
|
|
6
|
+
export const Radians = {
|
|
7
|
+
circle: 2 * pi,
|
|
8
|
+
halfcircle: pi,
|
|
9
|
+
|
|
10
|
+
toDegrees(r: number) {
|
|
11
|
+
return r * (180 / pi)
|
|
12
|
+
},
|
|
13
|
+
toArcseconds(r: number) {
|
|
14
|
+
return Radians.toDegrees(r) * 3600
|
|
15
|
+
},
|
|
16
|
+
toTurns(r: number) {
|
|
17
|
+
return r / Radians.circle
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
circleDistance(radiansA: number, radiansB: number): number {
|
|
21
|
+
const diff = Math.abs(Scalar.wrap(radiansA - radiansB, 0, Radians.circle))
|
|
22
|
+
return Math.min(diff, Radians.circle - diff)
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Turns = {
|
|
27
|
+
toRadians(t: number) {
|
|
28
|
+
return t * Radians.circle
|
|
29
|
+
},
|
|
30
|
+
toDegrees(t: number) {
|
|
31
|
+
return Radians.toDegrees(Turns.toRadians(t))
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const Arcseconds = {
|
|
36
|
+
toRadians(a: number) {
|
|
37
|
+
return Degrees.toRadians(a / 3600)
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Degrees = {
|
|
42
|
+
toRadians(d: number) {
|
|
43
|
+
return d * (pi / 180)
|
|
44
|
+
},
|
|
45
|
+
toTurns(d: number) {
|
|
46
|
+
return Radians.toTurns(Degrees.toRadians(d))
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
import {Scalar} from "./scalar.js"
|
|
3
3
|
|
|
4
|
+
const circle = 2 * Math.PI
|
|
5
|
+
|
|
4
6
|
export class Circular {
|
|
5
7
|
constructor(public x: number) {}
|
|
6
8
|
|
|
@@ -20,7 +22,7 @@ export class Circular {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
static normalize(x: number) {
|
|
23
|
-
return Scalar.wrap(x, 0,
|
|
25
|
+
return Scalar.wrap(x, 0, circle)
|
|
24
26
|
} normalize() {
|
|
25
27
|
this.x = Circular.normalize(this.x)
|
|
26
28
|
return this
|
|
@@ -30,8 +32,8 @@ export class Circular {
|
|
|
30
32
|
x = this.normalize(x)
|
|
31
33
|
y = this.normalize(y)
|
|
32
34
|
let delta = y - x
|
|
33
|
-
if (delta > Math.PI) delta -=
|
|
34
|
-
if (delta < -Math.PI) delta +=
|
|
35
|
+
if (delta > Math.PI) delta -= circle
|
|
36
|
+
if (delta < -Math.PI) delta += circle
|
|
35
37
|
return delta
|
|
36
38
|
} difference(y: number | Circular) {
|
|
37
39
|
return Circular.difference(this.x, Circular.value(y))
|
|
@@ -98,19 +98,5 @@ export class Randy {
|
|
|
98
98
|
}
|
|
99
99
|
return array
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
/** @deprecated create an instance with the given seed number. */
|
|
103
|
-
static seed(seed: number): Randy {
|
|
104
|
-
return new this(seed)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** @deprecated renamed to `take` */
|
|
108
|
-
extract<T>(count: number, array: T[]) { return this.take(count, array) }
|
|
109
|
-
|
|
110
|
-
/** @deprecated renamed to `range` */
|
|
111
|
-
between(a: number, b: number) { return this.range(a, b) }
|
|
112
|
-
|
|
113
|
-
/** @deprecated renamed to `integerRange` */
|
|
114
|
-
integerBetween(a: number, b: number) { return this.integerRange(a, b) }
|
|
115
101
|
}
|
|
116
102
|
|
|
@@ -43,7 +43,7 @@ export class Scalar {
|
|
|
43
43
|
x += n
|
|
44
44
|
return x
|
|
45
45
|
} add(...nums: number[]) {
|
|
46
|
-
this.x = Scalar.add(...nums)
|
|
46
|
+
this.x = Scalar.add(this.x, ...nums)
|
|
47
47
|
return this
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -53,23 +53,23 @@ export class Scalar {
|
|
|
53
53
|
return this
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
static
|
|
57
|
-
return Math.max(x,
|
|
58
|
-
}
|
|
59
|
-
this.x = Scalar.
|
|
56
|
+
static atLeast(x: number, least: number = 0) {
|
|
57
|
+
return Math.max(x, least)
|
|
58
|
+
} atLeast(least: number = 0) {
|
|
59
|
+
this.x = Scalar.atLeast(this.x, least)
|
|
60
60
|
return this
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
static
|
|
64
|
-
return Math.min(x,
|
|
65
|
-
}
|
|
66
|
-
this.x = Scalar.
|
|
63
|
+
static atMost(x: number, most: number = 1) {
|
|
64
|
+
return Math.min(x, most)
|
|
65
|
+
} atMost(most: number = 1) {
|
|
66
|
+
this.x = Scalar.atMost(this.x, most)
|
|
67
67
|
return this
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
static clamp(x: number, a: number = 0, b: number = 1) {
|
|
71
|
-
x = Scalar.
|
|
72
|
-
x = Scalar.
|
|
71
|
+
x = Scalar.atLeast(x, Math.min(a, b))
|
|
72
|
+
x = Scalar.atMost(x, Math.max(a, b))
|
|
73
73
|
return x
|
|
74
74
|
} clamp(a: number = 0, b: number = 1) {
|
|
75
75
|
this.x = Scalar.clamp(this.x, a, b)
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
import {Scalar} from "./scalar.js"
|
|
3
|
-
import {
|
|
3
|
+
import {XyArray} from "../core/vec2.js"
|
|
4
4
|
|
|
5
5
|
/** resolve a number within a linear spline. */
|
|
6
|
-
export function linear(x: number, points:
|
|
6
|
+
export function linear(x: number, points: XyArray[]): number {
|
|
7
7
|
if (points.length < 2)
|
|
8
8
|
throw new Error("need at least two points, come on")
|
|
9
9
|
|
|
10
10
|
const [first] = points.at(0)!
|
|
11
11
|
const [last] = points.at(-1)!
|
|
12
|
-
|
|
13
12
|
x = Scalar.clamp(x, first, last)
|
|
14
13
|
|
|
15
14
|
for (let i = 0; i < points.length - 1; i++) {
|
|
@@ -26,11 +25,13 @@ export function linear(x: number, points: Vec2Array[]): number {
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
/** resolve a number within a catmull-rom spline, that's all smooth-like. */
|
|
29
|
-
export function catmullRom(x: number, points:
|
|
28
|
+
export function catmullRom(x: number, points: XyArray[]) {
|
|
30
29
|
if (points.length < 4)
|
|
31
30
|
throw new Error("need at least four points for this magic")
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
const [first] = points.at(0)!
|
|
33
|
+
const [last] = points.at(-1)!
|
|
34
|
+
x = Scalar.clamp(x, first, last)
|
|
34
35
|
|
|
35
36
|
// find the segment where 'x' fits
|
|
36
37
|
for (let i = 1; i < points.length - 2; i++) {
|
|
@@ -54,7 +55,7 @@ export const ez = {
|
|
|
54
55
|
throw new Error("need at least two points, come on")
|
|
55
56
|
|
|
56
57
|
const points2 = points.map(
|
|
57
|
-
(p, index):
|
|
58
|
+
(p, index): XyArray =>
|
|
58
59
|
[Scalar.clamp(index / (points.length - 1)), p]
|
|
59
60
|
)
|
|
60
61
|
|
|
@@ -67,10 +68,10 @@ namespace helpers {
|
|
|
67
68
|
/** internal big-brain maths for the catmull-rom implementation */
|
|
68
69
|
export function catmullRom(
|
|
69
70
|
t: number,
|
|
70
|
-
[,p0]:
|
|
71
|
-
[,p1]:
|
|
72
|
-
[,p2]:
|
|
73
|
-
[,p3]:
|
|
71
|
+
[,p0]: XyArray,
|
|
72
|
+
[,p1]: XyArray,
|
|
73
|
+
[,p2]: XyArray,
|
|
74
|
+
[,p3]: XyArray,
|
|
74
75
|
) {
|
|
75
76
|
|
|
76
77
|
const t2 = t * t
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Xyz } from "./vec3.js";
|
|
2
|
-
export type
|
|
2
|
+
export type XyzwArray = [x: number, y: number, z: number, w: number];
|
|
3
3
|
export type Xyzw = {
|
|
4
4
|
x: number;
|
|
5
5
|
y: number;
|
|
@@ -14,14 +14,19 @@ export declare class Quat {
|
|
|
14
14
|
constructor(x: number, y: number, z: number, w: number);
|
|
15
15
|
static new(x: number, y: number, z: number, w: number): Quat;
|
|
16
16
|
static identity(): Quat;
|
|
17
|
-
static
|
|
18
|
-
static import({ x, y, z, w }: Xyzw): Quat;
|
|
19
|
-
static from(q: QuatArray | Xyzw): Quat;
|
|
17
|
+
static from(q: XyzwArray | Xyzw): Quat;
|
|
20
18
|
static rotate_(pitch: number, yaw: number, roll: number): Quat;
|
|
21
19
|
static rotate(vec: Xyz): Quat;
|
|
22
|
-
|
|
20
|
+
toJSON(): XyzwArray;
|
|
23
21
|
toString(): string;
|
|
24
22
|
clone(): Quat;
|
|
23
|
+
lengthSquared(): number;
|
|
24
|
+
length(): number;
|
|
25
|
+
isUnit(epsilon?: number): boolean;
|
|
26
|
+
ensureUnit(): this;
|
|
27
|
+
normalize(): this;
|
|
28
|
+
conjugate(): this;
|
|
29
|
+
invert(): this;
|
|
25
30
|
transform_(x: number, y: number, z: number, w: number, global?: boolean): Quat;
|
|
26
31
|
transform({ x, y, z, w }: Xyzw, global?: boolean): Quat;
|
|
27
32
|
rotate_(pitch: number, yaw: number, roll: number, global?: boolean): Quat;
|
|
@@ -15,16 +15,10 @@ export class Quat {
|
|
|
15
15
|
static identity() {
|
|
16
16
|
return new this(0, 0, 0, 1);
|
|
17
17
|
}
|
|
18
|
-
static array(q) {
|
|
19
|
-
return new this(...q);
|
|
20
|
-
}
|
|
21
|
-
static import({ x, y, z, w }) {
|
|
22
|
-
return new this(x, y, z, w);
|
|
23
|
-
}
|
|
24
18
|
static from(q) {
|
|
25
19
|
return Array.isArray(q)
|
|
26
|
-
? this
|
|
27
|
-
: this
|
|
20
|
+
? new this(...q)
|
|
21
|
+
: new this(q.x, q.y, q.z, q.w);
|
|
28
22
|
}
|
|
29
23
|
static rotate_(pitch, yaw, roll) {
|
|
30
24
|
return this.identity().rotate_(pitch, yaw, roll);
|
|
@@ -32,7 +26,7 @@ export class Quat {
|
|
|
32
26
|
static rotate(vec) {
|
|
33
27
|
return this.identity().rotate(vec);
|
|
34
28
|
}
|
|
35
|
-
|
|
29
|
+
toJSON() {
|
|
36
30
|
const { x, y, z, w } = this;
|
|
37
31
|
return [x, y, z, w];
|
|
38
32
|
}
|
|
@@ -40,12 +34,55 @@ export class Quat {
|
|
|
40
34
|
return `(Quat x${this.x.toFixed(2)}, y${this.y.toFixed(2)}, z${this.z.toFixed(2)}, w${this.w.toFixed(2)})`;
|
|
41
35
|
}
|
|
42
36
|
clone() {
|
|
43
|
-
return new Quat(...this.
|
|
37
|
+
return new Quat(...this.toJSON());
|
|
38
|
+
}
|
|
39
|
+
lengthSquared() {
|
|
40
|
+
return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
41
|
+
}
|
|
42
|
+
length() {
|
|
43
|
+
return Math.sqrt(this.lengthSquared());
|
|
44
|
+
}
|
|
45
|
+
isUnit(epsilon = 1e-6) {
|
|
46
|
+
return Math.abs(this.length() - 1) <= epsilon;
|
|
47
|
+
}
|
|
48
|
+
ensureUnit() {
|
|
49
|
+
if (!this.isUnit())
|
|
50
|
+
this.normalize();
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
normalize() {
|
|
54
|
+
const m = this.length();
|
|
55
|
+
if (!m) {
|
|
56
|
+
this.x = this.y = this.z = 0;
|
|
57
|
+
this.w = 1;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
this.x /= m;
|
|
61
|
+
this.y /= m;
|
|
62
|
+
this.z /= m;
|
|
63
|
+
this.w /= m;
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
conjugate() {
|
|
67
|
+
this.x *= -1;
|
|
68
|
+
this.y *= -1;
|
|
69
|
+
this.z *= -1;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
invert() {
|
|
73
|
+
const len2 = this.lengthSquared();
|
|
74
|
+
if (!len2)
|
|
75
|
+
return this.set_(0, 0, 0, 1);
|
|
76
|
+
this.x = -this.x / len2;
|
|
77
|
+
this.y = -this.y / len2;
|
|
78
|
+
this.z = -this.z / len2;
|
|
79
|
+
this.w = this.w / len2;
|
|
80
|
+
return this;
|
|
44
81
|
}
|
|
45
82
|
transform_(x, y, z, w, global = false) {
|
|
46
83
|
if (global) {
|
|
47
|
-
const original = this.
|
|
48
|
-
return this.set_(x, y, z, w).
|
|
84
|
+
const original = this.clone();
|
|
85
|
+
return this.set_(x, y, z, w).multiply(original);
|
|
49
86
|
}
|
|
50
87
|
else {
|
|
51
88
|
return this.multiply_(x, y, z, w);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quat.js","sourceRoot":"","sources":["../../s/core/quat.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type XyArray = [x: number, y: number];
|
|
2
2
|
export type Xy = {
|
|
3
3
|
x: number;
|
|
4
4
|
y: number;
|
|
5
5
|
};
|
|
6
|
-
/** https://github.com/microsoft/TypeScript/issues/5863 */
|
|
7
|
-
type TsHack<T> = {
|
|
8
|
-
new (...a: ConstructorParameters<typeof Vec2>): T;
|
|
9
|
-
};
|
|
10
6
|
export declare class Vec2 implements Xy {
|
|
11
7
|
x: number;
|
|
12
8
|
y: number;
|
|
13
9
|
constructor(x: number, y: number);
|
|
14
|
-
static new
|
|
15
|
-
static zero
|
|
16
|
-
static all
|
|
17
|
-
static
|
|
18
|
-
static import<T extends Vec2>(this: TsHack<T>, { x, y }: Xy): T;
|
|
19
|
-
static from(v: Vec2Array | Xy): Vec2;
|
|
10
|
+
static new(x: number, y: number): Vec2;
|
|
11
|
+
static zero(): Vec2;
|
|
12
|
+
static all(value: number): Vec2;
|
|
13
|
+
static from(v: XyArray | Xy): Vec2;
|
|
20
14
|
static magnitudeSquared(x: number, y: number): number;
|
|
21
15
|
static magnitude(x: number, y: number): number;
|
|
22
16
|
static average(...vectors: Xy[]): Vec2;
|
|
23
|
-
static min(...vecs:
|
|
24
|
-
static max(...vecs:
|
|
17
|
+
static min(...vecs: Xy[]): Vec2;
|
|
18
|
+
static max(...vecs: Xy[]): Vec2;
|
|
19
|
+
static fromAngle(radians: number): Vec2;
|
|
25
20
|
clone(): Vec2;
|
|
26
|
-
|
|
21
|
+
[Symbol.iterator](): Generator<number, void, unknown>;
|
|
22
|
+
toJSON(): XyArray;
|
|
27
23
|
toString(): string;
|
|
28
24
|
/** mutator */
|
|
29
25
|
set_(x: number, y: number): this;
|
|
@@ -34,6 +30,8 @@ export declare class Vec2 implements Xy {
|
|
|
34
30
|
rotation(): number;
|
|
35
31
|
equals_(x: number, y: number): boolean;
|
|
36
32
|
equals(...vecs: Xy[]): boolean;
|
|
33
|
+
near_(x: number, y: number, epsilon?: number): boolean;
|
|
34
|
+
near({ x, y }: Xy, epsilon?: number): boolean;
|
|
37
35
|
dot_(x: number, y: number): number;
|
|
38
36
|
dot({ x, y }: Xy): number;
|
|
39
37
|
distanceSquared_(x: number, y: number): number;
|
|
@@ -65,7 +63,9 @@ export declare class Vec2 implements Xy {
|
|
|
65
63
|
/** mutator */
|
|
66
64
|
map(fn: (a: number, index: number) => number): this;
|
|
67
65
|
/** mutator */
|
|
68
|
-
clamp(min:
|
|
66
|
+
clamp(min: Xy, max: Xy): this;
|
|
67
|
+
/** mutator */
|
|
68
|
+
clampBy(min: number, max: number): this;
|
|
69
69
|
/** mutator */
|
|
70
70
|
negate(): this;
|
|
71
71
|
/** mutator */
|
|
@@ -105,10 +105,9 @@ export declare class Vec2 implements Xy {
|
|
|
105
105
|
/** mutator */
|
|
106
106
|
rotateAroundPoint_(x: number, y: number, radians: number): this;
|
|
107
107
|
/** mutator */
|
|
108
|
-
rotateAroundPoint({ x, y }:
|
|
108
|
+
rotateAroundPoint({ x, y }: Xy, radians: number): this;
|
|
109
109
|
/** mutator */
|
|
110
110
|
smooth_(x: number, y: number, smoothing: number): this;
|
|
111
111
|
/** mutator */
|
|
112
112
|
smooth({ x, y }: Xy, smoothing: number): this;
|
|
113
113
|
}
|
|
114
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Scalar } from "
|
|
1
|
+
import { Scalar } from "../tools/scalar.js";
|
|
2
2
|
export class Vec2 {
|
|
3
3
|
x;
|
|
4
4
|
y;
|
|
@@ -6,7 +6,6 @@ export class Vec2 {
|
|
|
6
6
|
this.x = x;
|
|
7
7
|
this.y = y;
|
|
8
8
|
}
|
|
9
|
-
///////////////////////////////////////////////////////////////////////
|
|
10
9
|
static new(x, y) {
|
|
11
10
|
return new this(x, y);
|
|
12
11
|
}
|
|
@@ -16,16 +15,10 @@ export class Vec2 {
|
|
|
16
15
|
static all(value) {
|
|
17
16
|
return new this(value, value);
|
|
18
17
|
}
|
|
19
|
-
static array(v) {
|
|
20
|
-
return new this(...v);
|
|
21
|
-
}
|
|
22
|
-
static import({ x, y }) {
|
|
23
|
-
return new this(x, y);
|
|
24
|
-
}
|
|
25
18
|
static from(v) {
|
|
26
19
|
return Array.isArray(v)
|
|
27
|
-
? this
|
|
28
|
-
: this
|
|
20
|
+
? new this(...v)
|
|
21
|
+
: new this(v.x, v.y);
|
|
29
22
|
}
|
|
30
23
|
static magnitudeSquared(x, y) {
|
|
31
24
|
return (x * x) + (y * y);
|
|
@@ -39,16 +32,22 @@ export class Vec2 {
|
|
|
39
32
|
.divideBy(vectors.length);
|
|
40
33
|
}
|
|
41
34
|
static min(...vecs) {
|
|
42
|
-
return new
|
|
35
|
+
return new this(Math.min(...vecs.map(v => v.x)), Math.min(...vecs.map(v => v.y)));
|
|
43
36
|
}
|
|
44
37
|
static max(...vecs) {
|
|
45
|
-
return new
|
|
38
|
+
return new this(Math.max(...vecs.map(v => v.x)), Math.max(...vecs.map(v => v.y)));
|
|
39
|
+
}
|
|
40
|
+
static fromAngle(radians) {
|
|
41
|
+
return new this(Math.cos(radians), Math.sin(radians));
|
|
46
42
|
}
|
|
47
|
-
///////////////////////////////////////////////////////////////////////
|
|
48
43
|
clone() {
|
|
49
44
|
return new Vec2(this.x, this.y);
|
|
50
45
|
}
|
|
51
|
-
|
|
46
|
+
*[Symbol.iterator]() {
|
|
47
|
+
yield this.x;
|
|
48
|
+
yield this.y;
|
|
49
|
+
}
|
|
50
|
+
toJSON() {
|
|
52
51
|
return [this.x, this.y];
|
|
53
52
|
}
|
|
54
53
|
toString() {
|
|
@@ -66,7 +65,6 @@ export class Vec2 {
|
|
|
66
65
|
this.y = y;
|
|
67
66
|
return this;
|
|
68
67
|
}
|
|
69
|
-
///////////////////////////////////////////////////////////////////////
|
|
70
68
|
magnitudeSquared() {
|
|
71
69
|
return Vec2.magnitudeSquared(this.x, this.y);
|
|
72
70
|
}
|
|
@@ -83,6 +81,13 @@ export class Vec2 {
|
|
|
83
81
|
equals(...vecs) {
|
|
84
82
|
return vecs.every(({ x, y }) => this.equals_(x, y));
|
|
85
83
|
}
|
|
84
|
+
near_(x, y, epsilon = 1e-6) {
|
|
85
|
+
return (Math.abs(this.x - x) <= epsilon &&
|
|
86
|
+
Math.abs(this.y - y) <= epsilon);
|
|
87
|
+
}
|
|
88
|
+
near({ x, y }, epsilon = 1e-6) {
|
|
89
|
+
return this.near_(x, y, epsilon);
|
|
90
|
+
}
|
|
86
91
|
dot_(x, y) {
|
|
87
92
|
return (this.x * x) + (this.y * y);
|
|
88
93
|
}
|
|
@@ -106,12 +111,14 @@ export class Vec2 {
|
|
|
106
111
|
angleBetween_(x, y) {
|
|
107
112
|
const dot = this.dot_(x, y);
|
|
108
113
|
const magnitudes = this.magnitude() * Vec2.magnitude(x, y);
|
|
109
|
-
|
|
114
|
+
if (magnitudes === 0)
|
|
115
|
+
return 0;
|
|
116
|
+
const ratio = Scalar.clamp(dot / magnitudes, -1, 1);
|
|
117
|
+
return Math.acos(ratio);
|
|
110
118
|
}
|
|
111
119
|
angleBetween({ x, y }) {
|
|
112
120
|
return this.angleBetween_(x, y);
|
|
113
121
|
}
|
|
114
|
-
///////////////////////////////////////////////////////////////////////
|
|
115
122
|
/** mutator */
|
|
116
123
|
normalize() {
|
|
117
124
|
return this.divideBy(this.magnitude());
|
|
@@ -175,8 +182,15 @@ export class Vec2 {
|
|
|
175
182
|
}
|
|
176
183
|
/** mutator */
|
|
177
184
|
clamp(min, max) {
|
|
178
|
-
|
|
179
|
-
|
|
185
|
+
this.x = Scalar.clamp(this.x, min.x, max.x);
|
|
186
|
+
this.y = Scalar.clamp(this.y, min.y, max.y);
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
/** mutator */
|
|
190
|
+
clampBy(min, max) {
|
|
191
|
+
this.x = Scalar.clamp(this.x, min, max);
|
|
192
|
+
this.y = Scalar.clamp(this.y, min, max);
|
|
193
|
+
return this;
|
|
180
194
|
}
|
|
181
195
|
/** mutator */
|
|
182
196
|
negate() {
|
|
@@ -247,8 +261,10 @@ export class Vec2 {
|
|
|
247
261
|
}
|
|
248
262
|
/** mutator */
|
|
249
263
|
divide_(x, y) {
|
|
250
|
-
|
|
251
|
-
|
|
264
|
+
if (x !== 0)
|
|
265
|
+
this.x /= x;
|
|
266
|
+
if (y !== 0)
|
|
267
|
+
this.y /= y;
|
|
252
268
|
return this;
|
|
253
269
|
}
|
|
254
270
|
/** mutator */
|