@woosh/meep-engine 2.39.36 → 2.39.39
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/LICENSE +13 -0
- package/core/assert.js +14 -5
- package/core/binary/Base64.js +58 -31
- package/core/binary/Base64.spec.js +14 -0
- package/core/bvh2/aabb3/AABB3.js +2 -2
- package/core/bvh2/aabb3/aabb3_detailed_volume_intersection.js +3 -2
- package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +2 -2
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +7 -0
- package/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +149 -6
- package/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.spec.js +41 -0
- package/core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js +2 -2
- package/core/bvh2/traversal/__process_point_if_within_planes.js +2 -2
- package/core/bvh2/traversal/aabb3_detailed_volume_intersection_callback_based.js +3 -0
- package/core/collection/array/computeHashArray.d.ts +1 -0
- package/core/color/Color.js +7 -3
- package/core/geom/3d/aabb/aabb3_computeDistanceAbovePlane_max.spec.js +8 -0
- package/core/geom/3d/aabb/{aabb3_computeDistanceAbovePlane.js → aabb3_compute_distance_above_plane_max.js} +3 -2
- package/core/geom/3d/aabb/computeAABB3PlaneSide.js +3 -3
- package/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +3 -2
- package/core/geom/3d/plane/is_point_within_planes.js +2 -2
- package/core/geom/3d/plane/plane3_projectPoint.js +2 -2
- package/core/geom/3d/plane/plane3_projectPoint.spec.js +54 -0
- package/core/geom/Plane.js +0 -19
- package/core/geom/Quaternion.js +52 -38
- package/core/geom/v3_distance_above_plane.js +20 -0
- package/core/geom/v3_distance_above_plane.spec.js +40 -0
- package/core/math/statistics/halton_sequence.js +26 -0
- package/core/model/ModuleRegistry.js +1 -1
- package/core/model/reactive/model/terminal/ReactiveReference.js +1 -1
- package/core/model/reactive/trigger/ReactiveTrigger.js +14 -4
- package/editor/ecs/component/editors/ImagePathEditor.js +83 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +76 -16
- package/engine/ecs/EntityComponentDataset.js +18 -28
- package/engine/ecs/terrain/ecs/splat/SplatMapping.js +27 -4
- package/engine/graphics/GraphicsEngine.d.ts +2 -2
- package/engine/graphics/GraphicsEngine.js +11 -15
- package/engine/graphics/composit/LayerCompositer.js +1 -0
- package/engine/graphics/ecs/camera/Camera.js +2 -2
- package/engine/graphics/ecs/camera/CameraSystem.js +6 -0
- package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +14 -6
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +2 -1
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +17 -2
- package/engine/graphics/ecs/mesh-v2/aggregate/prototypeSGMesh.js +17 -20
- package/engine/graphics/filter/FlipArrayInPlace.js +11 -6
- package/engine/graphics/geometry/clipping/ClippedGeometry.js +4 -4
- package/engine/graphics/micron/prototypeVirtualGeometry.js +3 -1
- package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +2 -0
- package/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +95 -0
- package/engine/graphics/render/buffer/simple-fx/taa/prototypeTAA.js +61 -0
- package/engine/graphics/render/forward_plus/LightManager.js +4 -4
- package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +6 -7
- package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +6 -2
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_objects.js +4 -2
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +4 -2
- package/engine/graphics/render/frame_graph/GraphNode.js +22 -0
- package/engine/graphics/render/frame_graph/RenderGraph.js +405 -0
- package/engine/graphics/render/frame_graph/RenderGraphBuilder.js +77 -0
- package/engine/graphics/render/frame_graph/RenderPass.js +30 -12
- package/engine/graphics/render/frame_graph/RenderPassNode.js +103 -0
- package/engine/graphics/render/frame_graph/RenderPassResources.js +54 -4
- package/engine/graphics/render/frame_graph/ResourceEntry.js +77 -0
- package/engine/graphics/render/frame_graph/ResourceNode.js +23 -0
- package/engine/graphics/render/frame_graph/TextureDescriptor.js +38 -4
- package/engine/graphics/render/frame_graph/sample/deferred/GBufferDrawPass.js +11 -5
- package/engine/graphics/render/frame_graph/sample/deferred/LightingPass.js +24 -0
- package/engine/graphics/render/frame_graph/sample/deferred/run.js +31 -0
- package/engine/graphics/render/frame_graph/sample/meep-v1/ColorDepthPass.js +38 -0
- package/engine/graphics/render/frame_graph/sample/meep-v1/OutlinePass.js +9 -0
- package/engine/graphics/render/frame_graph/sample/meep-v1/SSAOPass.js +5 -0
- package/engine/graphics/render/frame_graph/sample/meep-v1/render.js +7 -0
- package/engine/graphics/render/frame_graph/webgl/WebGLRenderContext.js +5 -0
- package/engine/graphics/render/layers/RenderLayerUtils.js +5 -3
- package/engine/graphics/render/view/CameraView.js +38 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +22 -2
- package/engine/knowledge/database/DATABASE_SERIALIZATION_IGNORE_PROPERTY.js +1 -0
- package/engine/knowledge/database/StaticKnowledgeDataTable.js +5 -4
- package/package.json +1 -1
- package/view/elements/button/ButtonView.js +12 -1
- package/core/geom/Plane.spec.js +0 -12
- package/engine/graphics/render/frame_graph/FrameGraphBuilder.js +0 -36
- package/engine/graphics/render/frame_graph/Resource.js +0 -21
- package/engine/graphics/render/frame_graph/ResourceReference.js +0 -14
- package/engine/graphics/render/frame_graph/UsageModeType.js +0 -5
- package/engine/graphics/render/frame_graph/sample/deferred/PresentPass.js +0 -17
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Please note that this package comes without a license.
|
|
2
|
+
No permission is granted for any kind of usage.
|
|
3
|
+
All rights are reserved by the author.
|
|
4
|
+
|
|
5
|
+
For illustration purposes, this means that unless you have obtained a license, all of the following terms apply:
|
|
6
|
+
* You are NOT permitted to make copies of this package
|
|
7
|
+
* You are NOT permitted to re-distribute this package
|
|
8
|
+
* You are NOT permitted to extend the code from this package
|
|
9
|
+
* You are NOT permitted to make use of this package for any purpose, commercial or otherwise
|
|
10
|
+
|
|
11
|
+
If you would like to use this package in any context, please contact me via email so we can arrange a license:
|
|
12
|
+
|
|
13
|
+
travnick [at] gmail [d0t] com
|
package/core/assert.js
CHANGED
|
@@ -280,18 +280,27 @@ assert.isFunction = function (value, name = 'value') {
|
|
|
280
280
|
* @param {number|*} value
|
|
281
281
|
* @param {string} [name]
|
|
282
282
|
*/
|
|
283
|
-
assert.
|
|
283
|
+
assert.isInteger = function (value, name = 'value') {
|
|
284
284
|
assert.isNumber(value, name);
|
|
285
285
|
|
|
286
|
-
if (value < 0) {
|
|
287
|
-
throw new Error(`${name} must be >= 0, instead was ${value}`);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
286
|
if (!Number.isInteger(value)) {
|
|
291
287
|
throw new Error(`${name} must be an integer, instead was ${value}`);
|
|
292
288
|
}
|
|
293
289
|
}
|
|
294
290
|
|
|
291
|
+
/**
|
|
292
|
+
*
|
|
293
|
+
* @param {number|*} value
|
|
294
|
+
* @param {string} [name]
|
|
295
|
+
*/
|
|
296
|
+
assert.isNonNegativeInteger = function (value, name = 'value') {
|
|
297
|
+
assert.isInteger(value, name);
|
|
298
|
+
|
|
299
|
+
if (value < 0) {
|
|
300
|
+
throw new Error(`${name} must be >= 0, instead was ${value}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
295
304
|
/**
|
|
296
305
|
* @template T
|
|
297
306
|
* @param {T[]} value
|
package/core/binary/Base64.js
CHANGED
|
@@ -3,13 +3,21 @@
|
|
|
3
3
|
* @author Jameson Little
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @type {string[]}
|
|
9
|
+
*/
|
|
10
|
+
const lookup = [];
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @type {number[]}
|
|
14
|
+
*/
|
|
15
|
+
const revLookup = [];
|
|
16
|
+
const Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
const code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
11
19
|
|
|
12
|
-
for (
|
|
20
|
+
for (let i = 0, len = code.length; i < len; ++i) {
|
|
13
21
|
lookup[i] = code[i];
|
|
14
22
|
revLookup[code.charCodeAt(i)] = i;
|
|
15
23
|
}
|
|
@@ -19,6 +27,11 @@ for (var i = 0, len = code.length; i < len; ++i) {
|
|
|
19
27
|
revLookup['-'.charCodeAt(0)] = 62;
|
|
20
28
|
revLookup['_'.charCodeAt(0)] = 63;
|
|
21
29
|
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {string} b64
|
|
33
|
+
* @return {number[]}
|
|
34
|
+
*/
|
|
22
35
|
function getLens(b64) {
|
|
23
36
|
var len = b64.length;
|
|
24
37
|
|
|
@@ -41,12 +54,6 @@ function getLens(b64) {
|
|
|
41
54
|
}
|
|
42
55
|
|
|
43
56
|
// base64 is 4/3 + up to two characters of the original data
|
|
44
|
-
function byteLength(b64) {
|
|
45
|
-
var lens = getLens(b64);
|
|
46
|
-
var validLen = lens[0];
|
|
47
|
-
var placeHoldersLen = lens[1];
|
|
48
|
-
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;
|
|
49
|
-
}
|
|
50
57
|
|
|
51
58
|
function _byteLength(b64, validLen, placeHoldersLen) {
|
|
52
59
|
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen;
|
|
@@ -99,37 +106,57 @@ function toByteArray(b64) {
|
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
function tripletToBase64(num) {
|
|
102
|
-
return lookup[num >> 18 & 0x3F]
|
|
103
|
-
lookup[num >> 12 & 0x3F]
|
|
104
|
-
lookup[num >> 6 & 0x3F]
|
|
105
|
-
lookup[num & 0x3F]
|
|
109
|
+
return lookup[num >> 18 & 0x3F]
|
|
110
|
+
+ lookup[num >> 12 & 0x3F]
|
|
111
|
+
+ lookup[num >> 6 & 0x3F]
|
|
112
|
+
+ lookup[num & 0x3F]
|
|
113
|
+
;
|
|
106
114
|
}
|
|
107
115
|
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @param {Uint8Array} uint8
|
|
119
|
+
* @param {number} start
|
|
120
|
+
* @param {number} end
|
|
121
|
+
* @return {string}
|
|
122
|
+
*/
|
|
108
123
|
function encodeChunk(uint8, start, end) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
for (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
((uint8[i + 1] << 8) & 0xFF00)
|
|
115
|
-
(uint8[i + 2] & 0xFF);
|
|
124
|
+
const output = [];
|
|
125
|
+
|
|
126
|
+
for (let i = start; i < end; i += 3) {
|
|
127
|
+
|
|
128
|
+
const tmp = ((uint8[i] << 16) & 0xFF0000)
|
|
129
|
+
+ ((uint8[i + 1] << 8) & 0xFF00)
|
|
130
|
+
+ (uint8[i + 2] & 0xFF);
|
|
131
|
+
|
|
116
132
|
output.push(tripletToBase64(tmp));
|
|
117
133
|
}
|
|
134
|
+
|
|
118
135
|
return output.join('');
|
|
119
136
|
}
|
|
120
137
|
|
|
138
|
+
/**
|
|
139
|
+
*
|
|
140
|
+
* @param {Uint8Array} uint8
|
|
141
|
+
* @return {string}
|
|
142
|
+
*/
|
|
121
143
|
function fromByteArray(uint8) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
let tmp;
|
|
145
|
+
|
|
146
|
+
const len = uint8.length;
|
|
147
|
+
const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
|
|
148
|
+
const parts = [];
|
|
149
|
+
const maxChunkLength = 16383; // must be multiple of 3
|
|
127
150
|
|
|
128
151
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
));
|
|
152
|
+
const len2 = len - extraBytes;
|
|
153
|
+
|
|
154
|
+
for (let i = 0; i < len2; i += maxChunkLength) {
|
|
155
|
+
const end = (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength);
|
|
156
|
+
|
|
157
|
+
const chunk = encodeChunk(uint8, i, end);
|
|
158
|
+
|
|
159
|
+
parts.push(chunk);
|
|
133
160
|
}
|
|
134
161
|
|
|
135
162
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Base64 } from "./Base64.js";
|
|
2
|
+
|
|
3
|
+
test("to/from consistency", () => {
|
|
4
|
+
const source = new Uint8Array(256);
|
|
5
|
+
for (let i = 0; i < source.length; i++) {
|
|
6
|
+
source[i] = i;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const encoded = Base64.encode(source.buffer);
|
|
10
|
+
|
|
11
|
+
const decoded = Base64.decode(encoded);
|
|
12
|
+
|
|
13
|
+
expect(Array.from(new Uint8Array(decoded))).toEqual(Array.from(source));
|
|
14
|
+
});
|
package/core/bvh2/aabb3/AABB3.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { aabb3_computeDistanceAbovePlane_max } from "../../geom/3d/aabb/aabb3_compute_distance_above_plane_max.js";
|
|
7
7
|
import { computeAABB3PlaneSide } from "../../geom/3d/aabb/computeAABB3PlaneSide.js";
|
|
8
8
|
import computeMortonCode from "../../geom/3d/morton/Morton.js";
|
|
9
9
|
import { aabb3_build_corners } from "../../geom/3d/aabb/aabb3_build_corners.js";
|
|
@@ -795,7 +795,7 @@ export class AABB3 {
|
|
|
795
795
|
* @returns {number}
|
|
796
796
|
*/
|
|
797
797
|
computeDistanceAbovePlane(normal_x, normal_y, normal_z, offset) {
|
|
798
|
-
return
|
|
798
|
+
return aabb3_computeDistanceAbovePlane_max(
|
|
799
799
|
normal_x, normal_y, normal_z, offset,
|
|
800
800
|
this.x0, this.y0, this.z0,
|
|
801
801
|
this.x1, this.y1, this.z1
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { aabb3_build_corners } from "../../geom/3d/aabb/aabb3_build_corners.js";
|
|
2
2
|
import { aabb_build_frustum } from "../../geom/3d/aabb/aabb3_build_frustum.js";
|
|
3
|
-
import {
|
|
3
|
+
import { plane3_computeLineSegmentIntersection } from "../../geom/Plane.js";
|
|
4
4
|
import { aabb3_corner_edge_mapping } from "./aabb3_corner_edge_mapping.js";
|
|
5
5
|
import { aabb3_edge_corner_mapping } from "./aabb3_edge_corner_mapping.js";
|
|
6
6
|
import { plane_computeConvex3PlaneIntersection } from "../../geom/3d/plane/plane_computeConvex3PlaneIntersection.js";
|
|
7
7
|
import { EPSILON } from "../../math/MathUtils.js";
|
|
8
8
|
import { is_point_within_planes } from "../../geom/3d/plane/is_point_within_planes.js";
|
|
9
|
+
import { v3_distance_above_plane } from "../../geom/v3_distance_above_plane.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Common piece of continuous memory for better cache coherence
|
|
@@ -120,7 +121,7 @@ export function aabb3_detailed_volume_intersection(
|
|
|
120
121
|
const nz = planes[plane_address + 2];
|
|
121
122
|
const c = planes[plane_address + 3];
|
|
122
123
|
|
|
123
|
-
const distance_to_plane =
|
|
124
|
+
const distance_to_plane = v3_distance_above_plane(
|
|
124
125
|
x, y, z,
|
|
125
126
|
nx, ny, nz, c
|
|
126
127
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aabb3_computeDistanceAbovePlane_max } from "../../geom/3d/aabb/aabb3_compute_distance_above_plane_max.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
@@ -19,7 +19,7 @@ export function aabb3_intersects_frustum_array(x0, y0, z0, x1, y1, z1, frustum)
|
|
|
19
19
|
const plane_z = frustum[i + 2];
|
|
20
20
|
const plane_w = frustum[i + 3];
|
|
21
21
|
|
|
22
|
-
const plane_distance =
|
|
22
|
+
const plane_distance = aabb3_computeDistanceAbovePlane_max(
|
|
23
23
|
plane_x, plane_y, plane_z, plane_w,
|
|
24
24
|
x0, y0, z0,
|
|
25
25
|
x1, y1, z1
|
|
@@ -299,6 +299,13 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
|
|
|
299
299
|
node_set_aabb(id, aabb) {
|
|
300
300
|
assert.isNonNegativeInteger(id, 'id');
|
|
301
301
|
|
|
302
|
+
assert.notNaN(aabb[0], 'aabb[0] x0');
|
|
303
|
+
assert.notNaN(aabb[1], 'aabb[1] y0');
|
|
304
|
+
assert.notNaN(aabb[2], 'aabb[2] z0');
|
|
305
|
+
assert.notNaN(aabb[3], 'aabb[3] x1');
|
|
306
|
+
assert.notNaN(aabb[4], 'aabb[4] y1');
|
|
307
|
+
assert.notNaN(aabb[5], 'aabb[5] z1');
|
|
308
|
+
|
|
302
309
|
const address = ELEMENT_WORD_COUNT * id;
|
|
303
310
|
const float32 = this.__data_float32;
|
|
304
311
|
|
|
@@ -1,13 +1,156 @@
|
|
|
1
1
|
//
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
import { array_copy } from "../../../collection/array/copyArray.js";
|
|
5
|
+
import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
6
|
+
import { aabb3_array_intersects_frustum_degree } from "../../aabb3/aabb3_array_intersects_frustum_degree.js";
|
|
7
|
+
import { bvh_collect_user_data } from "../bvh_collect_user_data.js";
|
|
8
|
+
import { v3_distance_above_plane } from "../../../geom/v3_distance_above_plane.js";
|
|
9
|
+
|
|
10
|
+
const traversal_stack = [];
|
|
11
|
+
|
|
12
|
+
const scratch_aabb = [];
|
|
13
|
+
|
|
4
14
|
/**
|
|
5
|
-
*
|
|
6
|
-
* @param result
|
|
7
|
-
* @param result_offset
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
15
|
+
*
|
|
16
|
+
* @param {number[]} result
|
|
17
|
+
* @param {number} result_offset
|
|
18
|
+
* @param {number} constrained_planes_mask if bit is set to 1, that plane is not allowed to move
|
|
19
|
+
* @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
|
|
20
|
+
* @param {number[]|ArrayLike<number>|Float32Array} frustum
|
|
10
21
|
*/
|
|
11
|
-
export function compute_tight_near_far_clipping_planes(result, result_offset, bvh, frustum) {
|
|
22
|
+
export function compute_tight_near_far_clipping_planes(result, result_offset, constrained_planes_mask, bvh, frustum) {
|
|
23
|
+
// initialize result
|
|
24
|
+
array_copy(frustum, 0, result, result_offset, 24);
|
|
25
|
+
|
|
26
|
+
const root = bvh.root;
|
|
27
|
+
|
|
28
|
+
if (root === NULL_NODE) {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @type {number}
|
|
35
|
+
*/
|
|
36
|
+
let traversal_cursor = 1;
|
|
37
|
+
|
|
38
|
+
traversal_stack[0] = root;
|
|
39
|
+
|
|
40
|
+
let result_cursor = result_offset;
|
|
41
|
+
|
|
42
|
+
// 0 is the nearest point along the normal and 1 is the furthest
|
|
43
|
+
let x0,
|
|
44
|
+
y0,
|
|
45
|
+
z0,
|
|
46
|
+
x1,
|
|
47
|
+
y1,
|
|
48
|
+
z1;
|
|
49
|
+
|
|
50
|
+
node_loop: while (traversal_cursor > 0) {
|
|
51
|
+
traversal_cursor--;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
const node = traversal_stack[traversal_cursor];
|
|
58
|
+
|
|
59
|
+
// test node against the ray
|
|
60
|
+
bvh.node_get_aabb(node, scratch_aabb);
|
|
61
|
+
|
|
62
|
+
const _x0 = scratch_aabb[0];
|
|
63
|
+
const _y0 = scratch_aabb[1];
|
|
64
|
+
const _z0 = scratch_aabb[2];
|
|
65
|
+
const _x1 = scratch_aabb[3];
|
|
66
|
+
const _y1 = scratch_aabb[4];
|
|
67
|
+
const _z1 = scratch_aabb[5];
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < 6; i++) {
|
|
70
|
+
const plane_address = i * 4;
|
|
71
|
+
|
|
72
|
+
//read out plane
|
|
73
|
+
const plane_normal_x = frustum[plane_address];
|
|
74
|
+
const plane_normal_y = frustum[plane_address + 1];
|
|
75
|
+
const plane_normal_z = frustum[plane_address + 2];
|
|
76
|
+
const plane_offset = frustum[plane_address + 3];
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// construct nearest and farthest corners along the plane normal
|
|
80
|
+
if (plane_normal_x > 0) {
|
|
81
|
+
x0 = _x0;
|
|
82
|
+
x1 = _x1;
|
|
83
|
+
} else {
|
|
84
|
+
x0 = _x1;
|
|
85
|
+
x1 = _x0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (plane_normal_y > 0) {
|
|
89
|
+
y0 = _y0;
|
|
90
|
+
y1 = _y1;
|
|
91
|
+
} else {
|
|
92
|
+
y0 = _y1;
|
|
93
|
+
y1 = _y0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (plane_normal_z > 0) {
|
|
97
|
+
z0 = _z0;
|
|
98
|
+
z1 = _z1;
|
|
99
|
+
} else {
|
|
100
|
+
z0 = _z1;
|
|
101
|
+
z1 = _z0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const distance_above_plane = v3_distance_above_plane(
|
|
105
|
+
x1, y1, z1,
|
|
106
|
+
plane_normal_x, plane_normal_y, plane_normal_z, plane_offset
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (distance_above_plane < 0) {
|
|
110
|
+
// below plane, reject this branch
|
|
111
|
+
continue node_loop;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if ((constrained_planes_mask & (1 << i)) !== 0) {
|
|
115
|
+
// plane is constrained, we're done here
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const intersection = aabb3_array_intersects_frustum_degree(scratch_aabb, frustum);
|
|
124
|
+
|
|
125
|
+
if (intersection === 0) {
|
|
126
|
+
// fully outside
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const node_is_leaf = bvh.node_is_leaf(node);
|
|
131
|
+
|
|
132
|
+
if (!node_is_leaf) {
|
|
133
|
+
|
|
134
|
+
if (intersection === 2) {
|
|
135
|
+
// fully inside, fast collection path
|
|
136
|
+
result_cursor += bvh_collect_user_data(result, result_cursor, bvh, node);
|
|
137
|
+
} else {
|
|
138
|
+
// partially inside
|
|
139
|
+
// read in-order
|
|
140
|
+
const child1 = bvh.node_get_child1(node);
|
|
141
|
+
const child2 = bvh.node_get_child2(node);
|
|
142
|
+
|
|
143
|
+
// write to stack in reverse order, so that fist child ends up being visited first
|
|
144
|
+
traversal_stack[traversal_cursor++] = child1;
|
|
145
|
+
traversal_stack[traversal_cursor++] = child2;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
} else {
|
|
149
|
+
// leaf node
|
|
150
|
+
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// drop stack frame
|
|
12
155
|
|
|
13
156
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ExplicitBinaryBoundingVolumeHierarchy } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
2
|
+
import { compute_tight_near_far_clipping_planes } from "./compute_tight_near_far_clipping_planes.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function orthographic_frustum(left, right, up, down, near, far) {
|
|
6
|
+
return new Float32Array([
|
|
7
|
+
1, 0, 0, right,
|
|
8
|
+
-1, 0, 0, -left,
|
|
9
|
+
0, 1, 0, down,
|
|
10
|
+
0, -1, 0, -up,
|
|
11
|
+
0, 0, 1, far,
|
|
12
|
+
0, 0, -1, -near
|
|
13
|
+
]);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
test('Empty', () => {
|
|
17
|
+
const bvh = new ExplicitBinaryBoundingVolumeHierarchy();
|
|
18
|
+
|
|
19
|
+
const res = [];
|
|
20
|
+
|
|
21
|
+
const frustum = new Float32Array(24);
|
|
22
|
+
|
|
23
|
+
compute_tight_near_far_clipping_planes(res, 0, 0b000011, bvh, frustum);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('Axis-aligned, orthographic tight fit around a single small node', () => {
|
|
27
|
+
const frustum = orthographic_frustum(-1, 1, -1, 1, -1, 1);
|
|
28
|
+
|
|
29
|
+
const bvh = new ExplicitBinaryBoundingVolumeHierarchy();
|
|
30
|
+
|
|
31
|
+
const leaf = bvh.allocate_node();
|
|
32
|
+
bvh.node_set_aabb(leaf, [-0.1, -0.1, -0.1, 0.1, 0.1, 0.1]);
|
|
33
|
+
bvh.insert_leaf(leaf);
|
|
34
|
+
|
|
35
|
+
const res = [];
|
|
36
|
+
|
|
37
|
+
compute_tight_near_far_clipping_planes(res, 0, 0b000011, bvh, frustum);
|
|
38
|
+
|
|
39
|
+
expect(res[4 * 4 + 3]).toBeCloseTo(0.1);
|
|
40
|
+
expect(res[4 * 5 + 3]).toBeCloseTo(0.1);
|
|
41
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { computePointDistanceToPlane } from "../../geom/Plane.js";
|
|
2
1
|
import { BVHVisitor } from "./BVHVisitor.js";
|
|
3
2
|
import { read_frustum_planes_to_array } from "../../geom/3d/frustum/read_frustum_planes_to_array.js";
|
|
4
3
|
import {
|
|
5
4
|
aabb3_detailed_volume_intersection_callback_based
|
|
6
5
|
} from "./aabb3_detailed_volume_intersection_callback_based.js";
|
|
6
|
+
import { v3_distance_above_plane } from "../../geom/v3_distance_above_plane.js";
|
|
7
7
|
|
|
8
8
|
export class ThreeClippingPlaneComputingBVHVisitor extends BVHVisitor {
|
|
9
9
|
constructor() {
|
|
@@ -113,7 +113,7 @@ export class ThreeClippingPlaneComputingBVHVisitor extends BVHVisitor {
|
|
|
113
113
|
|
|
114
114
|
const n = this.__nearPlaneNormal;
|
|
115
115
|
|
|
116
|
-
return
|
|
116
|
+
return v3_distance_above_plane(x, y, z, n.x, n.y, n.z, this.__nearPlaneConstant);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computePointDistanceToPlane } from "../../geom/Plane.js";
|
|
2
1
|
import { EPSILON } from "../../math/MathUtils.js";
|
|
2
|
+
import { v3_distance_above_plane } from "../../geom/v3_distance_above_plane.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
@@ -39,7 +39,7 @@ export function __process_point_if_within_planes(
|
|
|
39
39
|
const nz = planes[plane_address + 2];
|
|
40
40
|
const c = planes[plane_address + 3];
|
|
41
41
|
|
|
42
|
-
const distance_to_plane =
|
|
42
|
+
const distance_to_plane = v3_distance_above_plane(x, y, z, nx, ny, nz, c);
|
|
43
43
|
|
|
44
44
|
if (distance_to_plane < -EPSILON) {
|
|
45
45
|
// point is outside of one of the planes
|
|
@@ -43,10 +43,13 @@ export function aabb3_detailed_volume_intersection_callback_based(
|
|
|
43
43
|
);
|
|
44
44
|
|
|
45
45
|
for (let i = 0; i < point_count; i++) {
|
|
46
|
+
|
|
46
47
|
const address = i * 3;
|
|
48
|
+
|
|
47
49
|
const x = scratch_points_data[address];
|
|
48
50
|
const y = scratch_points_data[address + 1];
|
|
49
51
|
const z = scratch_points_data[address + 2];
|
|
52
|
+
|
|
50
53
|
callback.call(thisArg,
|
|
51
54
|
x,
|
|
52
55
|
y,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function computeHashArray<T>(array: T[], hash: (T) => number): number
|
package/core/color/Color.js
CHANGED
|
@@ -301,12 +301,15 @@ export class Color {
|
|
|
301
301
|
* @param {number} v 0..1
|
|
302
302
|
*/
|
|
303
303
|
setHSV(h, s, v) {
|
|
304
|
-
let _h = h
|
|
304
|
+
let _h = h;
|
|
305
305
|
|
|
306
306
|
if (_h < 0) {
|
|
307
|
-
|
|
307
|
+
// move into positive range
|
|
308
|
+
_h = _h + Math.ceil(Math.abs(_h));
|
|
308
309
|
}
|
|
309
310
|
|
|
311
|
+
_h = _h % 1
|
|
312
|
+
|
|
310
313
|
const _s = clamp01(s);
|
|
311
314
|
const _v = clamp01(v);
|
|
312
315
|
|
|
@@ -409,7 +412,8 @@ export class Color {
|
|
|
409
412
|
* @param {Color} other
|
|
410
413
|
*/
|
|
411
414
|
copy(other) {
|
|
412
|
-
this.
|
|
415
|
+
this.a = other.a;
|
|
416
|
+
this.setRGB(other.r, other.g, other.b);
|
|
413
417
|
}
|
|
414
418
|
|
|
415
419
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Distance of the farthest point along the plane normal from the plane. If the result is >= 0, at least a portion of AABB pokes above the plane
|
|
2
3
|
* @param {number} plane_normal_x
|
|
3
4
|
* @param {number} plane_normal_y
|
|
4
5
|
* @param {number} plane_normal_z
|
|
@@ -11,13 +12,13 @@
|
|
|
11
12
|
* @param {number} _z1
|
|
12
13
|
* @returns {number}
|
|
13
14
|
*/
|
|
14
|
-
export function
|
|
15
|
+
export function aabb3_computeDistanceAbovePlane_max(
|
|
15
16
|
plane_normal_x, plane_normal_y, plane_normal_z, plane_constant,
|
|
16
17
|
_x0, _y0, _z0,
|
|
17
18
|
_x1, _y1, _z1
|
|
18
19
|
) {
|
|
19
20
|
|
|
20
|
-
// pick a corner point
|
|
21
|
+
// pick a corner point nearest along the plane normal
|
|
21
22
|
const px = plane_normal_x > 0 ? _x1 : _x0;
|
|
22
23
|
const py = plane_normal_y > 0 ? _y1 : _y0;
|
|
23
24
|
const pz = plane_normal_z > 0 ? _z1 : _z0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v3_distance_above_plane } from "../../v3_distance_above_plane.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 2,0,or -2; 2: above, -2 : below, 0 : intersects plane
|
|
@@ -62,7 +62,7 @@ export function computeAABB3PlaneSide(
|
|
|
62
62
|
|
|
63
63
|
// check the nearest corner
|
|
64
64
|
|
|
65
|
-
if (
|
|
65
|
+
if (v3_distance_above_plane(x0, y0, z0, plane_normal_x, plane_normal_y, plane_normal_z, plane_constant) >= 0) {
|
|
66
66
|
// above the plane
|
|
67
67
|
result += 1;
|
|
68
68
|
} else {
|
|
@@ -71,7 +71,7 @@ export function computeAABB3PlaneSide(
|
|
|
71
71
|
|
|
72
72
|
// check the farthest corner
|
|
73
73
|
|
|
74
|
-
if (
|
|
74
|
+
if (v3_distance_above_plane(x1, y1, z1, plane_normal_x, plane_normal_y, plane_normal_z, plane_constant) >= 0) {
|
|
75
75
|
// above the plane
|
|
76
76
|
result += 1;
|
|
77
77
|
} else {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { computePlanePlaneIntersection
|
|
1
|
+
import { computePlanePlaneIntersection } from "../../Plane.js";
|
|
2
2
|
import Vector3 from "../../Vector3.js";
|
|
3
3
|
import { plane3_projectPoint } from "../plane/plane3_projectPoint.js";
|
|
4
4
|
import { plane_three_computeConvex3PlaneIntersection } from "../plane/plane_computeConvex3PlaneIntersection.js";
|
|
5
5
|
import { ray_computeNearestPointToPoint } from "../ray/ray_computeNearestPointToPoint.js";
|
|
6
|
+
import { v3_distance_above_plane } from "../../v3_distance_above_plane.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -42,7 +43,7 @@ export function frustum3_computeNearestPointToPoint(result, planes, target_x, ta
|
|
|
42
43
|
|
|
43
44
|
const plane_normal = plane.normal;
|
|
44
45
|
|
|
45
|
-
const distance =
|
|
46
|
+
const distance = v3_distance_above_plane(
|
|
46
47
|
target_x, target_y, target_z,
|
|
47
48
|
plane_normal.x, plane_normal.y, plane_normal.z, plane.constant
|
|
48
49
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computePointDistanceToPlane } from "../../Plane.js";
|
|
2
1
|
import { EPSILON } from "../../../math/MathUtils.js";
|
|
2
|
+
import { v3_distance_above_plane } from "../../v3_distance_above_plane.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
@@ -34,7 +34,7 @@ export function is_point_within_planes(
|
|
|
34
34
|
const nz = planes[plane_address + 2];
|
|
35
35
|
const c = planes[plane_address + 3];
|
|
36
36
|
|
|
37
|
-
const distance_to_plane =
|
|
37
|
+
const distance_to_plane = v3_distance_above_plane(x, y, z, nx, ny, nz, c);
|
|
38
38
|
|
|
39
39
|
if (distance_to_plane < -EPSILON) {
|
|
40
40
|
// point is outside of one of the planes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { v3_distance_above_plane } from "../../v3_distance_above_plane.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
@@ -12,7 +12,7 @@ import { computePointDistanceToPlane } from "../../Plane.js";
|
|
|
12
12
|
* @param {number} plane_offset
|
|
13
13
|
*/
|
|
14
14
|
export function plane3_projectPoint(result, point_x, point_y, point_z, normal_x, normal_y, normal_z, plane_offset) {
|
|
15
|
-
const distance =
|
|
15
|
+
const distance = v3_distance_above_plane(point_x, point_y, point_z, normal_x, normal_y, normal_z, plane_offset);
|
|
16
16
|
|
|
17
17
|
const negative_distance = -distance;
|
|
18
18
|
|