@woosh/meep-engine 2.36.0 → 2.36.4
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/collection/queue/Deque.js +1 -1
- package/core/color/Color.d.ts +32 -2
- package/core/color/Color.js +31 -18
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/Vector3.js +5 -1
- package/core/process/undo/ActionProcessor.js +31 -3
- package/core/process/undo/ActionProcessor.spec.js +1 -1
- package/engine/animation/curve/AnimationCurve.js +40 -1
- package/engine/animation/curve/Keyframe.js +19 -0
- package/engine/animation/curve/compression/animation_curve_to_float_array.js +35 -0
- package/engine/animation/curve/compression/downsample_float_array.js +50 -0
- package/engine/animation/curve/compression/downsample_float_array_curve_by_error.js +147 -0
- package/engine/animation/curve/compression/downsample_float_array_curve_by_error.spec.js +47 -0
- package/engine/animation/curve/compression/prototypeCurveCompression.js +154 -0
- package/engine/animation/curve/draw/build_curve_editor.js +316 -0
- package/engine/animation/curve/draw/build_plot_entity_from_array.js +47 -0
- package/engine/animation/curve/draw/build_tangent_editor.js +115 -0
- package/engine/animation/curve/draw/draw_grid.js +27 -0
- package/engine/animation/curve/draw/draw_label.js +17 -0
- package/engine/animation/curve/draw/plot_array.js +76 -0
- package/engine/animation/curve/draw/plot_data.js +49 -0
- package/engine/ecs/parent/EntityNode.d.ts +7 -3
- package/engine/ecs/parent/EntityNode.js +21 -0
- package/engine/ecs/parent/entity_node_compute_bounding_box.js +41 -0
- package/engine/graphics/ecs/highlight/HighlightDefinition.d.ts +11 -1
- package/engine/graphics/ecs/highlight/HighlightDefinition.js +18 -8
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +5 -1
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +122 -0
- package/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +148 -0
- package/engine/graphics/ecs/mesh-v2/render/adapters/InstancedRendererAdapter.js +2 -0
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.d.ts +4 -0
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -3
- package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.spec.js +24 -0
- package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +10 -0
- package/engine/graphics/micron/prototypeVirtualGeometry.js +5 -3
- package/engine/graphics/micron/render/v1/MicronRenderContext.js +0 -6
- package/engine/graphics/render/forward_plus/LightManager.js +8 -6
- package/engine/graphics/render/forward_plus/data/channelCountToThreIntegerTextureType.js +3 -3
- package/engine/graphics/texture/channelCountToThreeTextureFormat.js +2 -2
- package/engine/ui/DraggableAspect.js +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { min2 } from "../../../../core/math/min2.js";
|
|
2
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {number[]} data
|
|
7
|
+
* @return {number[]}
|
|
8
|
+
*/
|
|
9
|
+
export function array_compute_min_max(data) {
|
|
10
|
+
const point_count = data.length;
|
|
11
|
+
|
|
12
|
+
let min = Number.POSITIVE_INFINITY;
|
|
13
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
14
|
+
for (let i = 0; i < point_count; i++) {
|
|
15
|
+
min = min2(data[i], min);
|
|
16
|
+
max = max2(data[i], max);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return [min, max];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
25
|
+
* @param {number} width
|
|
26
|
+
* @param {number} height
|
|
27
|
+
* @param {number} x_offset
|
|
28
|
+
* @param {number} y_offset
|
|
29
|
+
* @param {number[]} data
|
|
30
|
+
* @param {number[]} data_range_y
|
|
31
|
+
*/
|
|
32
|
+
export function plot_array(
|
|
33
|
+
ctx,
|
|
34
|
+
width,
|
|
35
|
+
height,
|
|
36
|
+
x_offset,
|
|
37
|
+
y_offset,
|
|
38
|
+
data,
|
|
39
|
+
data_range_y
|
|
40
|
+
) {
|
|
41
|
+
const point_count = data.length;
|
|
42
|
+
|
|
43
|
+
if (data_range_y === undefined) {
|
|
44
|
+
data_range_y = array_compute_min_max(data)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const [min, max] = data_range_y;
|
|
48
|
+
|
|
49
|
+
const value_span = max - min;
|
|
50
|
+
const normalization_multiplier = value_span !== 0 ? 1 / value_span : 0;
|
|
51
|
+
|
|
52
|
+
ctx.beginPath();
|
|
53
|
+
if (point_count === 1) {
|
|
54
|
+
ctx.moveTo(x_offset, height + y_offset);
|
|
55
|
+
ctx.lineTo(x_offset + width, height + y_offset);
|
|
56
|
+
} else {
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < point_count; i++) {
|
|
59
|
+
const value = data[i];
|
|
60
|
+
const value_normalized = (value - min) * normalization_multiplier;
|
|
61
|
+
|
|
62
|
+
const v = 1 - value_normalized;
|
|
63
|
+
const u = i / (point_count - 1);
|
|
64
|
+
|
|
65
|
+
const x = u * width + x_offset;
|
|
66
|
+
const y = v * height + y_offset;
|
|
67
|
+
|
|
68
|
+
if (i === 0) {
|
|
69
|
+
ctx.moveTo(x, y);
|
|
70
|
+
} else {
|
|
71
|
+
ctx.lineTo(x, y);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
ctx.stroke();
|
|
76
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { draw_grid } from "./draw_grid.js";
|
|
2
|
+
import { plot_array } from "./plot_array.js";
|
|
3
|
+
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
8
|
+
* @param {number[]|Float32Array} data
|
|
9
|
+
* @param {Vector2} [margin]
|
|
10
|
+
* @param {number} width
|
|
11
|
+
* @param {number} height
|
|
12
|
+
* @param {number[]} [range_y]
|
|
13
|
+
*/
|
|
14
|
+
export function plot_data({
|
|
15
|
+
ctx,
|
|
16
|
+
data,
|
|
17
|
+
margin = Vector2.zero,
|
|
18
|
+
width,
|
|
19
|
+
height,
|
|
20
|
+
range_y
|
|
21
|
+
}) {
|
|
22
|
+
|
|
23
|
+
ctx.fillStyle = '#222222';
|
|
24
|
+
ctx.fillRect(0, 0, width, height);
|
|
25
|
+
|
|
26
|
+
draw_grid({
|
|
27
|
+
ctx,
|
|
28
|
+
width,
|
|
29
|
+
height,
|
|
30
|
+
color: '#262626',
|
|
31
|
+
spacing: 32
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
draw_grid({
|
|
35
|
+
ctx,
|
|
36
|
+
width,
|
|
37
|
+
height,
|
|
38
|
+
color: '#303030',
|
|
39
|
+
spacing: 32,
|
|
40
|
+
offset_x: 16,
|
|
41
|
+
offset_y: 16
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
ctx.fillStyle = 'none';
|
|
45
|
+
ctx.strokeStyle = '#00ff00';
|
|
46
|
+
ctx.lineWidth = 1;
|
|
47
|
+
plot_array(ctx, width - margin.x * 2, height - margin.y * 2, margin.x, margin.y, data, range_y);
|
|
48
|
+
|
|
49
|
+
}
|
|
@@ -5,15 +5,19 @@ import {Transform} from "../transform/Transform";
|
|
|
5
5
|
export class EntityNode {
|
|
6
6
|
constructor(entity?: EntityBuilder)
|
|
7
7
|
|
|
8
|
-
parent: EntityNode | null
|
|
9
|
-
entity: EntityBuilder
|
|
8
|
+
readonly parent: EntityNode | null
|
|
9
|
+
readonly entity: EntityBuilder
|
|
10
10
|
|
|
11
|
-
transform: Transform
|
|
11
|
+
readonly transform: Transform
|
|
12
|
+
|
|
13
|
+
readonly children: Readonly<EntityNode[]>
|
|
12
14
|
|
|
13
15
|
addChild(node: EntityNode): boolean
|
|
14
16
|
|
|
15
17
|
removeChild(node: EntityNode): boolean
|
|
16
18
|
|
|
19
|
+
traverseChildren(visitor: (EntityNode) => void, thisArg?: any): void
|
|
20
|
+
|
|
17
21
|
build(ecd: EntityComponentDataset): void
|
|
18
22
|
|
|
19
23
|
destroy(): void
|
|
@@ -41,6 +41,23 @@ export class EntityNode {
|
|
|
41
41
|
this.__transform = new Transform();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {(EntityNode) => *} visitor
|
|
47
|
+
* @param {*} [context]
|
|
48
|
+
*/
|
|
49
|
+
traverseChildren(visitor, context) {
|
|
50
|
+
this.__children.forEach(visitor, context);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @return {Readonly<EntityNode[]>}
|
|
56
|
+
*/
|
|
57
|
+
get children() {
|
|
58
|
+
return this.__children;
|
|
59
|
+
}
|
|
60
|
+
|
|
44
61
|
/**
|
|
45
62
|
*
|
|
46
63
|
* @private
|
|
@@ -162,6 +179,10 @@ export class EntityNode {
|
|
|
162
179
|
}
|
|
163
180
|
}
|
|
164
181
|
|
|
182
|
+
/**
|
|
183
|
+
*
|
|
184
|
+
* @return {EntityBuilder}
|
|
185
|
+
*/
|
|
165
186
|
get entity() {
|
|
166
187
|
return this.__entity;
|
|
167
188
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ShadedGeometry } from "../../graphics/ecs/mesh-v2/ShadedGeometry.js";
|
|
2
|
+
import { AABB3 } from "../../../core/bvh2/aabb3/AABB3.js";
|
|
3
|
+
|
|
4
|
+
const scratch_aabb3 = new AABB3();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {AABB3} out
|
|
9
|
+
* @param {EntityNode} root
|
|
10
|
+
*/
|
|
11
|
+
export function entity_node_expand_bounding_box_to_fit(out, root) {
|
|
12
|
+
const sg = root.entity.getComponent(ShadedGeometry);
|
|
13
|
+
|
|
14
|
+
if (sg !== null) {
|
|
15
|
+
sg.getBoundingBox(scratch_aabb3);
|
|
16
|
+
|
|
17
|
+
out.expandToFit(scratch_aabb3);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const children = root.children;
|
|
21
|
+
const child_count = children.length;
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < child_count; i++) {
|
|
24
|
+
const child = children[i];
|
|
25
|
+
|
|
26
|
+
entity_node_expand_bounding_box_to_fit(out, child);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {AABB3} out
|
|
33
|
+
* @param {EntityNode} root
|
|
34
|
+
*/
|
|
35
|
+
export function entity_node_compute_bounding_box(out, root) {
|
|
36
|
+
// init bounds
|
|
37
|
+
out.setNegativelyInfiniteBounds();
|
|
38
|
+
|
|
39
|
+
// expand bounds to fit the tree
|
|
40
|
+
entity_node_expand_bounding_box_to_fit(out, root);
|
|
41
|
+
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import {Color} from "../../../../core/color/Color";
|
|
2
2
|
|
|
3
3
|
export class HighlightDefinition {
|
|
4
|
-
color: Color
|
|
4
|
+
readonly color: Color
|
|
5
5
|
opacity: number
|
|
6
|
+
|
|
7
|
+
static rgba(r: number, g: number, b: number, a?: number): HighlightDefinition
|
|
8
|
+
|
|
9
|
+
equals(other: HighlightDefinition): boolean
|
|
10
|
+
|
|
11
|
+
hash(): number
|
|
12
|
+
|
|
13
|
+
fromJSON(json: any): void
|
|
14
|
+
|
|
15
|
+
toJSON(): any
|
|
6
16
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Color } from "../../../../core/color/Color.js";
|
|
2
2
|
import { assert } from "../../../../core/assert.js";
|
|
3
|
-
import { COMPONENT_SERIALIZATION_TRANSIENT_FIELD } from "../../../ecs/storage/COMPONENT_SERIALIZATION_TRANSIENT_FIELD.js";
|
|
4
3
|
import { computeHashIntegerArray } from "../../../../core/collection/array/computeHashIntegerArray.js";
|
|
5
4
|
import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
|
|
6
5
|
|
|
@@ -8,7 +7,7 @@ export class HighlightDefinition {
|
|
|
8
7
|
constructor() {
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* @readonly
|
|
12
11
|
* @type {Color}
|
|
13
12
|
*/
|
|
14
13
|
this.color = new Color();
|
|
@@ -18,12 +17,6 @@ export class HighlightDefinition {
|
|
|
18
17
|
* @type {number}
|
|
19
18
|
*/
|
|
20
19
|
this.opacity = 1;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @type {boolean}
|
|
25
|
-
*/
|
|
26
|
-
this[COMPONENT_SERIALIZATION_TRANSIENT_FIELD] = false;
|
|
27
20
|
}
|
|
28
21
|
|
|
29
22
|
/**
|
|
@@ -73,4 +66,21 @@ export class HighlightDefinition {
|
|
|
73
66
|
|
|
74
67
|
return r;
|
|
75
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @param {number} r
|
|
73
|
+
* @param {number} g
|
|
74
|
+
* @param {number} b
|
|
75
|
+
* @param {number} [a]
|
|
76
|
+
* @return {HighlightDefinition}
|
|
77
|
+
*/
|
|
78
|
+
static rgba(r, g, b, a = 1) {
|
|
79
|
+
const result = new HighlightDefinition();
|
|
80
|
+
|
|
81
|
+
result.color.setRGB(r, g, b);
|
|
82
|
+
result.opacity = a;
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
76
86
|
}
|
|
@@ -10,7 +10,9 @@ import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererCo
|
|
|
10
10
|
import { assert } from "../../../../core/assert.js";
|
|
11
11
|
import { ray3_array_compose } from "../../../../core/geom/3d/ray/ray3_array_compose.js";
|
|
12
12
|
import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ExplicitBinaryBoundingVolumeHierarchy
|
|
15
|
+
} from "../../../../core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
14
16
|
import { bvh_query_leaves_generic } from "../../../../core/bvh2/bvh3/bvh_query_leaves_generic.js";
|
|
15
17
|
import { BVHQueryIntersectsRay } from "../../../../core/bvh2/bvh3/query/BVHQueryIntersectsRay.js";
|
|
16
18
|
|
|
@@ -157,6 +159,8 @@ export class ShadedGeometrySystem extends System {
|
|
|
157
159
|
|
|
158
160
|
async startup(entityManager, readyCallback, errorCallback) {
|
|
159
161
|
|
|
162
|
+
this.entityManager = entityManager;
|
|
163
|
+
|
|
160
164
|
const engine = this.__engine;
|
|
161
165
|
const graphics = engine.graphics;
|
|
162
166
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export const SGMeshFlags = {
|
|
2
|
+
CastShadow: 1,
|
|
3
|
+
ReceiveShadow: 2
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export class SGMesh {
|
|
7
|
+
constructor() {
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @type {string|null}
|
|
11
|
+
*/
|
|
12
|
+
this.__url = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {EntityNode|null}
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
this.__node = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
this.flags = 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @returns {string|null}
|
|
31
|
+
*/
|
|
32
|
+
get url() {
|
|
33
|
+
return this.__url;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {string|null} v
|
|
39
|
+
*/
|
|
40
|
+
set url(v) {
|
|
41
|
+
if (v === this.__url) {
|
|
42
|
+
// no change
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.__url = v;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param {number|SGMeshFlags} flag
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
setFlag(flag) {
|
|
55
|
+
this.flags |= flag;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @param {number|SGMeshFlags} flag
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
clearFlag(flag) {
|
|
64
|
+
this.flags &= ~flag;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @param {number|SGMeshFlags} flag
|
|
70
|
+
* @param {boolean} value
|
|
71
|
+
*/
|
|
72
|
+
writeFlag(flag, value) {
|
|
73
|
+
if (value) {
|
|
74
|
+
this.setFlag(flag);
|
|
75
|
+
} else {
|
|
76
|
+
this.clearFlag(flag);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {number|SGMeshFlags} flag
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
getFlag(flag) {
|
|
86
|
+
return (this.flags & flag) === flag;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
*
|
|
91
|
+
* @return {boolean}
|
|
92
|
+
*/
|
|
93
|
+
get castShadow() {
|
|
94
|
+
return this.getFlag(SGMeshFlags.CastShadow);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
* @param {boolean} v
|
|
100
|
+
*/
|
|
101
|
+
set castShadow(v) {
|
|
102
|
+
this.writeFlag(SGMeshFlags.CastShadow, v);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @return {boolean}
|
|
108
|
+
*/
|
|
109
|
+
get receiveShadow() {
|
|
110
|
+
return this.getFlag(SGMeshFlags.ReceiveShadow);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
* @param {boolean} v
|
|
116
|
+
*/
|
|
117
|
+
set receiveShadow(v) {
|
|
118
|
+
this.writeFlag(SGMeshFlags.ReceiveShadow, v);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
SGMesh.typeName = "SGMesh";
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { System } from "../../../../ecs/System.js";
|
|
2
|
+
import { SGMesh } from "./SGMesh.js";
|
|
3
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
4
|
+
import { assetTypeByPath } from "../../mesh/assetTypeByPath.js";
|
|
5
|
+
import { three_object_to_entity_composition } from "../three_object_to_entity_composition.js";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @readonly
|
|
10
|
+
* @type {number}
|
|
11
|
+
*/
|
|
12
|
+
const CYCLE_COUNT = 128;
|
|
13
|
+
|
|
14
|
+
export class SGMeshSystem extends System {
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {Engine} engine
|
|
18
|
+
*/
|
|
19
|
+
constructor(engine) {
|
|
20
|
+
super();
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @type {Engine}
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
this.__engine = engine;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @type {AssetManager}
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
this.__assetManager = engine.assetManager;
|
|
35
|
+
|
|
36
|
+
this.dependencies = [SGMesh, Transform];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @type {number[]}
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
this.__wait_queue = [];
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @type {number}
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
this.__wait_queue_process_index = 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {number} entity
|
|
55
|
+
* @param {SGMesh} mesh
|
|
56
|
+
* @param {Transform} transform
|
|
57
|
+
*/
|
|
58
|
+
async process(entity, mesh, transform) {
|
|
59
|
+
const am = this.__assetManager;
|
|
60
|
+
|
|
61
|
+
const assetType = assetTypeByPath(component.url);
|
|
62
|
+
|
|
63
|
+
const asset = await am.promise(mesh.url, assetType);
|
|
64
|
+
|
|
65
|
+
// TODO check that entity still exists, as we get to this point asynchronously
|
|
66
|
+
|
|
67
|
+
const entity_node = three_object_to_entity_composition(asset.create());
|
|
68
|
+
|
|
69
|
+
mesh.__node = entity_node;
|
|
70
|
+
|
|
71
|
+
entity_node.build(this.entityManager.dataset);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @param {SGMesh} mesh
|
|
77
|
+
* @param {Transform} transform
|
|
78
|
+
* @param {number} entity
|
|
79
|
+
*/
|
|
80
|
+
link(mesh, transform, entity) {
|
|
81
|
+
if (mesh.url === null) {
|
|
82
|
+
this.__wait_queue.push(entity);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.process(entity, mesh, transform);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
*
|
|
91
|
+
* @param {SGMesh} mesh
|
|
92
|
+
* @param {Transform} transform
|
|
93
|
+
* @param {number} entity
|
|
94
|
+
*/
|
|
95
|
+
unlink(mesh, transform, entity) {
|
|
96
|
+
if (mesh.__node !== null) {
|
|
97
|
+
mesh.__node.destroy();
|
|
98
|
+
|
|
99
|
+
mesh.__node = null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// check the queue
|
|
103
|
+
const i = this.__wait_queue.indexOf(entity);
|
|
104
|
+
|
|
105
|
+
if (i !== -1) {
|
|
106
|
+
this.__wait_queue.splice(i, 1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
update(time_delta) {
|
|
111
|
+
|
|
112
|
+
const waiting = this.__wait_queue;
|
|
113
|
+
|
|
114
|
+
let l = waiting.length;
|
|
115
|
+
|
|
116
|
+
if (l > 0) {
|
|
117
|
+
|
|
118
|
+
let pointer = this.__wait_queue_process_index;
|
|
119
|
+
|
|
120
|
+
const dataset = this.entityManager.dataset;
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < CYCLE_COUNT; i++) {
|
|
123
|
+
|
|
124
|
+
const index = pointer % l;
|
|
125
|
+
|
|
126
|
+
const entity = waiting[index];
|
|
127
|
+
|
|
128
|
+
const mesh = dataset.getComponent(entity, SGMesh);
|
|
129
|
+
|
|
130
|
+
if (mesh.url === null) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const transform = dataset.getComponent(entity, Transform);
|
|
135
|
+
|
|
136
|
+
this.process(entity, mesh, transform);
|
|
137
|
+
|
|
138
|
+
waiting.splice(i, 1);
|
|
139
|
+
|
|
140
|
+
i--;
|
|
141
|
+
l--;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.__wait_queue_process_index = pointer;
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -3,6 +3,7 @@ import { HashMap } from "../../../../../../core/collection/HashMap.js";
|
|
|
3
3
|
import { InstancedMeshGroup } from "../../../../geometry/instancing/InstancedMeshGroup.js";
|
|
4
4
|
import { ShadedGeometryFlags } from "../../ShadedGeometryFlags.js";
|
|
5
5
|
import { DrawMode } from "../../DrawMode.js";
|
|
6
|
+
import { StreamDrawUsage } from "three";
|
|
6
7
|
|
|
7
8
|
const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
|
|
8
9
|
| ShadedGeometryFlags.ReceiveShadow
|
|
@@ -89,6 +90,7 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
im = new InstancedMeshGroup();
|
|
93
|
+
im.instance_usage = StreamDrawUsage;
|
|
92
94
|
im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
|
|
93
95
|
|
|
94
96
|
im.setMaterial(sg.material);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BufferGeometry,
|
|
3
|
+
DynamicDrawUsage,
|
|
3
4
|
InstancedBufferAttribute,
|
|
4
5
|
InstancedBufferGeometry,
|
|
5
6
|
MeshDepthMaterial,
|
|
6
|
-
RGBADepthPacking
|
|
7
|
-
StreamDrawUsage
|
|
7
|
+
RGBADepthPacking
|
|
8
8
|
} from 'three';
|
|
9
9
|
import ThreeFactory from "../../three/ThreeFactory.js";
|
|
10
10
|
import { StaticMaterialCache } from "../../../asset/loaders/material/StaticMaterialCache.js";
|
|
@@ -77,6 +77,13 @@ export class InstancedMeshGroup {
|
|
|
77
77
|
*/
|
|
78
78
|
this.__attributeTransformArray = null;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @type {Usage}
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
this.__instanceUsage = DynamicDrawUsage;
|
|
86
|
+
|
|
80
87
|
/**
|
|
81
88
|
*
|
|
82
89
|
* @type {Material}
|
|
@@ -90,6 +97,30 @@ export class InstancedMeshGroup {
|
|
|
90
97
|
this.mesh = ThreeFactory.createMesh();
|
|
91
98
|
}
|
|
92
99
|
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @param {Usage} v
|
|
103
|
+
*/
|
|
104
|
+
set instance_usage(v) {
|
|
105
|
+
if (this.__instanceUsage === v) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.__instanceUsage = v;
|
|
110
|
+
|
|
111
|
+
if (this.__attributeTransform !== null) {
|
|
112
|
+
this.__attributeTransform.setUsage(v);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @return {Usage}
|
|
119
|
+
*/
|
|
120
|
+
get instance_usage() {
|
|
121
|
+
return this.__instanceUsage;
|
|
122
|
+
}
|
|
123
|
+
|
|
93
124
|
dispose() {
|
|
94
125
|
if (this.__threeGeometry !== null) {
|
|
95
126
|
this.__threeGeometry.dispose();
|
|
@@ -367,7 +398,7 @@ export class InstancedMeshGroup {
|
|
|
367
398
|
//rewrite old attributes
|
|
368
399
|
this.__attributeTransformArray = newTransformArray;
|
|
369
400
|
this.__attributeTransform = new InstancedBufferAttribute(newTransformArray, 16);
|
|
370
|
-
this.__attributeTransform.setUsage(
|
|
401
|
+
this.__attributeTransform.setUsage(this.__instanceUsage);
|
|
371
402
|
|
|
372
403
|
//add attributes to newly created geometry
|
|
373
404
|
geometry.setAttribute("instanceMatrix", this.__attributeTransform);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { deserialize_geometry_collection, serialize_geometry_collection } from "./geometry_collection_serialization.js";
|
|
2
|
+
import { BinaryBuffer } from "../../../../../../core/binary/BinaryBuffer.js";
|
|
3
|
+
|
|
4
|
+
test('serialize empty', () => {
|
|
5
|
+
const bb = new BinaryBuffer();
|
|
6
|
+
|
|
7
|
+
expect(() => {
|
|
8
|
+
serialize_geometry_collection([], bb);
|
|
9
|
+
}).not.toThrow();
|
|
10
|
+
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('serialize/deserialize empty', () => {
|
|
14
|
+
const bb = new BinaryBuffer();
|
|
15
|
+
|
|
16
|
+
serialize_geometry_collection([], bb);
|
|
17
|
+
|
|
18
|
+
bb.position = 0;
|
|
19
|
+
|
|
20
|
+
const destination = [];
|
|
21
|
+
deserialize_geometry_collection(destination, bb);
|
|
22
|
+
|
|
23
|
+
expect(destination.length).toBe(0);
|
|
24
|
+
});
|