@woosh/meep-engine 2.33.2 → 2.33.6
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/core/bvh2/aabb3/AABB3.js +18 -0
- package/core/bvh2/aabb3/aabb3_intersects_frustum.js +38 -0
- package/core/collection/RingBuffer.js +40 -10
- package/core/collection/array/copyArray.js +2 -2
- package/core/collection/array/typed/typed_array_copy.js +2 -2
- package/core/collection/table/RowFirstTableSpec.js +8 -0
- package/core/geom/3d/aabb/aabb3_compute_projected_area.js +16 -14
- package/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +59 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +33 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +41 -0
- package/core/geom/3d/plane/plane3_lerp.js +2 -2
- package/core/geom/3d/topology/TopoTriangle.js +2 -2
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/Matrix4.js +4 -4
- package/core/geom/Vector3.js +5 -5
- package/core/model/reactive/model/terminal/ReactiveReference.js +7 -1
- package/core/process/undo/ActionProcessor.d.ts +2 -0
- package/core/process/undo/ActionProcessor.js +59 -1
- package/core/process/undo/ActionProcessor.spec.js +59 -0
- package/core/process/undo/Mark.js +2 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +3 -3
- package/engine/asset/loaders/material/TextureAttachmensByMaterialType.js +11 -1
- package/engine/asset/loaders/material/TextureAttachment.js +12 -1
- package/engine/asset/loaders/material/bitmap2sampler_gl.js +19 -0
- package/engine/asset/loaders/material/computeImageBitmapEquality.js +7 -19
- package/engine/asset/loaders/material/computeTextureEquality.js +1 -1
- package/engine/asset/loaders/material/computeTextureHash.js +16 -14
- package/engine/asset/loaders/material/traverseMaterialTextures.js +2 -2
- package/engine/ecs/animation/OneBoneSurfaceAlignmentSolver.js +2 -2
- package/engine/ecs/animation/TwoBoneInverseKinematicsSolver.js +4 -4
- package/engine/graphics/GraphicsEngine.d.ts +2 -2
- package/engine/graphics/GraphicsEngine.js +20 -62
- package/engine/graphics/filter/FlipArrayInPlace.js +25 -0
- package/engine/graphics/filter/FlipArrayViaCanvas.js +13 -0
- package/engine/graphics/filter/ImageFilter.js +20 -51
- package/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +2 -2
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +25 -16
- package/engine/graphics/material/SplatMaterial.js +4 -97
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +598 -0
- package/engine/graphics/micron/build/PatchRepresentation.js +4 -43
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +4 -75
- package/engine/graphics/micron/build/compute_buffer_geometry_byte_size.js +16 -0
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +2 -0
- package/engine/graphics/micron/format/MicronGeometryBufferAttributeSpec.js +1 -1
- package/engine/graphics/micron/format/MicronGeometryPatch.js +17 -5
- package/engine/graphics/micron/format/MicronVertexDataSpec.js +25 -3
- package/engine/graphics/micron/prototypeVirtualGeometry.js +19 -12
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +34 -27
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +2 -4
- package/engine/graphics/micron/render/instanced/PatchDataTextures.js +1 -0
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -29
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +43 -159
- package/engine/graphics/micron/render/refinement/ActivePatchRecord.js +4 -2
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +98 -0
- package/engine/graphics/micron/render/refinement/array_normalize_plane.js +25 -0
- package/engine/graphics/micron/render/refinement/array_setFromProjectionMatrix.js +60 -0
- package/engine/graphics/micron/render/refinement/is_patch_facing_back.js +43 -0
- package/engine/graphics/micron/render/refinement/is_patch_visible.js +37 -0
- package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +21 -0
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +12 -9
- package/engine/graphics/micron/util/unit_hemioct.spec.js +2 -2
- package/engine/graphics/render/buffer/buffers/ColorAndDepthFrameBuffer.js +5 -3
- package/engine/graphics/render/buffer/buffers/NormalFrameBuffer.js +12 -2
- package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +8 -10
- package/engine/graphics/render/forward_plus/LightManager.js +5 -7
- package/engine/graphics/render/forward_plus/data/NumericType.js +9 -0
- package/engine/graphics/render/forward_plus/{TextureBackedMemoryRegion.js → data/TextureBackedMemoryRegion.js} +11 -190
- package/engine/graphics/render/forward_plus/data/channelCountToThreIntegerTextureType.js +16 -0
- package/engine/graphics/render/forward_plus/data/computeDataType.js +36 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureFormat.js +18 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureInternalFormatFromDataType.js +63 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureTypeFromDataType.js +41 -0
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/engine/graphics/render/forward_plus/prototypeLightManager.js +1 -1
- package/engine/graphics/render/utils/ThreeBypassRenderer.js +1 -3
- package/engine/graphics/render/visibility/hiz/buffer/HierarchicalZBuffer.js +198 -0
- package/engine/graphics/render/visibility/hiz/buffer/ReductionShader.js +51 -0
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +179 -0
- package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +435 -0
- package/engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js +174 -0
- package/engine/graphics/render/visibility/hiz/query/QueryShader.js +173 -0
- package/engine/graphics/shadows/ShadowMapRenderer.js +12 -2
- package/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
- package/engine/graphics/texture/cubemap/buildCubeURLs.js +13 -0
- package/engine/graphics/texture/cubemap/load_environment_map.d.ts +8 -0
- package/engine/graphics/texture/cubemap/load_environment_map.js +163 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +18 -62
- package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +8 -4
- package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +3 -2
- package/engine/graphics/texture/sampler/differenceSampler.js +31 -0
- package/engine/graphics/texture/sampler/typedArrayConstructorByInstance.js +25 -0
- package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +3 -2
- package/engine/graphics/texture/virtual/v2/ShaderUsage.js +6 -5
- package/engine/graphics/texture/virtual/v2/prototype.js +16 -6
- package/package.json +1 -1
- package/view/elements/progress/segmented/SegmentedResourceBarView.js +50 -15
- package/view/minimap/gl/MinimapMarkersGL.js +2 -2
- package/engine/graphics/micron/render/RefinementSpec.js +0 -110
package/core/bvh2/aabb3/AABB3.js
CHANGED
|
@@ -8,6 +8,7 @@ import { computeAABB3PlaneSide } from "../../geom/3d/aabb/computeAABB3PlaneSide.
|
|
|
8
8
|
import computeMortonCode from "../../geom/3d/morton/Morton.js";
|
|
9
9
|
import { _boxSurfaceArea2, intersectRay, intersectSegment } from "./AABB3Math.js";
|
|
10
10
|
import { aabb3_build_corners } from "../../geom/3d/aabb/aabb3_build_corners.js";
|
|
11
|
+
import { assert } from "../../assert.js";
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -718,6 +719,23 @@ AABB3.prototype.getCorners = function (result) {
|
|
|
718
719
|
);
|
|
719
720
|
};
|
|
720
721
|
|
|
722
|
+
/**
|
|
723
|
+
*
|
|
724
|
+
* @param {number[]|Float32Array|Float64Array} result
|
|
725
|
+
* @param {number} offset
|
|
726
|
+
*/
|
|
727
|
+
AABB3.prototype.writeToArray = function (result, offset) {
|
|
728
|
+
assert.isNonNegativeInteger(offset, 'offset');
|
|
729
|
+
|
|
730
|
+
result[offset] = this.x0;
|
|
731
|
+
result[offset + 1] = this.y0;
|
|
732
|
+
result[offset + 2] = this.z0;
|
|
733
|
+
|
|
734
|
+
result[offset + 3] = this.x1;
|
|
735
|
+
result[offset + 4] = this.y1;
|
|
736
|
+
result[offset + 5] = this.z1;
|
|
737
|
+
};
|
|
738
|
+
|
|
721
739
|
/**
|
|
722
740
|
* @param {THREE.Plane} plane
|
|
723
741
|
* @returns {int} 2,0,or -2; 2: above, -2 : below, 0 : intersects plane
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { aabb3_computeDistanceAbovePlane } from "../../geom/3d/aabb/aabb3_computeDistanceAbovePlane.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {Float32Array|number[]} aabb
|
|
6
|
+
* @param {Float32Array|number[]} frustum
|
|
7
|
+
* @return {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export function aabb3_intersects_frustum(aabb, frustum) {
|
|
10
|
+
|
|
11
|
+
const x0 = aabb[0];
|
|
12
|
+
const y0 = aabb[1];
|
|
13
|
+
const z0 = aabb[2];
|
|
14
|
+
const x1 = aabb[3];
|
|
15
|
+
const y1 = aabb[4];
|
|
16
|
+
const z1 = aabb[5];
|
|
17
|
+
|
|
18
|
+
for (let i = 0; i < 24; i += 4) {
|
|
19
|
+
|
|
20
|
+
const plane_n_x = frustum[i];
|
|
21
|
+
const plane_n_y = frustum[i + 1];
|
|
22
|
+
const plane_n_z = frustum[i + 2];
|
|
23
|
+
const plane_constant = frustum[i + 3];
|
|
24
|
+
|
|
25
|
+
const plane_distance = aabb3_computeDistanceAbovePlane(
|
|
26
|
+
plane_n_x, plane_n_y, plane_n_z, plane_constant,
|
|
27
|
+
x0, y0, z0,
|
|
28
|
+
x1, y1, z1
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if (plane_distance < 0) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
@@ -7,14 +7,32 @@ export class RingBuffer {
|
|
|
7
7
|
* @constructor
|
|
8
8
|
*/
|
|
9
9
|
constructor(size) {
|
|
10
|
-
assert.
|
|
10
|
+
assert.isNumber(size, 'size');
|
|
11
11
|
assert.greaterThan(size, 0, `size`);
|
|
12
|
+
assert.isNonNegativeInteger(size, 'size');
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
13
18
|
this.size = size;
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
15
24
|
this.head = 0;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
16
30
|
this.tail = 0;
|
|
17
31
|
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
18
36
|
this.count = 0;
|
|
19
37
|
|
|
20
38
|
/**
|
|
@@ -62,13 +80,15 @@ export class RingBuffer {
|
|
|
62
80
|
|
|
63
81
|
this.data[head] = element;
|
|
64
82
|
|
|
65
|
-
const
|
|
83
|
+
const size = this.size;
|
|
84
|
+
|
|
85
|
+
const newHead = (head + 1) % size;
|
|
66
86
|
|
|
67
87
|
this.head = newHead;
|
|
68
88
|
|
|
69
|
-
if (this.count ===
|
|
89
|
+
if (this.count === size) {
|
|
70
90
|
//update tail
|
|
71
|
-
this.tail = (this.tail + 1) %
|
|
91
|
+
this.tail = (this.tail + 1) % size;
|
|
72
92
|
} else {
|
|
73
93
|
this.count++;
|
|
74
94
|
}
|
|
@@ -130,11 +150,15 @@ export class RingBuffer {
|
|
|
130
150
|
* @returns {V|undefined}
|
|
131
151
|
*/
|
|
132
152
|
removeIf(condition, thisArg) {
|
|
153
|
+
const count = this.count;
|
|
154
|
+
const size = this.size;
|
|
133
155
|
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
const tail = this.tail;
|
|
157
|
+
const data = this.data;
|
|
136
158
|
|
|
137
|
-
|
|
159
|
+
for (let i = 0; i < count; i++) {
|
|
160
|
+
const index = (tail + i) % size;
|
|
161
|
+
const el = data[index];
|
|
138
162
|
|
|
139
163
|
if (condition.call(thisArg, el)) {
|
|
140
164
|
|
|
@@ -151,10 +175,16 @@ export class RingBuffer {
|
|
|
151
175
|
* @param {*} [thisArg]
|
|
152
176
|
*/
|
|
153
177
|
forEach(visitor, thisArg) {
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
const count = this.count;
|
|
179
|
+
const size = this.size;
|
|
180
|
+
|
|
181
|
+
const tail = this.tail;
|
|
182
|
+
const data = this.data;
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < count; i++) {
|
|
156
185
|
|
|
157
|
-
const
|
|
186
|
+
const index = (tail + i) % size;
|
|
187
|
+
const el = data[index];
|
|
158
188
|
|
|
159
189
|
visitor.call(thisArg, el);
|
|
160
190
|
}
|
|
@@ -25,9 +25,9 @@ export function copyArray(source, target) {
|
|
|
25
25
|
* Follows Java System.arraycopy interface
|
|
26
26
|
* Copy data from one array to another
|
|
27
27
|
* @template T
|
|
28
|
-
* @param {T[]|ArrayLike<T>|TypedArray} source The source array
|
|
28
|
+
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} source The source array
|
|
29
29
|
* @param {number} source_position Starting position where to copy from inside the source array
|
|
30
|
-
* @param {T[]|ArrayLike<T>|TypedArray} destination The destination array
|
|
30
|
+
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} destination The destination array
|
|
31
31
|
* @param {number} destination_position Starting position where to copy to inside the destination array
|
|
32
32
|
* @param {number} length How many elements should be copied
|
|
33
33
|
*/
|
|
@@ -3,8 +3,8 @@ import { array_copy } from "../copyArray.js";
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
|
-
* @param {TypedArray} source
|
|
7
|
-
* @param {TypedArray} destination
|
|
6
|
+
* @param {TypedArray|Float32Array} source
|
|
7
|
+
* @param {TypedArray|Float32Array} destination
|
|
8
8
|
*/
|
|
9
9
|
export function typed_array_copy(source, destination) {
|
|
10
10
|
const destination_size = destination.length;
|
|
@@ -234,6 +234,14 @@ export function RowFirstTableSpec(types, endianType = EndianType.BigEndian) {
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
/**
|
|
238
|
+
*
|
|
239
|
+
* @return {number}
|
|
240
|
+
*/
|
|
241
|
+
RowFirstTableSpec.prototype.getColumnCount = function () {
|
|
242
|
+
return this.types.length;
|
|
243
|
+
}
|
|
244
|
+
|
|
237
245
|
/**
|
|
238
246
|
*
|
|
239
247
|
* @param {RowFirstTableSpec} other
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const scratch_corners = new Float32Array(24);
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
|
|
5
3
|
one option of Algorithm (problem-orthogonal only, rectangles under perspective projection do not behave this way):
|
|
@@ -12,13 +10,13 @@ const scratch_corners = new Float32Array(24);
|
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
/**
|
|
13
|
+
* NOTE: Consider using an optimized aabb projection method based on Jim Arvo's Graphics Gems algorithm: https://stackoverflow.com/a/58630206/3973586
|
|
15
14
|
* Almost everything is inlined for speed
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {AABB3} bounds
|
|
15
|
+
* @param {number[]} aabb_corners
|
|
18
16
|
* @param {number[]|mat4|Float32Array} projection_matrix
|
|
17
|
+
* @returns {number}
|
|
19
18
|
*/
|
|
20
|
-
export function aabb3_project_to_2d(
|
|
21
|
-
bounds.getCorners(scratch_corners);
|
|
19
|
+
export function aabb3_project_to_2d(aabb_corners, projection_matrix) {
|
|
22
20
|
|
|
23
21
|
// read matrix into local variables for speed
|
|
24
22
|
const a0 = projection_matrix[0];
|
|
@@ -48,9 +46,9 @@ export function aabb3_project_to_2d(result, bounds, projection_matrix) {
|
|
|
48
46
|
for (let i = 0; i < 24; i += 3) {
|
|
49
47
|
|
|
50
48
|
// read corner
|
|
51
|
-
const _x =
|
|
52
|
-
const _y =
|
|
53
|
-
const _z =
|
|
49
|
+
const _x = aabb_corners[i];
|
|
50
|
+
const _y = aabb_corners[i + 1];
|
|
51
|
+
const _z = aabb_corners[i + 2];
|
|
54
52
|
|
|
55
53
|
// apply transform
|
|
56
54
|
const t_x = a0 * _x + b0 * _y + c0 * _z + d0;
|
|
@@ -58,7 +56,7 @@ export function aabb3_project_to_2d(result, bounds, projection_matrix) {
|
|
|
58
56
|
const t_w = a3 * _x + b3 * _y + c3 * _z + d3;
|
|
59
57
|
|
|
60
58
|
// perspective divide and normalization (-1,1 space projected to -0.5,0.5)
|
|
61
|
-
const d = 0.5 /
|
|
59
|
+
const d = 0.5 / t_w;
|
|
62
60
|
|
|
63
61
|
// finally compute screen-space coordinates of the corner
|
|
64
62
|
const x = t_x * d;
|
|
@@ -67,18 +65,22 @@ export function aabb3_project_to_2d(result, bounds, projection_matrix) {
|
|
|
67
65
|
if (x0 > x) {
|
|
68
66
|
x0 = x;
|
|
69
67
|
}
|
|
70
|
-
if (y0 > y) {
|
|
71
|
-
y0 = y;
|
|
72
|
-
}
|
|
73
68
|
|
|
74
69
|
if (x1 < x) {
|
|
75
70
|
x1 = x;
|
|
76
71
|
}
|
|
72
|
+
|
|
73
|
+
if (y0 > y) {
|
|
74
|
+
y0 = y;
|
|
75
|
+
}
|
|
77
76
|
if (y1 < y) {
|
|
78
77
|
y1 = y;
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
const dx = x1 - x0;
|
|
83
|
+
const dy = y1 - y0;
|
|
84
|
+
|
|
85
|
+
return dx * dy;
|
|
84
86
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const scratch_aabb = new Float32Array(4);
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NOTE: tends to overestimate the area
|
|
6
|
+
* @param {number[]} aabb
|
|
7
|
+
* @param {number[]} matrix
|
|
8
|
+
* @return {number}
|
|
9
|
+
*/
|
|
10
|
+
export function aabb3_estimate_projected_area2(aabb, matrix) {
|
|
11
|
+
// extract translation from matrix
|
|
12
|
+
scratch_aabb[0] = scratch_aabb[2] = matrix[12];
|
|
13
|
+
scratch_aabb[1] = scratch_aabb[3] = matrix[13];
|
|
14
|
+
|
|
15
|
+
// apply 3x3 matrix transform
|
|
16
|
+
for (let i = 0; i < 2; i++) {
|
|
17
|
+
for (let j = 0; j < 3; j++) {
|
|
18
|
+
|
|
19
|
+
const m_a = i * 4 + j;
|
|
20
|
+
const m_v = matrix[m_a];
|
|
21
|
+
|
|
22
|
+
const a = m_v * aabb[j];
|
|
23
|
+
const b = m_v * aabb[j + 3];
|
|
24
|
+
|
|
25
|
+
if (a < b) {
|
|
26
|
+
scratch_aabb[i] += a;
|
|
27
|
+
scratch_aabb[i + 2] += b;
|
|
28
|
+
} else {
|
|
29
|
+
scratch_aabb[i] += b;
|
|
30
|
+
scratch_aabb[i + 2] += a;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const x1 = scratch_aabb[2];
|
|
37
|
+
const x0 = scratch_aabb[0];
|
|
38
|
+
|
|
39
|
+
const dx = x1 - x0;
|
|
40
|
+
|
|
41
|
+
const y1 = scratch_aabb[3];
|
|
42
|
+
const y0 = scratch_aabb[1];
|
|
43
|
+
|
|
44
|
+
const dy = y1 - y0;
|
|
45
|
+
const a = dx * dy;
|
|
46
|
+
|
|
47
|
+
const cx = (aabb[0] + aabb[3]) * 0.5;
|
|
48
|
+
const cy = (aabb[1] + aabb[4]) * 0.5;
|
|
49
|
+
const cz = (aabb[2] + aabb[5]) * 0.5;
|
|
50
|
+
|
|
51
|
+
/* compute W projection value, using conservative estimate
|
|
52
|
+
@see https://twitter.com/SebAaltonen/status/1332332808979832832
|
|
53
|
+
@see https://gist.github.com/slembcke/b2b2af4dede1d5702a635dc2d0e45d54
|
|
54
|
+
*/
|
|
55
|
+
const w = matrix[3] * cx + matrix[7] * cy + matrix[11] * cz + matrix[15];
|
|
56
|
+
const d = 0.5 / Math.abs(w);
|
|
57
|
+
|
|
58
|
+
return a * d * d;
|
|
59
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* NOTE: Based on Transforming Axis-Aligned Bounding Boxes by Jim Arvo from "Graphics Gems", Academic Press, 1990
|
|
4
|
+
* @param {number[]} result
|
|
5
|
+
* @param {number[]} aabb
|
|
6
|
+
* @param {number[]} matrix 4x4 matrix
|
|
7
|
+
*/
|
|
8
|
+
export function aabb3_matrix4_project(result, aabb, matrix) {
|
|
9
|
+
// extract translation from matrix
|
|
10
|
+
result[0] = result[3] = matrix[12];
|
|
11
|
+
result[1] = result[4] = matrix[13];
|
|
12
|
+
result[2] = result[5] = matrix[14];
|
|
13
|
+
|
|
14
|
+
// apply 3x3 matrix transform
|
|
15
|
+
for (let i = 0; i < 3; i++) {
|
|
16
|
+
for (let j = 0; j < 3; j++) {
|
|
17
|
+
|
|
18
|
+
const m_a = i * 4 + j;
|
|
19
|
+
const m_v = matrix[m_a];
|
|
20
|
+
|
|
21
|
+
const a = m_v * aabb[j];
|
|
22
|
+
const b = m_v * aabb[j + 3];
|
|
23
|
+
|
|
24
|
+
if (a < b) {
|
|
25
|
+
result[i] += a;
|
|
26
|
+
result[i + 3] += b;
|
|
27
|
+
} else {
|
|
28
|
+
result[i] += b;
|
|
29
|
+
result[i + 3] += a;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { aabb3_matrix4_project } from "./aabb3_matrix4_project.js";
|
|
2
|
+
|
|
3
|
+
test('identity', () => {
|
|
4
|
+
const r = [];
|
|
5
|
+
|
|
6
|
+
aabb3_matrix4_project(r, [1, 2, 3, 5, 7, 9], [
|
|
7
|
+
1, 0, 0, 0,
|
|
8
|
+
0, 1, 0, 0,
|
|
9
|
+
0, 0, 1, 0,
|
|
10
|
+
0, 0, 0, 1
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
expect(r).toEqual([1, 2, 3, 5, 7, 9]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('translation case', () => {
|
|
17
|
+
const r = [];
|
|
18
|
+
|
|
19
|
+
aabb3_matrix4_project(r, [1, 2, 3, 5, 7, 9], [
|
|
20
|
+
1, 0, 0, 0,
|
|
21
|
+
0, 1, 0, 0,
|
|
22
|
+
0, 0, 1, 0,
|
|
23
|
+
13, -17, 23, 1
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
expect(r).toEqual([14, -15, 26, 18, -10, 32]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
test('scale case', () => {
|
|
31
|
+
const r = [];
|
|
32
|
+
|
|
33
|
+
aabb3_matrix4_project(r, [1, 2, 3, 5, 7, 9], [
|
|
34
|
+
-1, 0, 0, 0,
|
|
35
|
+
0, 2, 0, 0,
|
|
36
|
+
0, 0, -3, 0,
|
|
37
|
+
0, 0, 0, 1
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
expect(r).toEqual([-5, 4, -27, -1, 14, -9]);
|
|
41
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lerp } from "../../../math/lerp.js";
|
|
2
|
-
import Vector3, { v3_dot,
|
|
2
|
+
import Vector3, { v3_dot, v3_length } from "../../Vector3.js";
|
|
3
3
|
import { plane3_intersect_plane } from "./plane3_intersect_plane.js";
|
|
4
4
|
|
|
5
5
|
const v0 = new Vector3();
|
|
@@ -32,7 +32,7 @@ export function plane3_lerp(
|
|
|
32
32
|
let normal_z = lerp(a_normal_z, b_normal_z, t);
|
|
33
33
|
|
|
34
34
|
// normalize the normal vector
|
|
35
|
-
const normal_length =
|
|
35
|
+
const normal_length = v3_length(normal_x, normal_y, normal_z);
|
|
36
36
|
const normal_length_inv = 1 / normal_length;
|
|
37
37
|
|
|
38
38
|
normal_x *= normal_length_inv;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v3_length } from "../../Vector3.js";
|
|
2
2
|
import { array_replace_all } from "../../../collection/array/array_replace_all.js";
|
|
3
3
|
import { array_push_if_unique } from "../../../collection/array/array_push_if_unique.js";
|
|
4
4
|
import { assert } from "../../../assert.js";
|
|
@@ -40,7 +40,7 @@ export function compute_triangle_normal(result, vA, vB, vC) {
|
|
|
40
40
|
const crossY = vCBz * vABx - vCBx * vABz;
|
|
41
41
|
const crossZ = vCBx * vABy - vCBy * vABx;
|
|
42
42
|
|
|
43
|
-
const l =
|
|
43
|
+
const l = v3_length(crossX, crossY, crossZ);
|
|
44
44
|
|
|
45
45
|
if (l === 0) {
|
|
46
46
|
// degenerate triangle, provide arbitrary invalid result
|
package/core/geom/AABB2.d.ts
CHANGED
package/core/geom/Matrix4.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Vector3, {
|
|
1
|
+
import Vector3, { v3_length } from "./Vector3.js";
|
|
2
2
|
|
|
3
3
|
const _z = new Vector3();
|
|
4
4
|
const _x = new Vector3();
|
|
@@ -192,9 +192,9 @@ export class Matrix4 {
|
|
|
192
192
|
decompose(position, rotation, scale) {
|
|
193
193
|
|
|
194
194
|
|
|
195
|
-
var sx =
|
|
196
|
-
var sy =
|
|
197
|
-
var sz =
|
|
195
|
+
var sx = v3_length(this.a0, this.a1, this.a2);
|
|
196
|
+
var sy = v3_length(this.b0, this.b1, this.b2);
|
|
197
|
+
var sz = v3_length(this.c0, this.c1, this.c2);
|
|
198
198
|
|
|
199
199
|
// if determine is negative, we need to invert one scale
|
|
200
200
|
var det = this.determinant();
|
package/core/geom/Vector3.js
CHANGED
|
@@ -883,7 +883,7 @@ class Vector3 {
|
|
|
883
883
|
* @returns {number}
|
|
884
884
|
*/
|
|
885
885
|
static distance(a, b) {
|
|
886
|
-
return
|
|
886
|
+
return v3_length(a.x - b.x, a.y - b.y, a.z - b.z);
|
|
887
887
|
}
|
|
888
888
|
}
|
|
889
889
|
|
|
@@ -1008,10 +1008,10 @@ export function v3_distance_sqr(x0, y0, z0, x1, y1, z1) {
|
|
|
1008
1008
|
|
|
1009
1009
|
|
|
1010
1010
|
function v3Length(v) {
|
|
1011
|
-
return
|
|
1011
|
+
return v3_length(v.x, v.y, v.z);
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
|
-
export function
|
|
1014
|
+
export function v3_length(x, y, z) {
|
|
1015
1015
|
return Math.sqrt(v3_length_sqr(x, y, z));
|
|
1016
1016
|
}
|
|
1017
1017
|
|
|
@@ -1040,8 +1040,8 @@ export function v3_length_sqr(x, y, z) {
|
|
|
1040
1040
|
export function v3_angleBetween(x0, y0, z0, x1, y1, z1) {
|
|
1041
1041
|
const d = v3_dot(x0, y0, z0, x1, y1, z1);
|
|
1042
1042
|
|
|
1043
|
-
const magnitude_0 =
|
|
1044
|
-
const magnitude_1 =
|
|
1043
|
+
const magnitude_0 = v3_length(x0, y0, z0);
|
|
1044
|
+
const magnitude_1 = v3_length(x1, y1, z1);
|
|
1045
1045
|
|
|
1046
1046
|
const l = magnitude_0 * magnitude_1;
|
|
1047
1047
|
|
|
@@ -64,9 +64,15 @@ export class ReactiveReference extends ReactiveExpression {
|
|
|
64
64
|
assert.notEqual(source, null, 'source is null');
|
|
65
65
|
assert.notEqual(source, undefined, 'source is undefined');
|
|
66
66
|
assert.typeOf(source.onChanged, 'object', 'source.onChanged');
|
|
67
|
-
assert.
|
|
67
|
+
assert.isFunction(source.onChanged.add, 'source.onChanged.add');
|
|
68
68
|
|
|
69
69
|
if (this.source !== null) {
|
|
70
|
+
|
|
71
|
+
if (this.source === source) {
|
|
72
|
+
// already connected to this source, do nothing
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
70
76
|
throw new Error('source is already set. Already connected');
|
|
71
77
|
}
|
|
72
78
|
|
|
@@ -202,6 +202,64 @@ export class ActionProcessor {
|
|
|
202
202
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Navigate to a specific mark back or forward
|
|
207
|
+
* @param {M} mark_descriptor specific mark description
|
|
208
|
+
* @returns {boolean} true on success, false otherwise (e.g. mark not found)
|
|
209
|
+
* @throws {Error} when mark is non-unique
|
|
210
|
+
*/
|
|
211
|
+
navigateTo(mark_descriptor) {
|
|
212
|
+
// find all matching marks
|
|
213
|
+
const matching_marks = this.marks.filter(m => m.description === mark_descriptor);
|
|
214
|
+
|
|
215
|
+
if (matching_marks.length === 0) {
|
|
216
|
+
// not found
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (matching_marks.length > 1) {
|
|
221
|
+
throw new Error(`Attempting to navigate to a non-unique mark descriptor '${mark_descriptor}'. Mark descriptor must be unique, instead ${matching_marks.length} matches were found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const match = matching_marks[0];
|
|
225
|
+
|
|
226
|
+
const target = match.index;
|
|
227
|
+
|
|
228
|
+
let temp_cursor = this.cursor;
|
|
229
|
+
|
|
230
|
+
if (target > this.cursor) {
|
|
231
|
+
|
|
232
|
+
while (target > this.cursor) {
|
|
233
|
+
// navigate forward
|
|
234
|
+
this.redo();
|
|
235
|
+
|
|
236
|
+
if (temp_cursor === this.cursor) {
|
|
237
|
+
// no cursor change
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
temp_cursor = this.cursor;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
} else if (target < this.cursor) {
|
|
245
|
+
|
|
246
|
+
while (target < this.cursor) {
|
|
247
|
+
// navigate backwards
|
|
248
|
+
this.undo();
|
|
249
|
+
|
|
250
|
+
if (temp_cursor === this.cursor) {
|
|
251
|
+
// no cursor change
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
temp_cursor = this.cursor;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
|
|
205
263
|
undo() {
|
|
206
264
|
let markAddress = 0;
|
|
207
265
|
/**
|
|
@@ -226,7 +284,7 @@ export class ActionProcessor {
|
|
|
226
284
|
markAddress = 0;
|
|
227
285
|
}
|
|
228
286
|
|
|
229
|
-
//keep rewinding until we hit mark
|
|
287
|
+
//keep rewinding until we hit a mark
|
|
230
288
|
while (this.cursor > markAddress && this.cursor > 0) {
|
|
231
289
|
this.cursor--;
|
|
232
290
|
const action = this.history.get(this.cursor);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ActionProcessor } from "./ActionProcessor.js";
|
|
2
|
+
import { Action } from "./Action.js";
|
|
3
|
+
|
|
4
|
+
class DummyContext {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.value = 0;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class DummyAction extends Action {
|
|
11
|
+
apply(context) {
|
|
12
|
+
// do nothing
|
|
13
|
+
context.value++;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
revert(context) {
|
|
17
|
+
context.value--;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test('navigateTo backwards', () => {
|
|
22
|
+
const ctx = new DummyContext();
|
|
23
|
+
const ap = new ActionProcessor(ctx);
|
|
24
|
+
|
|
25
|
+
ap.mark('a');
|
|
26
|
+
ap.do(new DummyAction());
|
|
27
|
+
ap.mark('b');
|
|
28
|
+
ap.do(new DummyAction());
|
|
29
|
+
|
|
30
|
+
expect(ap.navigateTo('a')).toBe(true);
|
|
31
|
+
|
|
32
|
+
expect(ctx.value).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('navigateTo forward', () => {
|
|
36
|
+
const ctx = new DummyContext();
|
|
37
|
+
const ap = new ActionProcessor(ctx);
|
|
38
|
+
|
|
39
|
+
ap.mark('a');
|
|
40
|
+
ap.do(new DummyAction());
|
|
41
|
+
ap.mark('b');
|
|
42
|
+
ap.do(new DummyAction());
|
|
43
|
+
ap.mark('c');
|
|
44
|
+
|
|
45
|
+
ap.undo();
|
|
46
|
+
ap.undo();
|
|
47
|
+
ap.undo();
|
|
48
|
+
|
|
49
|
+
expect(ap.navigateTo('c')).toBe(true);
|
|
50
|
+
|
|
51
|
+
expect(ctx.value).toBe(2);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('navigateTo non-existent on empty', () => {
|
|
55
|
+
const ctx = new DummyContext();
|
|
56
|
+
const ap = new ActionProcessor(ctx);
|
|
57
|
+
|
|
58
|
+
expect(ap.navigateTo('a')).toBe(false);
|
|
59
|
+
});
|
|
@@ -8,13 +8,14 @@ export class Mark {
|
|
|
8
8
|
* @constructor
|
|
9
9
|
*/
|
|
10
10
|
constructor(index, description) {
|
|
11
|
-
assert.
|
|
11
|
+
assert.isNumber(index, 'index');
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
15
|
* @type {number}
|
|
16
16
|
*/
|
|
17
17
|
this.index = index;
|
|
18
|
+
|
|
18
19
|
/**
|
|
19
20
|
*
|
|
20
21
|
* @type {D}
|