@woosh/meep-engine 2.34.48 → 2.35.1
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/BitSet.js +7 -2
- package/core/bvh2/BinaryNode.js +19 -35
- package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +5 -5
- package/core/bvh2/aabb3_combined_surface_area.js +21 -0
- package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +24 -12
- package/core/cache/Cache.d.ts +2 -0
- package/core/cache/Cache.js +27 -23
- package/core/geom/3d/frustum/frustum_from_projection_matrix_array.js +29 -24
- package/core/math/max2.js +2 -6
- package/core/math/min2.js +2 -6
- package/engine/asset/loaders/geometry/geometry/computeGeometryEquality.js +3 -2
- package/engine/asset/loaders/geometry/geometry/computeGeometryHash.js +9 -1
- package/engine/ecs/EntityComponentDataset.js +7 -2
- package/engine/ecs/foliage/ViewState.js +13 -3
- package/engine/ecs/parent/EntityNode.js +23 -11
- package/engine/ecs/transform/Transform.js +15 -13
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +63 -26
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +63 -3
- package/engine/graphics/ecs/mesh-v2/render/AbstractRenderAdapter.js +67 -0
- package/engine/graphics/ecs/mesh-v2/render/GenericRendererAdapter.js +48 -0
- package/engine/graphics/ecs/mesh-v2/render/InstancedRendererAdapter.js +110 -0
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +98 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +5 -0
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +23 -5
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +8 -3
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +23 -85
- package/engine/graphics/geometry/instancing/rewriteMaterial.js +9 -45
- package/engine/graphics/material/optimization/BUFFER_GEOMETRY_UVS.js +10 -0
- package/engine/graphics/material/optimization/MaterialDescriptor.js +46 -0
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +470 -201
- package/engine/graphics/material/optimization/UvContext.js +18 -0
- package/engine/graphics/material/optimization/is_compliant_mesh.js +71 -0
- package/engine/graphics/material/optimization/prepare_atlas_texture.js +23 -0
- package/engine/graphics/material/optimization/prototypeMaterialOptimizer.js +127 -0
- package/engine/graphics/micron/convert_three_object_to_micron.js +0 -2
- package/engine/graphics/micron/format/MicronGeometryPatch.js +34 -24
- package/engine/graphics/micron/format/VirtualGeometry.js +47 -11
- package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +22 -0
- package/engine/graphics/micron/prototypeVirtualGeometry.js +6 -3
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +9 -18
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +1 -45
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +18 -7
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -12
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +19 -24
- package/engine/graphics/micron/render/v1/MaterialContext.js +3 -2
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +19 -4
- package/engine/graphics/render/utils/ThreeBypassRenderer.js +3 -2
- package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
- package/engine/graphics/texture/normalized_internal_format.js +48 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +6 -0
- package/engine/graphics/texture/sampler/sampler2d_copy_channel_data.js +25 -0
- package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -0
- package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +14 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { array_remove_first } from "../../../core/collection/array/array_remove_
|
|
|
4
4
|
import { assert } from "../../../core/assert.js";
|
|
5
5
|
import { array_push_if_unique } from "../../../core/collection/array/array_push_if_unique.js";
|
|
6
6
|
import { Transform } from "../transform/Transform.js";
|
|
7
|
-
import { TransformAttachment } from "../transform-attachment/TransformAttachment.js";
|
|
7
|
+
import { TransformAttachment, TransformAttachmentFlags } from "../transform-attachment/TransformAttachment.js";
|
|
8
8
|
|
|
9
9
|
export class EntityNode {
|
|
10
10
|
/**
|
|
@@ -18,12 +18,14 @@ export class EntityNode {
|
|
|
18
18
|
* @private
|
|
19
19
|
*/
|
|
20
20
|
this.__parent = null;
|
|
21
|
+
|
|
21
22
|
/**
|
|
22
23
|
*
|
|
23
24
|
* @type {EntityBuilder}
|
|
24
25
|
* @private
|
|
25
26
|
*/
|
|
26
27
|
this.__entity = entity;
|
|
28
|
+
|
|
27
29
|
/**
|
|
28
30
|
*
|
|
29
31
|
* @type {EntityNode[]}
|
|
@@ -32,7 +34,7 @@ export class EntityNode {
|
|
|
32
34
|
this.__children = [];
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
37
|
+
* Local transform
|
|
36
38
|
* @type {Transform}
|
|
37
39
|
* @private
|
|
38
40
|
*/
|
|
@@ -45,13 +47,18 @@ export class EntityNode {
|
|
|
45
47
|
*/
|
|
46
48
|
__transform_sync_down() {
|
|
47
49
|
|
|
50
|
+
const transform = this.__transform;
|
|
51
|
+
|
|
48
52
|
if (this.__parent === null) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
// not attached to anything, world and local transforms match
|
|
54
|
+
const cTransform = this.__entity.getComponent(Transform);
|
|
55
|
+
|
|
56
|
+
if (cTransform !== null) {
|
|
57
|
+
cTransform.copy(transform);
|
|
52
58
|
}
|
|
59
|
+
|
|
53
60
|
} else {
|
|
54
|
-
this.__safe_get_attachment().transform.copy(
|
|
61
|
+
this.__safe_get_attachment().transform.copy(transform);
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
}
|
|
@@ -85,7 +92,7 @@ export class EntityNode {
|
|
|
85
92
|
|
|
86
93
|
if (attachment === null) {
|
|
87
94
|
attachment = new TransformAttachment();
|
|
88
|
-
attachment.
|
|
95
|
+
attachment.setFlag(TransformAttachmentFlags.Immediate);
|
|
89
96
|
|
|
90
97
|
entity.add(attachment);
|
|
91
98
|
}
|
|
@@ -115,13 +122,15 @@ export class EntityNode {
|
|
|
115
122
|
set parent(node) {
|
|
116
123
|
this.__parent = node;
|
|
117
124
|
|
|
125
|
+
const this_entity = this.__entity;
|
|
126
|
+
|
|
118
127
|
// check if entity is built
|
|
119
|
-
if (!
|
|
128
|
+
if (!this_entity.isBuilt) {
|
|
120
129
|
return;
|
|
121
130
|
}
|
|
122
131
|
|
|
123
|
-
let parent_entity =
|
|
124
|
-
let attachment =
|
|
132
|
+
let parent_entity = this_entity.removeComponent(ParentEntity);
|
|
133
|
+
let attachment = this_entity.removeComponent(TransformAttachment);
|
|
125
134
|
|
|
126
135
|
if (node !== null) {
|
|
127
136
|
|
|
@@ -141,7 +150,7 @@ export class EntityNode {
|
|
|
141
150
|
parent_entity.entity = parent_entity_id;
|
|
142
151
|
|
|
143
152
|
// add component back
|
|
144
|
-
|
|
153
|
+
this_entity.add(parent_entity);
|
|
145
154
|
|
|
146
155
|
|
|
147
156
|
// handle component Attachment
|
|
@@ -230,6 +239,8 @@ export class EntityNode {
|
|
|
230
239
|
}
|
|
231
240
|
|
|
232
241
|
this.__transform_sync_down();
|
|
242
|
+
|
|
243
|
+
// attach listeners
|
|
233
244
|
this.__transform.position.onChanged.add(this.__transform_sync_down, this);
|
|
234
245
|
this.__transform.scale.onChanged.add(this.__transform_sync_down, this);
|
|
235
246
|
this.__transform.rotation.onChanged.add(this.__transform_sync_down, this);
|
|
@@ -247,6 +258,7 @@ export class EntityNode {
|
|
|
247
258
|
}
|
|
248
259
|
|
|
249
260
|
destroy() {
|
|
261
|
+
// remove listeners
|
|
250
262
|
this.__transform.position.onChanged.remove(this.__transform_sync_down, this);
|
|
251
263
|
this.__transform.scale.onChanged.remove(this.__transform_sync_down, this);
|
|
252
264
|
this.__transform.rotation.onChanged.remove(this.__transform_sync_down, this);
|
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
6
6
|
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
7
|
-
import { Matrix4 } from "../../../core/geom/Matrix4.js";
|
|
8
7
|
import { compose_matrix4_array } from "../../graphics/util/composeMatrix4.js";
|
|
9
8
|
import { decompose_matrix_4_array } from "../../graphics/util/decompose_matrix_4_array.js";
|
|
9
|
+
import { mat4 } from "gl-matrix";
|
|
10
10
|
|
|
11
11
|
const delta = new Vector3();
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const scratch_buffer = new ArrayBuffer(32 * 4);
|
|
14
|
+
|
|
15
|
+
const m4_0 = new Float32Array(scratch_buffer, 0, 16);
|
|
16
|
+
const m4_1 = new Float32Array(scratch_buffer, 64, 16)
|
|
15
17
|
|
|
16
18
|
export class Transform {
|
|
17
19
|
/**
|
|
@@ -152,12 +154,12 @@ export class Transform {
|
|
|
152
154
|
* @param {Transform} b
|
|
153
155
|
*/
|
|
154
156
|
multiplyTransforms(a, b) {
|
|
155
|
-
m4_0
|
|
156
|
-
m4_1
|
|
157
|
+
compose_matrix4_array(m4_0, a.position, a.rotation, a.scale);
|
|
158
|
+
compose_matrix4_array(m4_1, b.position, b.rotation, b.scale);
|
|
157
159
|
|
|
158
|
-
|
|
160
|
+
mat4.multiply(m4_0, m4_0, m4_1);
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
this.fromMatrix4(m4_0);
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
/**
|
|
@@ -170,18 +172,18 @@ export class Transform {
|
|
|
170
172
|
|
|
171
173
|
/**
|
|
172
174
|
*
|
|
173
|
-
* @param {
|
|
175
|
+
* @param {Matrix4} matrix
|
|
174
176
|
*/
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
toThreeMatrix(matrix) {
|
|
178
|
+
this.toMatrix4(matrix.elements);
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
/**
|
|
180
182
|
*
|
|
181
|
-
* @param {
|
|
183
|
+
* @param {mat4|number[]|Float32Array} m
|
|
182
184
|
*/
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
+
fromMatrix4(m) {
|
|
186
|
+
decompose_matrix_4_array(m, this.position, this.rotation, this.scale);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
/**
|
|
@@ -12,6 +12,42 @@ const DEFAULT_FLAGS = ShadedGeometryFlags.CastShadow
|
|
|
12
12
|
| ShadedGeometryFlags.ReceiveShadow
|
|
13
13
|
;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {ShadedGeometry} sg
|
|
18
|
+
* @returns {THREE.Object3D}
|
|
19
|
+
*/
|
|
20
|
+
export function build_three_object(sg) {
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @type {THREE.Object3D}
|
|
24
|
+
*/
|
|
25
|
+
let object;
|
|
26
|
+
|
|
27
|
+
const mode = sg.mode;
|
|
28
|
+
const shader = sg.material;
|
|
29
|
+
const geo = sg.geometry;
|
|
30
|
+
|
|
31
|
+
if (mode === DrawMode.Triangles) {
|
|
32
|
+
object = new Mesh(geo, shader);
|
|
33
|
+
} else if (mode === DrawMode.Lines) {
|
|
34
|
+
object = new Line(geo, shader);
|
|
35
|
+
} else if (mode === DrawMode.LineSegments) {
|
|
36
|
+
object = new LineSegments(geo, shader);
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`Unsupported draw mode '${mode}'`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
object.matrixAutoUpdate = false;
|
|
42
|
+
object.frustumCulled = false;
|
|
43
|
+
object.matrixWorldNeedsUpdate = false;
|
|
44
|
+
|
|
45
|
+
object.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
|
|
46
|
+
object.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
47
|
+
|
|
48
|
+
return object;
|
|
49
|
+
}
|
|
50
|
+
|
|
15
51
|
export class ShadedGeometry {
|
|
16
52
|
constructor() {
|
|
17
53
|
/**
|
|
@@ -51,6 +87,7 @@ export class ShadedGeometry {
|
|
|
51
87
|
* @private
|
|
52
88
|
*/
|
|
53
89
|
this.__entity = -1;
|
|
90
|
+
|
|
54
91
|
/**
|
|
55
92
|
* Transform matrix
|
|
56
93
|
* Transient, assigned in the system
|
|
@@ -59,6 +96,12 @@ export class ShadedGeometry {
|
|
|
59
96
|
*/
|
|
60
97
|
this.__transform = null;
|
|
61
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Transient property signifying how to render object
|
|
101
|
+
* @type {number}
|
|
102
|
+
*/
|
|
103
|
+
this.draw_method = 0;
|
|
104
|
+
|
|
62
105
|
/**
|
|
63
106
|
*
|
|
64
107
|
* @type {number}
|
|
@@ -106,6 +149,25 @@ export class ShadedGeometry {
|
|
|
106
149
|
return (this.flags & flag) === flag;
|
|
107
150
|
}
|
|
108
151
|
|
|
152
|
+
/**
|
|
153
|
+
*
|
|
154
|
+
* @return {number}
|
|
155
|
+
*/
|
|
156
|
+
hash() {
|
|
157
|
+
return this.geometry.id ^ this.material.id;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* @param {ShadedGeometry} other
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
equals(other) {
|
|
166
|
+
return this.geometry.id === other.geometry.id
|
|
167
|
+
&& this.material.id === other.material.id
|
|
168
|
+
;
|
|
169
|
+
}
|
|
170
|
+
|
|
109
171
|
/**
|
|
110
172
|
* Current cached entity that this component is attached to
|
|
111
173
|
* @return {number}
|
|
@@ -130,32 +192,7 @@ export class ShadedGeometry {
|
|
|
130
192
|
}
|
|
131
193
|
|
|
132
194
|
__build_object() {
|
|
133
|
-
|
|
134
|
-
* @type {THREE.Object3D}
|
|
135
|
-
*/
|
|
136
|
-
let object;
|
|
137
|
-
|
|
138
|
-
const mode = this.mode;
|
|
139
|
-
const shader = this.material;
|
|
140
|
-
const geo = this.geometry;
|
|
141
|
-
|
|
142
|
-
if (mode === DrawMode.Triangles) {
|
|
143
|
-
object = new Mesh(geo, shader);
|
|
144
|
-
} else if (mode === DrawMode.Lines) {
|
|
145
|
-
object = new Line(geo, shader);
|
|
146
|
-
} else if (mode === DrawMode.LineSegments) {
|
|
147
|
-
object = new LineSegments(geo, shader);
|
|
148
|
-
} else {
|
|
149
|
-
throw new Error(`Unsupported draw mode '${mode}'`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
object.matrixAutoUpdate = false;
|
|
153
|
-
object.frustumCulled = false;
|
|
154
|
-
|
|
155
|
-
object.castShadow = this.getFlag(ShadedGeometryFlags.CastShadow);
|
|
156
|
-
object.receiveShadow = this.getFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
157
|
-
|
|
158
|
-
this.__cached_object = object;
|
|
195
|
+
this.__cached_object = build_three_object(this);
|
|
159
196
|
}
|
|
160
197
|
|
|
161
198
|
get bvh() {
|
|
@@ -7,6 +7,8 @@ import { v3_distance_sqr } from "../../../../core/geom/v3_distance_sqr.js";
|
|
|
7
7
|
import { mat4 } from "gl-matrix";
|
|
8
8
|
import { returnTrue } from "../../../../core/function/Functions.js";
|
|
9
9
|
import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
10
|
+
import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
|
|
11
|
+
import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
*
|
|
@@ -54,14 +56,72 @@ export class ShadedGeometrySystem extends System {
|
|
|
54
56
|
* @private
|
|
55
57
|
*/
|
|
56
58
|
this.__render_layer = null;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
* @type {Map<CameraView, ShadedGeometryRendererContext>}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
this.__view_contexts = new Map();
|
|
66
|
+
|
|
67
|
+
this.__bvh = new BinaryNode();
|
|
68
|
+
this.__bvh.setNegativelyInfiniteBounds();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @param {CameraView} view
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
__handle_view_added(view) {
|
|
77
|
+
this.__view_contexts.set(view, new ShadedGeometryRendererContext());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {CameraView} view
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
__handle_view_removed(view) {
|
|
86
|
+
const ctx = this.__view_contexts.get(view);
|
|
87
|
+
|
|
88
|
+
this.__view_contexts.delete(view);
|
|
89
|
+
|
|
90
|
+
ctx.dispose();
|
|
57
91
|
}
|
|
58
92
|
|
|
59
93
|
async startup(entityManager, readyCallback, errorCallback) {
|
|
60
94
|
|
|
61
95
|
const engine = this.__engine;
|
|
96
|
+
const graphics = engine.graphics;
|
|
97
|
+
|
|
98
|
+
const view_list = graphics.views.elements;
|
|
99
|
+
|
|
100
|
+
view_list.forEach(this.__handle_view_added, this);
|
|
101
|
+
view_list.on.added.add(this.__handle_view_added, this);
|
|
102
|
+
view_list.on.removed.add(this.__handle_view_removed, this);
|
|
103
|
+
|
|
104
|
+
this.__render_layer = graphics.layers.create('shaded-geometry');
|
|
105
|
+
|
|
106
|
+
this.__render_layer.buildVisibleSet = ((destination, destination_offset, view) => {
|
|
107
|
+
const ctx = this.__view_contexts.get(view);
|
|
108
|
+
|
|
109
|
+
return ctx.collect(destination, destination_offset, view, this.__bvh);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
readyCallback();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async shutdown(entityManager, readyCallback, errorCallback) {
|
|
116
|
+
|
|
117
|
+
const engine = this.__engine;
|
|
118
|
+
const graphics = engine.graphics;
|
|
119
|
+
|
|
120
|
+
const view_list = graphics.views.elements;
|
|
62
121
|
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
122
|
+
view_list.forEach(this.__handle_view_removed, this);
|
|
123
|
+
view_list.on.added.remove(this.__handle_view_added, this);
|
|
124
|
+
view_list.on.removed.remove(this.__handle_view_removed, this);
|
|
65
125
|
|
|
66
126
|
readyCallback();
|
|
67
127
|
}
|
|
@@ -87,7 +147,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
87
147
|
// remember entity for lookups
|
|
88
148
|
sg.__entity = entity;
|
|
89
149
|
|
|
90
|
-
this.
|
|
150
|
+
this.__bvh.insertNode(leaf_node);
|
|
91
151
|
}
|
|
92
152
|
|
|
93
153
|
/**
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export class AbstractRenderAdapter {
|
|
2
|
+
constructor() {
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @type {number}
|
|
7
|
+
* @protected
|
|
8
|
+
*/
|
|
9
|
+
this.__object_count = 0;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @type {THREE.Object3D[]}
|
|
14
|
+
* @protected
|
|
15
|
+
*/
|
|
16
|
+
this.__objects = [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param {THREE.BufferGeometry} geometry
|
|
22
|
+
* @param {THREE.Material} material
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
score(geometry, material) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param {ShadedGeometry} sg
|
|
32
|
+
* @returns {void}
|
|
33
|
+
*/
|
|
34
|
+
add(sg) {
|
|
35
|
+
throw new Error('Not Implemented');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
build_start() {
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
build_end() {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
clear() {
|
|
47
|
+
this.__object_count = 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @returns {THREE.Object3D[]}
|
|
52
|
+
*/
|
|
53
|
+
get objects() {
|
|
54
|
+
return this.__objects;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @returns {number}
|
|
59
|
+
*/
|
|
60
|
+
get object_count() {
|
|
61
|
+
return this.__object_count;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
dispose() {
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
|
|
2
|
+
import { build_three_object } from "../ShadedGeometry.js";
|
|
3
|
+
import { array_copy } from "../../../../../core/collection/array/copyArray.js";
|
|
4
|
+
|
|
5
|
+
export class GenericRendererAdapter extends AbstractRenderAdapter {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @type {Cache<ShadedGeometry, THREE.Object3D>}
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
this.__cache = new WeakMap();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
score(geometry, material) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
build_start() {
|
|
23
|
+
this.clear();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
add(sg) {
|
|
27
|
+
const cache = this.__cache;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @type {THREE.Object3D}
|
|
32
|
+
*/
|
|
33
|
+
let object = cache.get(sg);
|
|
34
|
+
|
|
35
|
+
if (object === undefined) {
|
|
36
|
+
|
|
37
|
+
object = build_three_object(sg);
|
|
38
|
+
|
|
39
|
+
cache.set(sg, object);
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
array_copy(sg.__transform, 0, object.matrixWorld.elements, 0, 16);
|
|
44
|
+
|
|
45
|
+
this.__objects[this.__object_count++] = object;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
|
|
2
|
+
import { HashMap } from "../../../../../core/collection/HashMap.js";
|
|
3
|
+
import { InstancedMeshGroup } from "../../../geometry/instancing/InstancedMeshGroup.js";
|
|
4
|
+
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
5
|
+
|
|
6
|
+
const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
|
|
7
|
+
| ShadedGeometryFlags.ReceiveShadow
|
|
8
|
+
;
|
|
9
|
+
|
|
10
|
+
export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {HashMap<ShadedGeometry, InstancedMeshGroup>}
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
this.__instanced_meshes = new HashMap({
|
|
20
|
+
keyHashFunction(sg) {
|
|
21
|
+
return sg.geometry.id ^ sg.material.id;
|
|
22
|
+
},
|
|
23
|
+
keyEqualityFunction(a, b) {
|
|
24
|
+
return a.material.id === b.material.id
|
|
25
|
+
&& a.geometry.id === b.geometry.id
|
|
26
|
+
&& (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
|
|
27
|
+
;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @type {Set<InstancedMeshGroup>}
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
this.__active_meshes = new Set();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param {ShadedGeometry} sg
|
|
42
|
+
* @returns {InstancedMeshGroup}
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
__get_instanced_mesh(sg) {
|
|
46
|
+
let im = this.__instanced_meshes.get(sg);
|
|
47
|
+
|
|
48
|
+
if (im === undefined) {
|
|
49
|
+
im = new InstancedMeshGroup();
|
|
50
|
+
im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
|
|
51
|
+
|
|
52
|
+
im.setMaterial(sg.material);
|
|
53
|
+
im.setGeometry(sg.geometry);
|
|
54
|
+
|
|
55
|
+
im.mesh.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
|
|
56
|
+
im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
57
|
+
|
|
58
|
+
this.__instanced_meshes.set(sg, im);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return im;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
add(sg) {
|
|
65
|
+
const mesh = this.__get_instanced_mesh(sg);
|
|
66
|
+
|
|
67
|
+
const index = mesh.count;
|
|
68
|
+
|
|
69
|
+
mesh.ensureCapacity(index + 1);
|
|
70
|
+
|
|
71
|
+
mesh.setTransformAt(index, sg.transform);
|
|
72
|
+
|
|
73
|
+
mesh.count++;
|
|
74
|
+
|
|
75
|
+
this.__active_meshes.add(mesh);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
build_start() {
|
|
79
|
+
this.clear();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
build_end() {
|
|
83
|
+
|
|
84
|
+
for (const activeMesh of this.__active_meshes) {
|
|
85
|
+
// force underlying geometry to update
|
|
86
|
+
activeMesh.setCount(activeMesh.getCount());
|
|
87
|
+
activeMesh.requestAttributeUpdate();
|
|
88
|
+
|
|
89
|
+
this.__objects[this.__object_count++] = activeMesh.mesh;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
clear() {
|
|
95
|
+
super.clear();
|
|
96
|
+
|
|
97
|
+
for (const activeMesh of this.__active_meshes) {
|
|
98
|
+
activeMesh.setCount(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.__active_meshes.clear();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
dispose() {
|
|
105
|
+
// release GPU memory
|
|
106
|
+
this.__instanced_meshes.forEach((value, key) => {
|
|
107
|
+
value.dispose();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { queryBinaryNode_FrustumIntersections_Data } from "../../../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
|
|
2
|
+
import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
|
|
3
|
+
import { InstancedRendererAdapter } from "./InstancedRendererAdapter.js";
|
|
4
|
+
import { GenericRendererAdapter } from "./GenericRendererAdapter.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 1 - collect visible meshes
|
|
8
|
+
* 2 - figure out how to render a given mesh
|
|
9
|
+
*/
|
|
10
|
+
export class ShadedGeometryRendererContext {
|
|
11
|
+
constructor() {
|
|
12
|
+
/**
|
|
13
|
+
* @readonly
|
|
14
|
+
* @type {AbstractRenderAdapter[]}
|
|
15
|
+
*/
|
|
16
|
+
this.adapters = [
|
|
17
|
+
new GenericRendererAdapter(),
|
|
18
|
+
new InstancedRendererAdapter()
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setAdapter(index, adapter) {
|
|
23
|
+
const existing = this.adapters[index];
|
|
24
|
+
if (existing !== undefined) {
|
|
25
|
+
// dispose of existing adapter
|
|
26
|
+
existing.dispose();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.adapters[index] = adapter;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {THREE.Object3D[]} destination
|
|
35
|
+
* @param {number} destination_offset
|
|
36
|
+
* @param {CameraView} view
|
|
37
|
+
* @param {BinaryNode<ShadedGeometry>} bvh
|
|
38
|
+
*/
|
|
39
|
+
collect(destination, destination_offset, view, bvh) {
|
|
40
|
+
const adapters = this.adapters;
|
|
41
|
+
const adapter_count = adapters.length;
|
|
42
|
+
|
|
43
|
+
let i = 0, j = 0;
|
|
44
|
+
for (; i < adapter_count; i++) {
|
|
45
|
+
const adapter = adapters[i];
|
|
46
|
+
|
|
47
|
+
adapter.build_start();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// get all meshes
|
|
52
|
+
|
|
53
|
+
const data = [];
|
|
54
|
+
|
|
55
|
+
const intersection_count = queryBinaryNode_FrustumIntersections_Data(data, 0, bvh, view.frustum);
|
|
56
|
+
|
|
57
|
+
for (i = 0; i < intersection_count; i++) {
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @type {ShadedGeometry}
|
|
61
|
+
*/
|
|
62
|
+
const sg = data[i];
|
|
63
|
+
|
|
64
|
+
const adapter = adapters[sg.draw_method];
|
|
65
|
+
|
|
66
|
+
adapter.add(sg);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let additions = 0;
|
|
70
|
+
|
|
71
|
+
for (i = 0; i < adapter_count; i++) {
|
|
72
|
+
const adapter = adapters[i];
|
|
73
|
+
|
|
74
|
+
adapter.build_end();
|
|
75
|
+
|
|
76
|
+
const adapter_object_count = adapter.object_count;
|
|
77
|
+
|
|
78
|
+
for (j = 0; j < adapter_object_count; j++) {
|
|
79
|
+
const object3D = adapter.objects[j];
|
|
80
|
+
|
|
81
|
+
destination[destination_offset + additions] = object3D;
|
|
82
|
+
|
|
83
|
+
additions++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return additions;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
dispose() {
|
|
92
|
+
for (const adapter of this.adapters) {
|
|
93
|
+
if (adapter !== undefined) {
|
|
94
|
+
adapter.dispose();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|