@pirireis/webglobeplugins 0.9.14 → 0.10.0-alpha

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/Math/arc.js CHANGED
@@ -1,62 +1,190 @@
1
- import { vec3 } from "./vec3";
1
+ import { create as vec3create, set as vec3set, cross, dot, normalize, clone as vec3clone, copy as vec3copy, equals as vec3equals, lengthSquared, fromUnitVectorLongLat, subtract, applyQuaternion, toUnitVectorLongLat } from "./vec3";
2
+ import { create as planeCreate, fromPoints as planeFromPoints, distanceToPoint as planeDistanceToPoint, projectPoint as planeProjectPoint } from "./plane";
3
+ import { create as quaternionCreate, fromAxisAngle } from "./quaternion";
2
4
  import { EPSILON } from "./constants";
3
- const _0vector = /*@__PURE__*/ vec3.create(0, 0, 0);
4
- const _1vector = /*@__PURE__*/ vec3.create(1, 1, 1);
5
- export const arc = Object.freeze({
6
- create(p0, p1) {
7
- const normal = vec3.create(0, 0, 0);
8
- vec3.cross(normal, p0, p1);
9
- const coverPlaneNormal = [p0[0] + p1[0], p0[1] + p1[1], p0[2] + p1[2]];
10
- vec3.normalize(coverPlaneNormal, coverPlaneNormal);
11
- const dot = vec3.dot(coverPlaneNormal, p0);
12
- return {
13
- p0: vec3.clone(p0),
14
- p1: vec3.clone(p1),
15
- normal: vec3.clone(normal),
16
- coverPlane: {
17
- normal: coverPlaneNormal,
18
- distance: dot
19
- }
20
- };
21
- },
22
- set(out, p0, p1) {
23
- vec3.copy(out.p0, p0);
24
- vec3.copy(out.p1, p1);
25
- vec3.cross(out.normal, p0, p1);
26
- const coverPlaneNormal = [p0[0] + p1[0], p0[1] + p1[1], p0[2] + p1[2]];
27
- vec3.normalize(coverPlaneNormal, coverPlaneNormal);
28
- out.coverPlane.normal = coverPlaneNormal;
29
- out.coverPlane.distance = vec3.dot(coverPlaneNormal, p0);
30
- },
31
- copy(out, a) {
32
- vec3.copy(out.p0, a.p0);
33
- vec3.copy(out.p1, a.p1);
34
- vec3.copy(out.normal, a.normal);
35
- out.coverPlane.normal = vec3.clone(a.coverPlane.normal);
36
- out.coverPlane.distance = a.coverPlane.distance;
37
- },
38
- clone(a) {
39
- return {
40
- p0: vec3.clone(a.p0),
41
- p1: vec3.clone(a.p1),
42
- normal: vec3.clone(a.normal),
43
- coverPlane: {
44
- normal: vec3.clone(a.coverPlane.normal),
45
- distance: a.coverPlane.distance
46
- }
47
- };
48
- },
49
- isPointOn(arc, point) {
50
- const alignment = Math.abs(vec3.dot(point, arc.normal)) < EPSILON;
51
- const distance = Math.abs(vec3.lengthSquared(point) - 1) < EPSILON;
52
- const cover = vec3.dot(arc.coverPlane.normal, point) >= arc.coverPlane.distance;
53
- return alignment || distance || cover;
54
- },
55
- equals(a, b) {
56
- return vec3.equals(a.p0, b.p0) && vec3.equals(a.p1, b.p1);
57
- },
58
- populatePoints(out, arc, count) {
59
- // rotate p0 around normal vector with a quaternion
60
- // calculate angle
5
+ import * as vec3 from "./vec3";
6
+ import * as quat from "./quaternion";
7
+ const _0vector = /*@__PURE__*/ vec3create(0, 0, 0);
8
+ const _closestPoint = /*@__PURE__*/ vec3create();
9
+ const _originPlane = /*@__PURE__*/ planeCreate(vec3create(0, 0, 1), 0);
10
+ // dont change distance of _originPlane
11
+ const _rotationQuaternion = /*@__PURE__*/ quaternionCreate();
12
+ const _longLat = /*@__PURE__*/ [0, 0];
13
+ function create(p0, p1) {
14
+ const normal = vec3create(0, 0, 0);
15
+ cross(normal, p0, p1);
16
+ const coverPlaneNormal = [p0[0] + p1[0], p0[1] + p1[1], p0[2] + p1[2]];
17
+ normalize(coverPlaneNormal, coverPlaneNormal);
18
+ const dot_ = dot(coverPlaneNormal, p0);
19
+ return {
20
+ p0: vec3clone(p0),
21
+ p1: vec3clone(p1),
22
+ normal: vec3clone(normal),
23
+ coverPlane: {
24
+ normal: coverPlaneNormal,
25
+ distance: dot_
26
+ }
27
+ };
28
+ }
29
+ function set(out, p0, p1) {
30
+ vec3copy(out.p0, p0);
31
+ vec3copy(out.p1, p1);
32
+ cross(out.normal, p0, p1);
33
+ vec3set(_0vector, p0[0] + p1[0], p0[1] + p1[1], p0[2] + p1[2]);
34
+ const ls = lengthSquared(_0vector);
35
+ if (ls > EPSILON) {
36
+ normalize(out.coverPlane.normal, _0vector);
37
+ out.coverPlane.distance = dot(out.coverPlane.normal, p0);
61
38
  }
62
- });
39
+ else {
40
+ _oppositePointsHandle(p0, p1, out.normal, out.coverPlane);
41
+ }
42
+ }
43
+ function copy(out, a) {
44
+ vec3copy(out.p0, a.p0);
45
+ vec3copy(out.p1, a.p1);
46
+ vec3copy(out.normal, a.normal);
47
+ out.coverPlane.normal = vec3clone(a.coverPlane.normal);
48
+ out.coverPlane.distance = a.coverPlane.distance;
49
+ }
50
+ function clone(a) {
51
+ return {
52
+ p0: vec3clone(a.p0),
53
+ p1: vec3clone(a.p1),
54
+ normal: vec3clone(a.normal),
55
+ coverPlane: {
56
+ normal: vec3clone(a.coverPlane.normal),
57
+ distance: a.coverPlane.distance
58
+ }
59
+ };
60
+ }
61
+ function isPointOn(arc, point) {
62
+ const alignment = Math.abs(dot(point, arc.normal)) < EPSILON;
63
+ const distance = Math.abs(lengthSquared(point) - 1) < EPSILON;
64
+ const cover = dot(arc.coverPlane.normal, point) >= arc.coverPlane.distance;
65
+ return alignment || distance || cover;
66
+ }
67
+ function equals(a, b) {
68
+ return (vec3equals(a.p0, b.p0) && vec3equals(a.p1, b.p1))
69
+ || (vec3equals(a.p0, b.p1) && vec3equals(a.p1, b.p0));
70
+ }
71
+ function closestPoint(out, inArc, point) {
72
+ // 1. calculate the projection of the point onto the plane definned by the arc.normal, distance 0
73
+ // 2. calculate projection distance to the arc.coverPlane.
74
+ // * if the distance is negative, the point is outside the arc
75
+ // * copy (the closest of [inArc.p0, inArc.p1] to the point) to the output
76
+ // * return false that indicates the point is outside the arc
77
+ // * if the distance is positive, the point is inside the arc
78
+ // * normalize the projection and copy it to out
79
+ // * return true that indicates the point is inside the arc
80
+ const distance = planeDistanceToPoint(inArc.coverPlane, point);
81
+ if (distance < -EPSILON) {
82
+ // point is outside the arc
83
+ // this case also covers point is on center shaft line of the arc
84
+ return false;
85
+ }
86
+ vec3copy(_originPlane.normal, inArc.normal);
87
+ planeProjectPoint(_0vector, _originPlane, point);
88
+ // point is inside the arc
89
+ normalize(out, _0vector);
90
+ return true;
91
+ }
92
+ function populatePoints(out, arc, count, pointOfProjection = undefined) {
93
+ // rotate p0 around normal vector with a quaternion
94
+ // calculate angle
95
+ _distanceSampling(out, count, arc, pointOfProjection || [0, 0, 0], 1);
96
+ }
97
+ function _oppositePointsHandle(p0, p1, outNormal, outCoverPlane) {
98
+ // first choice pass through Anitkabir
99
+ const radians = Math.PI / 180;
100
+ fromUnitVectorLongLat(_0vector, [39.9334 * radians, 32.8597 * radians]); // Anitkabir
101
+ if (vec3equals(p0, _0vector) || vec3equals(p1, _0vector)) {
102
+ // if Anitkabir is too close to p0 or p1, use Selanic
103
+ fromUnitVectorLongLat(_0vector, [37.0016 * radians, 35.3213 * radians]); // Selanic
104
+ }
105
+ planeFromPoints({ normal: outNormal, distance: 0 }, p0, _0vector, p1);
106
+ cross(outCoverPlane.normal, outNormal, p0);
107
+ }
108
+ function _populatePointsWithClosestPointInsideArc(out, arc, count, closestPoint) {
109
+ // two parts divided by closest point will be populated seperately
110
+ // pop1 + pop2 = count
111
+ // angular distance between [arc.p0, closestPoint] and [arc.p1, closestPoint]
112
+ // will be used to decide ratio between pop1 and pop2
113
+ const angleP0 = Math.acos(dot(arc.p0, closestPoint));
114
+ const angleP1 = Math.acos(dot(arc.p1, closestPoint));
115
+ const pop1 = Math.floor(count * (angleP0 / (angleP0 + angleP1)));
116
+ const pop2 = count - pop1;
117
+ const angleStep1 = angleP0 / pop1;
118
+ const angleStep2 = angleP1 / pop2;
119
+ fromAxisAngle(_rotationQuaternion, arc.normal, angleStep1);
120
+ }
121
+ function _populatePointsWithoutClosestPoint(out, arc, count) {
122
+ }
123
+ /**
124
+ * Samples points along an arc with density biased by the camera's distance,
125
+ * reusing the rotation quaternion to improve performance.
126
+ *
127
+ * @param {Float32Array} out - The output array to store longitude and latitude pairs.
128
+ * @param {number} count - The total number of points to sample.
129
+ * @param {Arc} inArc - The arc to sample from, containing p0, p1, and normal.
130
+ * @param {Vec3} cameraPosition - The position of the camera.
131
+ * @param {number} quaternionReuseCount - The number of times to apply the same rotation before recalculating. Higher is faster but less accurate.
132
+ */
133
+ function _distanceSampling(out, count, inArc, cameraPosition = vec3create(0, 0, 0), // TODO
134
+ quaternionReuseCount = 1) {
135
+ if (count === 0) {
136
+ return;
137
+ }
138
+ const _0vector = vec3.create();
139
+ const _longLat = [0, 0];
140
+ const _rotationQuaternion = quat.create();
141
+ // Ensure reuse count is at least 1 to prevent division by zero or infinite loops.
142
+ const reuseCount = Math.max(1, quaternionReuseCount);
143
+ subtract(_0vector, inArc.p0, cameraPosition);
144
+ const d2_0 = lengthSquared(_0vector);
145
+ subtract(_0vector, inArc.p1, cameraPosition);
146
+ const d2_1 = lengthSquared(_0vector);
147
+ const total = d2_0 + d2_1;
148
+ const ratio0 = Math.min(0.995, Math.max(0.005, d2_0 / total));
149
+ const is0Closer = d2_0 < d2_1;
150
+ const totalAngle = Math.acos(dot(inArc.p0, inArc.p1));
151
+ let accumulatedAngle = 0;
152
+ // This variable will hold the step angle for the current "chunk" of reused rotations.
153
+ let chunkStepAngle = 0;
154
+ let currentPoint = vec3.clone(is0Closer ? inArc.p0 : inArc.p1);
155
+ const angleSign = is0Closer ? 1 : -1;
156
+ // The loop generates all points *except* the very last one.
157
+ for (let i = 0; i < count - 1; i++) {
158
+ // First, store the longitude/latitude of the current point.
159
+ toUnitVectorLongLat(_longLat, currentPoint);
160
+ out[i * 2] = _longLat[0];
161
+ out[i * 2 + 1] = _longLat[1];
162
+ // --- OPTIMIZATION LOGIC ---
163
+ // We only update the quaternion and step angle periodically.
164
+ if (i % reuseCount === 0) {
165
+ // This is the start of a new chunk. Calculate the step angle that will be
166
+ // reused for the next `reuseCount` iterations.
167
+ const t = (i + 1) / (count - 1);
168
+ const biasedT = Math.sin(t * Math.PI / 2);
169
+ const targetAngleForNextStep = (is0Closer ? biasedT : 1.0 - biasedT) * totalAngle;
170
+ // Calculate the single step angle based on the progress at the start of the chunk.
171
+ chunkStepAngle = targetAngleForNextStep - accumulatedAngle;
172
+ // Update the quaternion. This expensive call now runs much less frequently.
173
+ fromAxisAngle(_rotationQuaternion, inArc.normal, chunkStepAngle * angleSign);
174
+ }
175
+ // Apply the rotation. This happens on every iteration, but uses the
176
+ // same quaternion for `reuseCount` steps.
177
+ applyQuaternion(currentPoint, currentPoint, _rotationQuaternion);
178
+ // We must still update the accumulated angle on every step to track our progress.
179
+ accumulatedAngle += chunkStepAngle;
180
+ }
181
+ // Set the final point directly to the endpoint to guarantee precision.
182
+ if (count > 0) {
183
+ const finalIndex = count - 1;
184
+ const endPoint = is0Closer ? inArc.p1 : inArc.p0;
185
+ toUnitVectorLongLat(_longLat, endPoint);
186
+ out[finalIndex * 2] = _longLat[0];
187
+ out[finalIndex * 2 + 1] = _longLat[1];
188
+ }
189
+ }
190
+ export { create, set, copy, clone, isPointOn, equals, closestPoint, populatePoints };
@@ -1,45 +1,53 @@
1
1
  import { EPSILON } from "../constants";
2
- import { vec3 } from "../vec3";
3
- import { line } from "../line";
4
- import { plane } from "../plane";
5
- import { arc } from "../arc";
2
+ import { create as vec3create, copy as vec3copy, dot, distanceSquared, } from "../vec3";
3
+ import { create as lineCreate } from "../line";
4
+ import { create as planeCreate, distanceToPoint, getUnitSphereRadiusAngle } from "../plane";
5
+ import { copy as arcCopy, set as arcSet } from "../arc";
6
6
  import { planePlaneJuction } from "./plane-plane";
7
7
  import { lineSphereIntersection } from "./line-sphere";
8
- const _intersectionLine = /*@__PURE__*/ line.create();
9
- const _originPlane = /*@__PURE__*/ plane.create();
8
+ const _intersectionLine = /*@__PURE__*/ lineCreate();
9
+ const _originPlane = /*@__PURE__*/ planeCreate();
10
10
  _originPlane.distance = 0;
11
- const _originSphere = /*@__PURE__*/ { center: vec3.create(0, 0, 0), radius: 1 };
12
- const _intersectionPoints = /*@__PURE__*/ [vec3.create(), vec3.create()];
11
+ const _originSphere = /*@__PURE__*/ { center: vec3create(0, 0, 0), radius: 1 };
12
+ const _intersectionPoints = /*@__PURE__*/ [vec3create(), vec3create()];
13
13
  // TODO: out must be [Arc, Arc] there is a case where split into three arcs, visible by points or arcs but middle is not visible
14
14
  /**
15
15
  *
16
16
  * @param out \
17
17
  * @param inArc
18
- * @param juctionPlane
18
+ * @param junctionPlane
19
19
  * @returns number of arcs segments in the junction divided by the junction plane.
20
20
  */
21
- export function arcSlice(out, inArc, juctionPlane) {
21
+ export function arcSlice(out, inArc, junctionPlane) {
22
+ if (junctionPlane.distance < -1 + EPSILON) {
23
+ arcCopy(out[0], inArc);
24
+ return 1;
25
+ }
22
26
  // arc coverPlane and junctionPlane intersection exist in the range of unit sphere
23
- const coverRadiusAngle = plane.getUnitSphereRadiusAngle(inArc.coverPlane);
24
- const visibleRadiusAngle = plane.getUnitSphereRadiusAngle(juctionPlane);
27
+ const coverRadiusAngle = getUnitSphereRadiusAngle(inArc.coverPlane);
28
+ const visibleRadiusAngle = getUnitSphereRadiusAngle(junctionPlane);
25
29
  // TODO: RESEARCH efficient approach --
26
- const angleBetween_Cover_Visible = Math.acos(vec3.dot(inArc.coverPlane.normal, juctionPlane.normal));
30
+ const angleBetween_Cover_Visible = Math.acos(dot(inArc.coverPlane.normal, junctionPlane.normal));
27
31
  if (coverRadiusAngle + visibleRadiusAngle < angleBetween_Cover_Visible - EPSILON) { // case A: out of range
28
32
  return 0; // No intersection
29
33
  }
30
34
  // ------------------------------------
31
35
  // the case when the arc is completely covered by the juction plane
32
36
  if (visibleRadiusAngle + EPSILON >= angleBetween_Cover_Visible + coverRadiusAngle) { // case B: fully visible
33
- arc.copy(out[0], inArc);
37
+ arcCopy(out[0], inArc);
34
38
  return 1;
35
39
  }
36
40
  // plane-plane intersection line should be calculated for the rest of the calculations
37
- vec3.copy(_originPlane.normal, inArc.normal);
38
- const isPlaneJunctions = planePlaneJuction(_intersectionLine, _originPlane, juctionPlane);
41
+ vec3copy(_originPlane.normal, inArc.normal);
42
+ const isPlaneJunctions = planePlaneJuction(_intersectionLine, _originPlane, junctionPlane);
39
43
  if (!isPlaneJunctions) { // case C: planes are parallel.
40
- // case A covers opposite directions
41
- // case B Covers they face each other
42
- throw new Error("Unexpected case: planes are parallel, case A and B should Cover it");
44
+ if (junctionPlane.distance <= 0) {
45
+ arcCopy(out[0], inArc);
46
+ return 1; // No intersection
47
+ }
48
+ else {
49
+ return 0; // No intersection
50
+ }
43
51
  }
44
52
  // --- read until here ---
45
53
  // calculate the intersection points
@@ -48,33 +56,33 @@ export function arcSlice(out, inArc, juctionPlane) {
48
56
  // other edge caes should be covered by now
49
57
  return 0; // No intersection
50
58
  }
51
- const i0IsCovered = plane.distanceToPoint(inArc.coverPlane, _intersectionPoints[0]) > -EPSILON;
52
- const i1IsCovered = plane.distanceToPoint(inArc.coverPlane, _intersectionPoints[1]) > -EPSILON;
53
- const p0IsVisible = plane.distanceToPoint(juctionPlane, inArc.p0) > -EPSILON;
54
- const p1IsVisible = plane.distanceToPoint(juctionPlane, inArc.p1) > -EPSILON;
59
+ const i0IsCovered = distanceToPoint(inArc.coverPlane, _intersectionPoints[0]) > -EPSILON;
60
+ const i1IsCovered = distanceToPoint(inArc.coverPlane, _intersectionPoints[1]) > -EPSILON;
61
+ const p0IsVisible = distanceToPoint(junctionPlane, inArc.p0) > -EPSILON;
62
+ const p1IsVisible = distanceToPoint(junctionPlane, inArc.p1) > -EPSILON;
55
63
  if (!p0IsVisible && !p1IsVisible && !i0IsCovered && !i1IsCovered) {
56
64
  return 0; // No intersection
57
65
  }
58
66
  if (i0IsCovered && i1IsCovered && p0IsVisible && p1IsVisible) {
59
67
  // calculate which points are closer
60
- const p0i0DistanceSquared = vec3.distanceSquared(inArc.p0, _intersectionPoints[0]);
61
- const p0i1DistanceSquared = vec3.distanceSquared(inArc.p0, _intersectionPoints[1]);
68
+ const p0i0DistanceSquared = distanceSquared(inArc.p0, _intersectionPoints[0]);
69
+ const p0i1DistanceSquared = distanceSquared(inArc.p0, _intersectionPoints[1]);
62
70
  const case0 = p0i0DistanceSquared < p0i1DistanceSquared;
63
- arc.set(out[0], inArc.p0, case0 ? _intersectionPoints[0] : _intersectionPoints[1]);
64
- arc.set(out[1], inArc.p1, !case0 ? _intersectionPoints[0] : _intersectionPoints[1]);
71
+ arcSet(out[0], inArc.p0, case0 ? _intersectionPoints[0] : _intersectionPoints[1]);
72
+ arcSet(out[1], inArc.p1, !case0 ? _intersectionPoints[0] : _intersectionPoints[1]);
65
73
  return 2;
66
74
  }
67
75
  if (i0IsCovered && i1IsCovered) {
68
- arc.set(out[0], _intersectionPoints[0], _intersectionPoints[1]);
76
+ arcSet(out[0], _intersectionPoints[0], _intersectionPoints[1]);
69
77
  return 1;
70
78
  }
71
79
  if (p0IsVisible && p1IsVisible) {
72
- arc.copy(out[0], inArc);
80
+ arcCopy(out[0], inArc);
73
81
  return 1;
74
82
  }
75
83
  if ((p0IsVisible || p1IsVisible) !== (i0IsCovered || i1IsCovered)) {
76
84
  throw new Error("Unexpected case: one covered and one visible point must be present");
77
85
  }
78
- arc.set(out[0], p0IsVisible ? inArc.p0 : inArc.p1, i0IsCovered ? _intersectionPoints[0] : _intersectionPoints[1]);
86
+ arcSet(out[0], p0IsVisible ? inArc.p0 : inArc.p1, i0IsCovered ? _intersectionPoints[0] : _intersectionPoints[1]);
79
87
  return 1;
80
88
  }
@@ -1,22 +1,22 @@
1
- import { vec3 } from "../vec3";
2
- import { line } from "../line";
3
- const _0vector = /*@__PURE__*/ vec3.create(0, 0, 0);
1
+ import { create, dot, lengthSquared, subtract } from "../vec3";
2
+ import { at } from "../line";
3
+ const _0vector = /*@__PURE__*/ create(0, 0, 0);
4
4
  export function lineSphereIntersection(out, inLine, inSphere) {
5
- vec3.subtract(_0vector, inLine.origin, inSphere.center);
6
- const distanceSquared = vec3.lengthSquared(_0vector);
5
+ subtract(_0vector, inLine.origin, inSphere.center);
6
+ const distanceSquared = lengthSquared(_0vector);
7
7
  const radiusSquared = inSphere.radius * inSphere.radius;
8
- const dot = vec3.dot(_0vector, inLine.direction);
9
- const dotSquared = dot * dot;
10
- const _a = dotSquared + radiusSquared - distanceSquared;
11
- if (_a < 0) {
8
+ const dot_ = dot(_0vector, inLine.direction);
9
+ const dotSquared = dot_ * dot_;
10
+ const discriminant = dotSquared + radiusSquared - distanceSquared;
11
+ if (discriminant < 0) {
12
12
  return false; // no intersection
13
13
  }
14
14
  else {
15
- const a = Math.sqrt(_a);
16
- const t1 = dot - a;
17
- const t2 = dot + a;
18
- line.at(out[0], inLine, t1);
19
- line.at(out[1], inLine, t2);
15
+ const a = Math.sqrt(discriminant);
16
+ const t1 = -dot_ - a;
17
+ const t2 = -dot_ + a;
18
+ at(out[0], inLine, t1);
19
+ at(out[1], inLine, t2);
20
20
  return true;
21
21
  }
22
22
  }
@@ -1,19 +1,19 @@
1
1
  import { EPSILON } from "../constants";
2
- import { vec3 } from "../vec3";
3
- const _normal1 = vec3.create();
4
- const _normal2 = vec3.create();
2
+ import { copy, create, dot, cross, lengthSquared } from "../vec3";
3
+ const _normal1 = create();
4
+ const _normal2 = create();
5
5
  export function planePlaneJuction(out, plane1, plane2) {
6
- vec3.copy(_normal1, plane1.normal);
7
- vec3.copy(_normal2, plane2.normal);
6
+ copy(_normal1, plane1.normal);
7
+ copy(_normal2, plane2.normal);
8
8
  const distance1 = plane1.distance;
9
9
  const distance2 = plane2.distance;
10
10
  const { origin, direction } = out;
11
- const dot = vec3.dot(_normal1, _normal2);
12
- if (Math.abs(dot) > 1 - EPSILON) {
11
+ const d = dot(_normal1, _normal2);
12
+ if (Math.abs(d) > 1 - EPSILON) {
13
13
  return false; // Planes are parallel, no intersection
14
14
  }
15
- vec3.cross(direction, _normal1, _normal2);
16
- const magnitudeSquired = vec3.lengthSquared(out.direction);
15
+ cross(direction, _normal1, _normal2);
16
+ const magnitudeSquired = lengthSquared(out.direction);
17
17
  if (magnitudeSquired < EPSILON) {
18
18
  return false; // No valid intersection line
19
19
  }
package/Math/line.js CHANGED
@@ -1,53 +1,52 @@
1
1
  import { EPSILON } from './constants';
2
- import { vec3 } from './vec3';
3
- const _0vector = /*@__PURE__*/ vec3.create(0, 0, 0);
4
- export const line = Object.freeze({
5
- create(origin = vec3.create(), direction = vec3.create()) {
6
- const direction_ = vec3.clone(direction);
7
- vec3.normalize(direction_, direction_);
8
- return {
9
- origin: vec3.clone(origin),
10
- direction: direction_
11
- };
12
- },
13
- set(out, origin, direction) {
14
- vec3.copy(out.origin, origin);
15
- vec3.copy(out.direction, direction);
16
- },
17
- copy(out, a) {
18
- out.origin = vec3.copy(out.origin, a.origin);
19
- out.direction = vec3.copy(out.direction, a.direction);
20
- },
21
- clone(a) {
22
- return {
23
- origin: vec3.clone(a.origin),
24
- direction: vec3.clone(a.direction)
25
- };
26
- },
27
- fromTwoPoints(out, a, b) {
28
- vec3.subtract(out.direction, b, a);
29
- vec3.normalize(out.direction, out.direction);
30
- vec3.copy(out.origin, a);
31
- },
32
- at(out, line, distance) {
33
- vec3.multiplyScalar(_0vector, line.direction, distance);
34
- vec3.add(out, _0vector, line.origin);
35
- },
36
- closestPoint(out, line, point) {
37
- vec3.subtract(_0vector, point, line.origin);
38
- const dot = vec3.dot(_0vector, line.direction);
39
- vec3.copy(out, line.direction);
40
- vec3.multiplyScalar(out, out, dot);
41
- vec3.add(out, out, line.origin);
42
- },
43
- contains(line, point) {
44
- vec3.subtract(_0vector, point, line.origin);
45
- vec3.cross(_0vector, _0vector, line.direction);
46
- return vec3.lengthSquared(_0vector) < EPSILON;
47
- },
48
- applyQuaternion(out, line, quaternion) {
49
- vec3.applyQuaternion(out.origin, line.origin, quaternion);
50
- vec3.applyQuaternion(out.direction, line.direction, quaternion);
51
- vec3.normalize(out.direction, out.direction);
52
- }
53
- });
2
+ import { subtract, applyQuaternion as vec3applyQuaternion, add, multiplyScalar, normalize, dot, cross, lengthSquared, clone as vec3clone, create as vec3create, copy as vec3copy } from './vec3';
3
+ const _0vector = /*@__PURE__*/ vec3create(0, 0, 0);
4
+ function create(origin = vec3create(), direction = vec3create()) {
5
+ const direction_ = vec3clone(direction);
6
+ normalize(direction_, direction_);
7
+ return {
8
+ origin: vec3clone(origin),
9
+ direction: direction_
10
+ };
11
+ }
12
+ function set(out, origin, direction) {
13
+ vec3copy(out.origin, origin);
14
+ vec3copy(out.direction, direction);
15
+ }
16
+ function copy(out, a) {
17
+ out.origin = vec3copy(out.origin, a.origin);
18
+ out.direction = vec3copy(out.direction, a.direction);
19
+ }
20
+ function clone(a) {
21
+ return {
22
+ origin: vec3clone(a.origin),
23
+ direction: vec3clone(a.direction)
24
+ };
25
+ }
26
+ function fromTwoPoints(out, a, b) {
27
+ subtract(out.direction, b, a);
28
+ normalize(out.direction, out.direction);
29
+ vec3copy(out.origin, a);
30
+ }
31
+ function at(out, line, distance) {
32
+ multiplyScalar(_0vector, line.direction, distance);
33
+ add(out, _0vector, line.origin);
34
+ }
35
+ function closestPoint(out, line, point) {
36
+ subtract(_0vector, point, line.origin);
37
+ const dot_ = dot(_0vector, line.direction);
38
+ vec3copy(out, line.direction);
39
+ multiplyScalar(out, out, dot_);
40
+ add(out, out, line.origin);
41
+ }
42
+ function contains(line, point) {
43
+ subtract(_0vector, point, line.origin);
44
+ cross(_0vector, _0vector, line.direction);
45
+ return lengthSquared(_0vector) < EPSILON;
46
+ }
47
+ function applyQuaternion(out, line, quaternion) {
48
+ vec3applyQuaternion(out.origin, line.origin, quaternion);
49
+ vec3applyQuaternion(out.direction, line.direction, quaternion);
50
+ normalize(out.direction, out.direction);
51
+ }
52
+ export { create, set, copy, clone, fromTwoPoints, at, closestPoint, contains, applyQuaternion };