@woosh/meep-engine 2.39.39 → 2.39.42
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/binary/operations/ceilPowerOfTwo.spec.js +17 -0
- package/core/bvh2/aabb3/AABB3.js +6 -6
- package/core/bvh2/binary/2/BinaryUint32BVH.js +7 -1
- package/core/bvh2/binary/2/BinaryUint32BVH.spec.js +31 -1
- package/core/bvh2/bvh3/bvh_query_user_data_nearest_to_point.js +5 -5
- package/core/bvh2/bvh3/bvh_query_user_data_nearest_to_point.spec.js +70 -0
- package/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.spec.js +2 -2
- package/core/cache/Cache.js +6 -0
- package/core/collection/IteratorUtils.js +1 -0
- package/core/collection/queue/Deque.js +5 -2
- package/core/color/Color.js +22 -4
- package/core/color/hsluv/HSLuv.js +187 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +1 -0
- package/core/geom/3d/topology/simplify/simplifyTopoMesh2.js +1 -1
- package/core/primitives/strings/compareStrings.js +22 -0
- package/editor/Editor.js +2 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +12 -6
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +22 -11
- package/engine/EngineHarness.js +7 -0
- package/engine/asset/loaders/geometry/geometry/computeBufferAttributeHash.js +5 -6
- package/engine/asset/loaders/image/codec/Codec.js +9 -0
- package/engine/asset/loaders/image/codec/CodecWithFallback.js +52 -11
- package/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +12 -0
- package/engine/asset/loaders/image/png/PNGReader.js +2 -1
- package/engine/asset/loaders/image/png/PNG_HEADER_BYTES.js +1 -0
- package/engine/computeStridedIntegerArrayHash.js +19 -0
- package/engine/ecs/EntityBuilder.d.ts +2 -0
- package/engine/ecs/gui/GUIElement.d.ts +3 -1
- package/engine/ecs/terrain/ecs/layers/TerrainLayers.js +5 -3
- package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +11 -2
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -8
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +7 -0
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +17 -1
- package/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +336 -0
- package/engine/graphics/geometry/optimization/merge/prototypeGeometryMerge.js +176 -0
- package/engine/graphics/micron/build/hierarchy/buildAbstractPatchHierarchy.js +7 -3
- package/engine/graphics/micron/build/hierarchy/merge_patches.js +0 -1
- package/engine/graphics/micron/prototypeVirtualGeometry.js +3 -3
- package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +32 -1
- package/engine/graphics/render/forward_plus/LightManager.js +58 -13
- package/engine/graphics/render/forward_plus/debug/createScreenGrid.js +192 -9
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +42 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +1 -0
- package/engine/graphics/render/forward_plus/materials/ForwardPlusThreeMaterial.js +5 -0
- package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +1 -4
- package/engine/graphics/render/forward_plus/model/Decal.js +33 -5
- package/engine/graphics/render/forward_plus/model/PointLight.js +1 -1
- package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +4 -0
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +480 -12
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +49 -29
- package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +11 -0
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +34 -0
- package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +9 -1
- package/engine/graphics/texture/atlas/TextureAtlas.js +29 -16
- package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +75 -19
- package/engine/graphics/texture/sampler/Sampler2D.d.ts +2 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +51 -10
- package/engine/sound/ecs/SoundListenerSystem.js +5 -0
- package/engine/sound/ecs/emitter/SoundEmitter.js +12 -1
- package/package.json +1 -1
- package/samples/terrain/from_image_2.js +8 -2
- package/view/tooltip/TooltipManager.js +0 -95
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ceilPowerOfTwo } from "./ceilPowerOfTwo.js";
|
|
2
|
+
|
|
3
|
+
test('test', () => {
|
|
4
|
+
expect(ceilPowerOfTwo(1)).toBe(1);
|
|
5
|
+
|
|
6
|
+
expect(ceilPowerOfTwo(2)).toBe(2);
|
|
7
|
+
|
|
8
|
+
expect(ceilPowerOfTwo(3)).toBe(4);
|
|
9
|
+
expect(ceilPowerOfTwo(4)).toBe(4);
|
|
10
|
+
|
|
11
|
+
expect(ceilPowerOfTwo(5)).toBe(8);
|
|
12
|
+
expect(ceilPowerOfTwo(7)).toBe(8);
|
|
13
|
+
expect(ceilPowerOfTwo(8)).toBe(8);
|
|
14
|
+
|
|
15
|
+
expect(ceilPowerOfTwo(9)).toBe(16);
|
|
16
|
+
expect(ceilPowerOfTwo(15)).toBe(16);
|
|
17
|
+
});
|
package/core/bvh2/aabb3/AABB3.js
CHANGED
|
@@ -553,12 +553,12 @@ export class AABB3 {
|
|
|
553
553
|
|
|
554
554
|
/**
|
|
555
555
|
* @source http://stackoverflow.com/questions/3106666/intersection-of-line-segment-with-axis-aligned-box-in-c-sharp
|
|
556
|
-
* @param startX
|
|
557
|
-
* @param startY
|
|
558
|
-
* @param startZ
|
|
559
|
-
* @param endX
|
|
560
|
-
* @param endY
|
|
561
|
-
* @param endZ
|
|
556
|
+
* @param {number} startX
|
|
557
|
+
* @param {number} startY
|
|
558
|
+
* @param {number} startZ
|
|
559
|
+
* @param {number} endX
|
|
560
|
+
* @param {number} endY
|
|
561
|
+
* @param {number} endZ
|
|
562
562
|
* @returns {boolean}
|
|
563
563
|
*/
|
|
564
564
|
intersectSegment2(startX, startY, startZ, endX, endY, endZ) {
|
|
@@ -201,7 +201,13 @@ export class BinaryUint32BVH {
|
|
|
201
201
|
|
|
202
202
|
const twoLeafLimit = ceilPowerOfTwo(count);
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
if (count <= 1) {
|
|
205
|
+
// special case
|
|
206
|
+
this.__node_count_binary = twoLeafLimit;
|
|
207
|
+
} else {
|
|
208
|
+
this.__node_count_binary = twoLeafLimit - 1;
|
|
209
|
+
}
|
|
210
|
+
|
|
205
211
|
}
|
|
206
212
|
|
|
207
213
|
/**
|
|
@@ -12,6 +12,36 @@ test('1 leaf build does not throw', () => {
|
|
|
12
12
|
bvh.build();
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
+
test('0 leaf tree must have a no binary nodes', () => {
|
|
16
|
+
const bvh = new BinaryUint32BVH();
|
|
17
|
+
|
|
18
|
+
bvh.setLeafCount(0);
|
|
19
|
+
bvh.initialize_structure();
|
|
20
|
+
bvh.build();
|
|
21
|
+
|
|
22
|
+
expect(bvh.getBinaryNodeCount()).toBe(0);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('1 leaf tree must have a single binary node', () => {
|
|
26
|
+
const bvh = new BinaryUint32BVH();
|
|
27
|
+
|
|
28
|
+
bvh.setLeafCount(1);
|
|
29
|
+
bvh.initialize_structure();
|
|
30
|
+
bvh.build();
|
|
31
|
+
|
|
32
|
+
expect(bvh.getBinaryNodeCount()).toBe(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('4 leaf tree must have a 3 binary nodes', () => {
|
|
36
|
+
const bvh = new BinaryUint32BVH();
|
|
37
|
+
|
|
38
|
+
bvh.setLeafCount(4);
|
|
39
|
+
bvh.initialize_structure();
|
|
40
|
+
bvh.build();
|
|
41
|
+
|
|
42
|
+
expect(bvh.getBinaryNodeCount()).toBe(3);
|
|
43
|
+
});
|
|
44
|
+
|
|
15
45
|
test('read/write 1 leaf', () => {
|
|
16
46
|
const bvh = new BinaryUint32BVH();
|
|
17
47
|
|
|
@@ -23,7 +53,7 @@ test('read/write 1 leaf', () => {
|
|
|
23
53
|
expect(bvh.readLeafPayload(0)).toBe(7);
|
|
24
54
|
|
|
25
55
|
const bounds = [];
|
|
26
|
-
bvh.readBounds(
|
|
56
|
+
bvh.readBounds(bvh.getLeafBlockAddress(), bounds, 0);
|
|
27
57
|
|
|
28
58
|
expect(bounds[0]).toBeCloseTo(-3);
|
|
29
59
|
expect(bounds[1]).toBeCloseTo(-7);
|
|
@@ -41,7 +41,7 @@ export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance
|
|
|
41
41
|
traversal_stack[traversal_cursor++] = root;
|
|
42
42
|
|
|
43
43
|
let best_leaf_data = -1;
|
|
44
|
-
let
|
|
44
|
+
let best_distance_sqr = max_distance * max_distance;
|
|
45
45
|
|
|
46
46
|
while (traversal_cursor > stack_frame_address) {
|
|
47
47
|
traversal_cursor--;
|
|
@@ -55,13 +55,13 @@ export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance
|
|
|
55
55
|
bvh.node_get_aabb(node, scratch_aabb);
|
|
56
56
|
|
|
57
57
|
// compute distance to box
|
|
58
|
-
const
|
|
58
|
+
const distance_sqr = max2(0, aabb3_signed_distance_sqr_to_point(
|
|
59
59
|
scratch_aabb[0], scratch_aabb[1], scratch_aabb[2],
|
|
60
60
|
scratch_aabb[3], scratch_aabb[4], scratch_aabb[5],
|
|
61
61
|
x, y, z
|
|
62
62
|
));
|
|
63
63
|
|
|
64
|
-
if (
|
|
64
|
+
if (distance_sqr > best_distance_sqr) {
|
|
65
65
|
// node is too far
|
|
66
66
|
continue;
|
|
67
67
|
}
|
|
@@ -81,8 +81,8 @@ export function bvh_query_user_data_nearest_to_point(bvh, x, y, z, max_distance
|
|
|
81
81
|
} else {
|
|
82
82
|
|
|
83
83
|
// leaf node
|
|
84
|
-
if (
|
|
85
|
-
|
|
84
|
+
if (distance_sqr < best_distance_sqr) {
|
|
85
|
+
best_distance_sqr = distance_sqr;
|
|
86
86
|
best_leaf_data = bvh.node_get_user_data(node);
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ExplicitBinaryBoundingVolumeHierarchy } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
2
|
+
import { bvh_query_user_data_nearest_to_point } from "./bvh_query_user_data_nearest_to_point.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {number[]} boxes
|
|
7
|
+
* @return {ExplicitBinaryBoundingVolumeHierarchy}
|
|
8
|
+
*/
|
|
9
|
+
function makeBvh(...boxes) {
|
|
10
|
+
const r = new ExplicitBinaryBoundingVolumeHierarchy();
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
13
|
+
const box = boxes[i];
|
|
14
|
+
|
|
15
|
+
const node = r.allocate_node();
|
|
16
|
+
|
|
17
|
+
r.node_set_aabb(node, box);
|
|
18
|
+
r.node_set_user_data(node, i);
|
|
19
|
+
|
|
20
|
+
r.insert_leaf(node);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return r;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
test('no data, infinite distance', () => {
|
|
27
|
+
const bvh = makeBvh();
|
|
28
|
+
|
|
29
|
+
const result = bvh_query_user_data_nearest_to_point(bvh, 0, 0, 0, Infinity);
|
|
30
|
+
|
|
31
|
+
expect(result).toBe(-1);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('single point, distance too short', () => {
|
|
35
|
+
const bvh = makeBvh([1, 0, 0, 1, 0, 0]);
|
|
36
|
+
|
|
37
|
+
const result = bvh_query_user_data_nearest_to_point(bvh, 0, 0, 0, 0.5);
|
|
38
|
+
|
|
39
|
+
expect(result).toBe(-1);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('single point, distance sufficient', () => {
|
|
43
|
+
const bvh = makeBvh([1, 0, 0, 1, 0, 0]);
|
|
44
|
+
|
|
45
|
+
const result = bvh_query_user_data_nearest_to_point(bvh, 0, 0, 0, 1.5);
|
|
46
|
+
|
|
47
|
+
expect(result).not.toBe(-1);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('two point, distance sufficient to one', () => {
|
|
51
|
+
const bvh = makeBvh(
|
|
52
|
+
[1, 0, 0, 1, 0, 0],
|
|
53
|
+
[2, 0, 0, 2, 0, 0],
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const result = bvh_query_user_data_nearest_to_point(bvh, 0, 0, 0, 1.5);
|
|
57
|
+
|
|
58
|
+
expect(result).toBe(0);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('two point, distance sufficient to both', () => {
|
|
62
|
+
const bvh = makeBvh(
|
|
63
|
+
[1, 0, 0, 1, 0, 0],
|
|
64
|
+
[2, 0, 0, 2, 0, 0],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const result = bvh_query_user_data_nearest_to_point(bvh, 0, 0, 0, 2.5);
|
|
68
|
+
|
|
69
|
+
expect(result).toBe(0);
|
|
70
|
+
});
|
|
@@ -13,7 +13,7 @@ function orthographic_frustum(left, right, up, down, near, far) {
|
|
|
13
13
|
]);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
test('Empty', () => {
|
|
16
|
+
test('Empty does not throw', () => {
|
|
17
17
|
const bvh = new ExplicitBinaryBoundingVolumeHierarchy();
|
|
18
18
|
|
|
19
19
|
const res = [];
|
|
@@ -23,7 +23,7 @@ test('Empty', () => {
|
|
|
23
23
|
compute_tight_near_far_clipping_planes(res, 0, 0b000011, bvh, frustum);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
test('Axis-aligned, orthographic tight fit around a single small node', () => {
|
|
26
|
+
test.skip('Axis-aligned, orthographic tight fit around a single small node', () => {
|
|
27
27
|
const frustum = orthographic_frustum(-1, 1, -1, 1, -1, 1);
|
|
28
28
|
|
|
29
29
|
const bvh = new ExplicitBinaryBoundingVolumeHierarchy();
|
package/core/cache/Cache.js
CHANGED
|
@@ -264,6 +264,12 @@ export class Cache {
|
|
|
264
264
|
*/
|
|
265
265
|
const weightTarget = this.maxWeight - elementWeight;
|
|
266
266
|
|
|
267
|
+
if (weightTarget < 0) {
|
|
268
|
+
// Special case
|
|
269
|
+
// element does not fit into cache, attempting to insert it forcibly would result in a full flush and overflow
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
267
273
|
//evict elements until there is enough space for the element
|
|
268
274
|
this.evictUntilWeight(weightTarget);
|
|
269
275
|
|
|
@@ -200,11 +200,14 @@ export class Deque {
|
|
|
200
200
|
*/
|
|
201
201
|
__index_of(e) {
|
|
202
202
|
const size = this.size();
|
|
203
|
-
|
|
203
|
+
|
|
204
|
+
const data = this.__data;
|
|
205
|
+
const capacity = data.length;
|
|
206
|
+
|
|
204
207
|
for (let i = 0; i < size; i++) {
|
|
205
208
|
const index = (this.__head + i) % capacity;
|
|
206
209
|
|
|
207
|
-
const el =
|
|
210
|
+
const el = data[index];
|
|
208
211
|
|
|
209
212
|
if (el === e) {
|
|
210
213
|
return i;
|
package/core/color/Color.js
CHANGED
|
@@ -157,7 +157,8 @@ export class Color {
|
|
|
157
157
|
let _h = h % 1;
|
|
158
158
|
|
|
159
159
|
if (_h < 0) {
|
|
160
|
-
|
|
160
|
+
// move into positive range
|
|
161
|
+
_h = _h + Math.ceil(Math.abs(_h));
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
const k_r = (_h * 12) % 12;
|
|
@@ -184,7 +185,8 @@ export class Color {
|
|
|
184
185
|
let _h = h % 1;
|
|
185
186
|
|
|
186
187
|
if (_h < 0) {
|
|
187
|
-
|
|
188
|
+
// move into positive range
|
|
189
|
+
_h = _h + Math.ceil(Math.abs(_h));
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
const h_face = _h * 6;
|
|
@@ -244,7 +246,8 @@ export class Color {
|
|
|
244
246
|
let _h = h % 1;
|
|
245
247
|
|
|
246
248
|
if (_h < 0) {
|
|
247
|
-
|
|
249
|
+
// move into positive range
|
|
250
|
+
_h = _h + Math.ceil(Math.abs(_h));
|
|
248
251
|
}
|
|
249
252
|
|
|
250
253
|
const h_face = _h * 6;
|
|
@@ -315,7 +318,7 @@ export class Color {
|
|
|
315
318
|
|
|
316
319
|
let r, g, b;
|
|
317
320
|
|
|
318
|
-
const i = Math.floor(
|
|
321
|
+
const i = Math.floor(_h * 6);
|
|
319
322
|
const f = _h * 6 - i;
|
|
320
323
|
const p = _v * (1 - _s);
|
|
321
324
|
const q = _v * (1 - f * _s);
|
|
@@ -534,6 +537,21 @@ export class Color {
|
|
|
534
537
|
return new Color(r, g, b);
|
|
535
538
|
}
|
|
536
539
|
|
|
540
|
+
/**
|
|
541
|
+
*
|
|
542
|
+
* @param {number} h
|
|
543
|
+
* @param {number} s
|
|
544
|
+
* @param {number} v
|
|
545
|
+
* @return {Color}
|
|
546
|
+
*/
|
|
547
|
+
static fromHSV(h, s, v) {
|
|
548
|
+
const color = new Color();
|
|
549
|
+
|
|
550
|
+
color.setHSV(h, s, v);
|
|
551
|
+
|
|
552
|
+
return color;
|
|
553
|
+
}
|
|
554
|
+
|
|
537
555
|
|
|
538
556
|
/**
|
|
539
557
|
*
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://github.com/hsluv/hsluv-c/blob/master/src/hsluv.c
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const temp_0 = new Float32Array(3);
|
|
6
|
+
const temp_1 = new Float32Array(3);
|
|
7
|
+
/* for RGB */
|
|
8
|
+
const m = new Float32Array([
|
|
9
|
+
3.24096994190452134377, -1.53738317757009345794, -0.49861076029300328366,
|
|
10
|
+
-0.96924363628087982613, 1.87596750150772066772, 0.04155505740717561247,
|
|
11
|
+
0.05563007969699360846, -0.20397695888897656435, 1.05697151424287856072
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
/* for XYZ */
|
|
15
|
+
const m_inv = new Float32Array([
|
|
16
|
+
0.41239079926595948129, 0.35758433938387796373, 0.18048078840183428751,
|
|
17
|
+
0.21263900587151035754, 0.71516867876775592746, 0.07219231536073371500,
|
|
18
|
+
0.01933081871559185069, 0.11919477979462598791, 0.95053215224966058086
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
function dot_product(t1, offset_1, t2, offset_2) {
|
|
22
|
+
return t1[offset_1] * t2[offset_2] + t1[offset_1 + 1] * t2[offset_2 + 1] + t1[offset_1 + 2] * t2[offset_2 + 2];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Used for rgb conversions */
|
|
26
|
+
|
|
27
|
+
function from_linear(c) {
|
|
28
|
+
if (c <= 0.0031308)
|
|
29
|
+
return 12.92 * c;
|
|
30
|
+
else
|
|
31
|
+
return 1.055 * Math.pow(c, 1.0 / 2.4) - 0.055;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function to_linear(c) {
|
|
35
|
+
if (c > 0.04045)
|
|
36
|
+
return Math.pow((c + 0.055) / 1.055, 2.4);
|
|
37
|
+
else
|
|
38
|
+
return c / 12.92;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const ref_u = 0.19783000664283680764;
|
|
42
|
+
const ref_v = 0.46831999493879100370;
|
|
43
|
+
|
|
44
|
+
const kappa = 903.29629629629629629630;
|
|
45
|
+
const epsilon = 0.00885645167903563082;
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param {number} theta
|
|
51
|
+
* @param {number[]|Float32Array} line
|
|
52
|
+
* @param {number} line_address
|
|
53
|
+
* @return {number}
|
|
54
|
+
*/
|
|
55
|
+
function ray_length_until_intersect(theta, line, line_address) {
|
|
56
|
+
return line[line_address + 1] / (Math.sin(theta) - line[line_address] * Math.cos(theta));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function get_bounds( l, bounds)
|
|
60
|
+
{
|
|
61
|
+
const tl = l + 16.0;
|
|
62
|
+
const sub1 = (tl * tl * tl) / 1560896.0;
|
|
63
|
+
const sub2 = (sub1 > epsilon ? sub1 : (l / kappa));
|
|
64
|
+
let channel;
|
|
65
|
+
let t;
|
|
66
|
+
|
|
67
|
+
for(channel = 0; channel < 3; channel++) {
|
|
68
|
+
const ch3 = channel*3;
|
|
69
|
+
let m1 = m[ch3];
|
|
70
|
+
let m2 = m[ch3+1];
|
|
71
|
+
let m3 = m[ch3+2];
|
|
72
|
+
|
|
73
|
+
for (t = 0; t < 2; t++) {
|
|
74
|
+
const top1 = (284517.0 * m1 - 94839.0 * m3) * sub2;
|
|
75
|
+
const top2 = (838422.0 * m3 + 769860.0 * m2 + 731718.0 * m1) * l * sub2 - 769860.0 * t * l;
|
|
76
|
+
const bottom = (632260.0 * m3 - 126452.0 * m2) * sub2 + 126452.0 * t;
|
|
77
|
+
|
|
78
|
+
const bounds_index = channel * 2 + t;
|
|
79
|
+
const bounds_address = bounds_index*2;
|
|
80
|
+
|
|
81
|
+
bounds[bounds_address] = top1 / bottom;
|
|
82
|
+
bounds[bounds_address] = top2 / bottom;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function max_chroma_for_lh(l, h) {
|
|
88
|
+
let min_len = Infinity;
|
|
89
|
+
const hrad = h * 0.01745329251994329577; /* (2 * pi / 360) */
|
|
90
|
+
const bounds = new Float32Array(12);
|
|
91
|
+
let i;
|
|
92
|
+
|
|
93
|
+
get_bounds(l, bounds);
|
|
94
|
+
|
|
95
|
+
for (i = 0; i < 6; i++) {
|
|
96
|
+
const len = ray_length_until_intersect(hrad, bounds, i * 2);
|
|
97
|
+
|
|
98
|
+
if (len >= 0 && len < min_len)
|
|
99
|
+
min_len = len;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return min_len;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function hsluv2lch(input, output) {
|
|
106
|
+
let h = input[0];
|
|
107
|
+
const s = input[1];
|
|
108
|
+
const l = input[2];
|
|
109
|
+
let c;
|
|
110
|
+
|
|
111
|
+
/* White and black: disambiguate chroma */
|
|
112
|
+
if (l > 99.9999999 || l < 0.00000001)
|
|
113
|
+
c = 0.0;
|
|
114
|
+
else
|
|
115
|
+
c = max_chroma_for_lh(l, h) / 100.0 * s;
|
|
116
|
+
|
|
117
|
+
/* Grays: disambiguate hue */
|
|
118
|
+
if (s < 0.00000001)
|
|
119
|
+
h = 0.0;
|
|
120
|
+
|
|
121
|
+
output[0] = l;
|
|
122
|
+
output[1] = c;
|
|
123
|
+
output[2] = h;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function lch2luv(input, output) {
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function luv2xyz(input, output) {
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function xyz2rgb(input, output) {
|
|
135
|
+
const r = from_linear(dot_product(m, 0, input, 0));
|
|
136
|
+
|
|
137
|
+
const g = from_linear(dot_product(m, 3, input, 0));
|
|
138
|
+
|
|
139
|
+
const b = from_linear(dot_product(m, 6, input, 0));
|
|
140
|
+
|
|
141
|
+
output[0] = r;
|
|
142
|
+
output[1] = g;
|
|
143
|
+
output[2] = b;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function rgb2xyz(input, output) {
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function xyz2luv(input, output) {
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function luv2lch(input, output) {
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function lch2hsluv(input, output) {
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
*
|
|
165
|
+
* @param {number[]} input
|
|
166
|
+
* @param {number[]} output
|
|
167
|
+
*/
|
|
168
|
+
export function rgb2hsluv(input, output) {
|
|
169
|
+
rgb2xyz(input, temp_0);
|
|
170
|
+
xyz2luv(temp_0, temp_1);
|
|
171
|
+
luv2lch(temp_1, temp_0);
|
|
172
|
+
lch2hsluv(temp_0, output);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* @param {number[]} input
|
|
178
|
+
* @param {number[]} output
|
|
179
|
+
*/
|
|
180
|
+
export function hsluv2rgb(input, output) {
|
|
181
|
+
hsluv2lch(input, temp_0);
|
|
182
|
+
lch2luv(temp_0, temp_1);
|
|
183
|
+
luv2xyz(temp_1, temp_0);
|
|
184
|
+
xyz2rgb(temp_0, output);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NOTE: Based on Transforming Axis-Aligned Bounding Boxes by Jim Arvo from "Graphics Gems", Academic Press, 1990
|
|
3
|
+
* NOTE: {@link result} and {@link aabb} must be different objects
|
|
3
4
|
* @param {ArrayLike<number>|number[]|Float32Array} result
|
|
4
5
|
* @param {ArrayLike<number>|number[]|Float32Array} aabb
|
|
5
6
|
* @param {number[]} matrix 4x4 matrix
|
|
@@ -52,7 +52,7 @@ export function edge_collapse_reduce_face_count(mesh, num_faces_to_remove, heap,
|
|
|
52
52
|
const target_face_count = max2(0, mesh_faces.size - num_faces_to_remove);
|
|
53
53
|
|
|
54
54
|
let cycle_count = 0;
|
|
55
|
-
let cycle_limit = max2(heap.size, num_faces_to_remove *
|
|
55
|
+
let cycle_limit = max2(heap.size, num_faces_to_remove * 10) + 10;
|
|
56
56
|
|
|
57
57
|
while (
|
|
58
58
|
!heap.is_empty()
|
|
@@ -5,6 +5,28 @@
|
|
|
5
5
|
* @returns {number}
|
|
6
6
|
*/
|
|
7
7
|
export function compareStrings(a, b) {
|
|
8
|
+
// null check
|
|
9
|
+
if (a === null) {
|
|
10
|
+
if (b === null) {
|
|
11
|
+
return 0;
|
|
12
|
+
} else {
|
|
13
|
+
return 1;
|
|
14
|
+
}
|
|
15
|
+
} else if (b === null) {
|
|
16
|
+
return -1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// undefined check
|
|
20
|
+
if (a === undefined) {
|
|
21
|
+
if (b === undefined) {
|
|
22
|
+
return 0;
|
|
23
|
+
} else {
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
} else if (b === undefined) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
const n = a.length;
|
|
9
31
|
|
|
10
32
|
const m = b.length;
|
package/editor/Editor.js
CHANGED
|
@@ -69,6 +69,8 @@ import Signal from "../core/events/signal/Signal.js";
|
|
|
69
69
|
import ObservedInteger from "../core/model/ObservedInteger.js";
|
|
70
70
|
import { ObservedIntegerEditor } from "./ecs/component/editors/ObservedIntegerEditor.js";
|
|
71
71
|
|
|
72
|
+
import '../../../../css/editor/EntityEditorView.scss';
|
|
73
|
+
import '../../../../css/editor/EditorView.scss';
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
76
|
* @template T
|
|
@@ -27,20 +27,26 @@ export class TerrainEditor extends ObjectEditor {
|
|
|
27
27
|
|
|
28
28
|
// splats
|
|
29
29
|
view.bindSignal(terrain.layers.layers.on.added, () => {
|
|
30
|
-
terrain.
|
|
31
|
-
|
|
30
|
+
if (terrain.getFlag(TerrainFlags.Built)) {
|
|
31
|
+
terrain.splat.addWeightLayer();
|
|
32
|
+
updateLayers();
|
|
33
|
+
}
|
|
32
34
|
});
|
|
33
35
|
view.bindSignal(terrain.layers.layers.on.removed, (a, index) => {
|
|
34
|
-
terrain.
|
|
36
|
+
if (terrain.getFlag(TerrainFlags.Built)) {
|
|
37
|
+
terrain.splat.removeWeightLayer(index);
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
updateLayers();
|
|
40
|
+
}
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
// mapping sizes
|
|
40
44
|
view.bindSignal(terrain.splat.size.onChanged, (x, y) => {
|
|
41
|
-
terrain.
|
|
45
|
+
if (terrain.getFlag(TerrainFlags.Built)) {
|
|
46
|
+
terrain.splat.resize(x, y, terrain.splat.depth);
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
terrain.updateMaterial();
|
|
49
|
+
}
|
|
44
50
|
});
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -217,7 +217,7 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
|
217
217
|
*
|
|
218
218
|
* @type {Vector3|null}
|
|
219
219
|
*/
|
|
220
|
-
this.
|
|
220
|
+
this.input_pointer_position = null;
|
|
221
221
|
|
|
222
222
|
this.center = new Vector3(this.options.size / 2, this.options.size / 2, 0);
|
|
223
223
|
this.selectedAxis = null;
|
|
@@ -240,16 +240,18 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
|
240
240
|
super.link();
|
|
241
241
|
|
|
242
242
|
const el = this.el;
|
|
243
|
-
|
|
244
|
-
el.addEventListener('
|
|
245
|
-
el.addEventListener('
|
|
243
|
+
|
|
244
|
+
el.addEventListener('mousemove', this.onMouseMove);
|
|
245
|
+
el.addEventListener('mouseout', this.onMouseOut);
|
|
246
|
+
el.addEventListener('click', this.onMouseClick);
|
|
246
247
|
}
|
|
247
248
|
|
|
248
249
|
unlink() {
|
|
249
250
|
const el = this.el;
|
|
250
|
-
|
|
251
|
-
el.removeEventListener('
|
|
252
|
-
el.removeEventListener('
|
|
251
|
+
|
|
252
|
+
el.removeEventListener('mousemove', this.onMouseMove);
|
|
253
|
+
el.removeEventListener('mouseout', this.onMouseOut);
|
|
254
|
+
el.removeEventListener('click', this.onMouseClick);
|
|
253
255
|
|
|
254
256
|
super.unlink();
|
|
255
257
|
}
|
|
@@ -259,10 +261,19 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
|
259
261
|
* @param {MouseEvent} evt
|
|
260
262
|
*/
|
|
261
263
|
onMouseMove(evt) {
|
|
264
|
+
this._setPointerPositionFromEvent(evt);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
*
|
|
269
|
+
* @param {MouseEvent} evt
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
_setPointerPositionFromEvent(evt) {
|
|
262
273
|
const v2 = new Vector2();
|
|
263
274
|
readPositionFromMouseEvent(v2, evt);
|
|
264
275
|
|
|
265
|
-
this.
|
|
276
|
+
this.input_pointer_position = new Vector3(v2.x, v2.y, 0);
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
/**
|
|
@@ -270,7 +281,7 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
|
270
281
|
* @param {MouseEvent} evt
|
|
271
282
|
*/
|
|
272
283
|
onMouseOut(evt) {
|
|
273
|
-
this.
|
|
284
|
+
this.input_pointer_position = null;
|
|
274
285
|
}
|
|
275
286
|
|
|
276
287
|
/**
|
|
@@ -362,13 +373,13 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
|
362
373
|
// If the mouse is over the gizmo, find the closest axis and highlight it
|
|
363
374
|
this.selectedAxis = null;
|
|
364
375
|
|
|
365
|
-
if (this.
|
|
376
|
+
if (this.input_pointer_position) {
|
|
366
377
|
let closestDist = Infinity;
|
|
367
378
|
let closestZ = -Infinity;
|
|
368
379
|
|
|
369
380
|
// Loop through each layer
|
|
370
381
|
for (let bubble of layers) {
|
|
371
|
-
const distance = v2_distance(this.
|
|
382
|
+
const distance = v2_distance(this.input_pointer_position.x, this.input_pointer_position.y, bubble.position.x, bubble.position.y);
|
|
372
383
|
|
|
373
384
|
// Only select the axis if its closer to the mouse than the previous or if its within its bubble circle
|
|
374
385
|
if (
|