@woosh/meep-engine 2.35.1 → 2.35.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/bvh2/aabb3/aabb3_intersects_frustum_degree.js +6 -6
- package/core/bvh2/traversal/queryBinaryNode_CollectData.js +1 -2
- package/core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js +30 -17
- package/core/collection/HashMap.js +1 -1
- package/core/geom/3d/SurfacePoint3.js +6 -6
- package/engine/ecs/EntityManager.d.ts +7 -0
- package/engine/graphics/ecs/highlight/system/ShadedGeometryHighlightSystem.js +13 -4
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +20 -119
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts +11 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +77 -13
- package/engine/graphics/ecs/mesh-v2/build_three_object.js +39 -0
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +37 -5
- package/engine/graphics/ecs/mesh-v2/render/{AbstractRenderAdapter.js → adapters/AbstractRenderAdapter.js} +13 -1
- package/engine/graphics/ecs/mesh-v2/render/{GenericRendererAdapter.js → adapters/GenericRendererAdapter.js} +8 -3
- package/engine/graphics/ecs/mesh-v2/render/{InstancedRendererAdapter.js → adapters/InstancedRendererAdapter.js} +63 -10
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +14 -5
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +0 -1
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +11 -2
- package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +150 -0
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +1 -3
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +0 -7
- package/engine/graphics/micron/render/v1/MaterialContext.js +1 -2
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +6 -12
- package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +0 -50
- package/package.json +1 -1
|
@@ -19,18 +19,18 @@ export function aabb3_intersects_frustum_degree(
|
|
|
19
19
|
frustum
|
|
20
20
|
) {
|
|
21
21
|
|
|
22
|
-
let i = 0;
|
|
23
22
|
let result = 2;
|
|
23
|
+
let i = 0;
|
|
24
24
|
|
|
25
25
|
for (; i < 24; i += 4) {
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
27
|
+
const p_x = frustum[i];
|
|
28
|
+
const p_y = frustum[i + 1];
|
|
29
|
+
const p_z = frustum[i + 2];
|
|
30
|
+
const p_w = frustum[i + 3];
|
|
31
31
|
|
|
32
32
|
const plane_side = computeAABB3PlaneSide(
|
|
33
|
-
|
|
33
|
+
p_x, p_y, p_z, p_w,
|
|
34
34
|
x0, y0, z0, x1, y1, z1
|
|
35
35
|
);
|
|
36
36
|
|
|
@@ -13,13 +13,12 @@ let stackPointer = 0;
|
|
|
13
13
|
*/
|
|
14
14
|
export function queryBinaryNode_CollectData(destination, destinationOffset, root) {
|
|
15
15
|
let n;
|
|
16
|
+
let i = 0;
|
|
16
17
|
|
|
17
18
|
const stackOffset = stackPointer;
|
|
18
19
|
|
|
19
20
|
stack[stackPointer++] = root;
|
|
20
21
|
|
|
21
|
-
let i = 0;
|
|
22
|
-
|
|
23
22
|
while (stackPointer-- > stackOffset) {
|
|
24
23
|
|
|
25
24
|
n = stack[stackPointer];
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { aabb3_intersects_frustum_degree } from "../aabb3/aabb3_intersects_frustum_degree.js";
|
|
2
|
+
import { queryBinaryNode_CollectData } from "./queryBinaryNode_CollectData.js";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
*
|
|
3
6
|
* @type {(BinaryNode|LeafNode)[]}
|
|
@@ -30,32 +33,42 @@ export function queryBinaryNode_FrustumIntersections_Data(destination, destinati
|
|
|
30
33
|
|
|
31
34
|
n = stack[stackPointer];
|
|
32
35
|
|
|
33
|
-
const
|
|
36
|
+
const intersection_degree = aabb3_intersects_frustum_degree(
|
|
37
|
+
n.x0, n.y0, n.z0,
|
|
38
|
+
n.x1, n.y1, n.z1,
|
|
39
|
+
frustum
|
|
40
|
+
);
|
|
34
41
|
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
}
|
|
42
|
+
if (intersection_degree === 2) {
|
|
43
|
+
// fully inside
|
|
38
44
|
|
|
39
|
-
|
|
45
|
+
offset += queryBinaryNode_CollectData(destination, offset, n);
|
|
40
46
|
|
|
41
|
-
|
|
47
|
+
} else if (intersection_degree === 1) {
|
|
48
|
+
// partly inside
|
|
42
49
|
|
|
43
|
-
if (
|
|
44
|
-
stack[stackPointer++] = right;
|
|
45
|
-
}
|
|
50
|
+
if (n.isBinaryNode === true) {
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
const right = n.right;
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
if (right !== null) {
|
|
55
|
+
stack[stackPointer++] = right;
|
|
56
|
+
}
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
// leaf node
|
|
58
|
+
const left = n.left;
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
if (left !== null) {
|
|
61
|
+
stack[stackPointer++] = left;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
} else {
|
|
65
|
+
// leaf node
|
|
66
|
+
|
|
67
|
+
destination[offset] = n.object;
|
|
68
|
+
|
|
69
|
+
offset++;
|
|
70
|
+
}
|
|
57
71
|
|
|
58
|
-
offset++;
|
|
59
72
|
}
|
|
60
73
|
|
|
61
74
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import Quaternion from "../Quaternion.js";
|
|
2
1
|
import Vector3 from "../Vector3.js";
|
|
3
2
|
import { v3_length } from "../v3_length.js";
|
|
4
3
|
|
|
5
|
-
const q = new Quaternion();
|
|
6
|
-
|
|
7
4
|
/**
|
|
8
5
|
* Used for representing points on a 3D surface. Used for raycasting contacts
|
|
9
6
|
*/
|
|
@@ -25,9 +22,12 @@ export class SurfacePoint3 {
|
|
|
25
22
|
const p_y = p.y;
|
|
26
23
|
const p_z = p.z;
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
25
|
+
// compute perspective projection
|
|
26
|
+
const w = 1 / (m4[3] * p_x + m4[7] * p_y + m4[11] * p_z + m4[15]);
|
|
27
|
+
|
|
28
|
+
const result_p_x = (m4[0] * p_x + m4[4] * p_y + m4[8] * p_z + m4[12]) * w;
|
|
29
|
+
const result_p_y = (m4[1] * p_x + m4[5] * p_y + m4[9] * p_z + m4[13]) * w;
|
|
30
|
+
const result_p_z = (m4[2] * p_x + m4[6] * p_y + m4[10] * p_z + m4[14]) * w;
|
|
31
31
|
|
|
32
32
|
this.position.set(
|
|
33
33
|
result_p_x,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {EntityComponentDataset} from "./EntityComponentDataset";
|
|
2
2
|
import {System} from "./System";
|
|
3
3
|
|
|
4
|
+
interface Type<T> extends Function {
|
|
5
|
+
new(...args: any[]): T;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
|
|
4
9
|
export class EntityManager {
|
|
5
10
|
dataset: EntityComponentDataset
|
|
6
11
|
|
|
@@ -10,6 +15,8 @@ export class EntityManager {
|
|
|
10
15
|
|
|
11
16
|
removeSystem<T>(system: System<T>): Promise<void>
|
|
12
17
|
|
|
18
|
+
getSystem<T>(systemClass: Type<T>): T | null
|
|
19
|
+
|
|
13
20
|
attachDataSet(dataset: EntityComponentDataset): void
|
|
14
21
|
|
|
15
22
|
detachDataSet(): void
|
|
@@ -3,6 +3,7 @@ import { HighlightRenderElementSource } from "../plugin/HighlightRenderElementSo
|
|
|
3
3
|
import Highlight from "../Highlight.js";
|
|
4
4
|
import { OutlineRenderPlugin } from "../plugin/OutlineRenderPlugin.js";
|
|
5
5
|
import { ShadedGeometry } from "../../mesh-v2/ShadedGeometry.js";
|
|
6
|
+
import { build_three_object } from "../../mesh-v2/build_three_object.js";
|
|
6
7
|
|
|
7
8
|
class Supplier extends HighlightRenderElementSource {
|
|
8
9
|
/**
|
|
@@ -31,6 +32,13 @@ class Supplier extends HighlightRenderElementSource {
|
|
|
31
32
|
* @private
|
|
32
33
|
*/
|
|
33
34
|
this.__group = null;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @type {WeakMap<ShadedGeometry, THREE.Object3D>}
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
this.__object_cache = new WeakMap();
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
collect(pool, group) {
|
|
@@ -77,13 +85,14 @@ class Supplier extends HighlightRenderElementSource {
|
|
|
77
85
|
return;
|
|
78
86
|
}
|
|
79
87
|
|
|
80
|
-
|
|
88
|
+
let object = this.__object_cache.get(sg);
|
|
81
89
|
|
|
82
|
-
if
|
|
83
|
-
|
|
84
|
-
return;
|
|
90
|
+
if(object === undefined){
|
|
91
|
+
object = build_three_object(sg);
|
|
85
92
|
}
|
|
86
93
|
|
|
94
|
+
object.matrixWorld.elements = sg.transform;
|
|
95
|
+
|
|
87
96
|
const renderElement = this.__pool.create();
|
|
88
97
|
|
|
89
98
|
renderElement.definitions = elements.asArray();
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { Line, LineSegments, Mesh } from "three";
|
|
2
1
|
import { updateNodeByMatrix4AndBBB } from "../mesh/updateNodeByTransformAndBBB.js";
|
|
3
2
|
import { LeafNode } from "../../../../core/bvh2/LeafNode.js";
|
|
4
3
|
import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
5
4
|
import { DrawMode } from "./DrawMode.js";
|
|
6
|
-
import { applyTransformToThreeObject } from "../mesh/applyTransformToThreeObject.js";
|
|
7
5
|
import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
|
|
8
6
|
|
|
9
7
|
const _aabb3 = new AABB3();
|
|
@@ -12,42 +10,6 @@ const DEFAULT_FLAGS = ShadedGeometryFlags.CastShadow
|
|
|
12
10
|
| ShadedGeometryFlags.ReceiveShadow
|
|
13
11
|
;
|
|
14
12
|
|
|
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
|
-
|
|
51
13
|
export class ShadedGeometry {
|
|
52
14
|
constructor() {
|
|
53
15
|
/**
|
|
@@ -67,13 +29,6 @@ export class ShadedGeometry {
|
|
|
67
29
|
*/
|
|
68
30
|
this.mode = DrawMode.Triangles;
|
|
69
31
|
|
|
70
|
-
/**
|
|
71
|
-
*
|
|
72
|
-
* @type {THREE.Object3D|null}
|
|
73
|
-
* @private
|
|
74
|
-
*/
|
|
75
|
-
this.__cached_object = null;
|
|
76
|
-
|
|
77
32
|
/**
|
|
78
33
|
*
|
|
79
34
|
* @type {LeafNode<ShadedGeometry>}
|
|
@@ -88,13 +43,20 @@ export class ShadedGeometry {
|
|
|
88
43
|
*/
|
|
89
44
|
this.__entity = -1;
|
|
90
45
|
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {Transform|null}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this.__c_transform = null;
|
|
52
|
+
|
|
91
53
|
/**
|
|
92
54
|
* Transform matrix
|
|
93
55
|
* Transient, assigned in the system
|
|
94
56
|
* @type {number[]|null}
|
|
95
57
|
* @private
|
|
96
58
|
*/
|
|
97
|
-
this.__transform =
|
|
59
|
+
this.__transform = new Float32Array(16);
|
|
98
60
|
|
|
99
61
|
/**
|
|
100
62
|
* Transient property signifying how to render object
|
|
@@ -109,6 +71,14 @@ export class ShadedGeometry {
|
|
|
109
71
|
this.flags = DEFAULT_FLAGS;
|
|
110
72
|
}
|
|
111
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
get __cached_object(){
|
|
79
|
+
throw new Error('Deprecated');
|
|
80
|
+
}
|
|
81
|
+
|
|
112
82
|
/**
|
|
113
83
|
*
|
|
114
84
|
* @param {number|ShadedGeometryFlags} flag
|
|
@@ -182,17 +152,7 @@ export class ShadedGeometry {
|
|
|
182
152
|
* @return {null|number[]}
|
|
183
153
|
*/
|
|
184
154
|
get transform() {
|
|
185
|
-
|
|
186
|
-
return this.__transform;
|
|
187
|
-
} else if (this.__cached_object !== null) {
|
|
188
|
-
return this.__cached_object.matrix.elements;
|
|
189
|
-
} else {
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
__build_object() {
|
|
195
|
-
this.__cached_object = build_three_object(this);
|
|
155
|
+
return this.__transform;
|
|
196
156
|
}
|
|
197
157
|
|
|
198
158
|
get bvh() {
|
|
@@ -214,13 +174,6 @@ export class ShadedGeometry {
|
|
|
214
174
|
if (geometry.boundingBox === null) {
|
|
215
175
|
geometry.computeBoundingBox();
|
|
216
176
|
}
|
|
217
|
-
|
|
218
|
-
if (this.__cached_object === null) {
|
|
219
|
-
this.__build_object();
|
|
220
|
-
} else {
|
|
221
|
-
this.__cached_object.material = material;
|
|
222
|
-
this.__cached_object.geometry = geometry;
|
|
223
|
-
}
|
|
224
177
|
}
|
|
225
178
|
|
|
226
179
|
/**
|
|
@@ -239,11 +192,8 @@ export class ShadedGeometry {
|
|
|
239
192
|
}
|
|
240
193
|
|
|
241
194
|
updateTransform() {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// update matrix
|
|
245
|
-
object_3d.updateMatrix();
|
|
246
|
-
object_3d.updateMatrixWorld();
|
|
195
|
+
//
|
|
196
|
+
this.__c_transform.toMatrix4(this.__transform);
|
|
247
197
|
|
|
248
198
|
// update bounds
|
|
249
199
|
const gbb = this.geometry.boundingBox;
|
|
@@ -260,56 +210,7 @@ export class ShadedGeometry {
|
|
|
260
210
|
max.z
|
|
261
211
|
);
|
|
262
212
|
|
|
263
|
-
updateNodeByMatrix4AndBBB(this.__bvh_leaf, _aabb3,
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
*
|
|
268
|
-
* @param {number} x
|
|
269
|
-
* @param {number} y
|
|
270
|
-
* @param {number} z
|
|
271
|
-
*/
|
|
272
|
-
setPositionByComponents(x, y, z) {
|
|
273
|
-
|
|
274
|
-
this.__cached_object.position.set(x, y, z);
|
|
275
|
-
|
|
276
|
-
this.updateTransform();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
*
|
|
281
|
-
* @param {number} x
|
|
282
|
-
* @param {number} y
|
|
283
|
-
* @param {number} z
|
|
284
|
-
* @param {number} w
|
|
285
|
-
*/
|
|
286
|
-
setRotationByComponents(x, y, z, w) {
|
|
287
|
-
|
|
288
|
-
this.__cached_object.quaternion.set(x, y, z, w);
|
|
289
|
-
|
|
290
|
-
this.updateTransform();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
*
|
|
295
|
-
* @param {number} x
|
|
296
|
-
* @param {number} y
|
|
297
|
-
* @param {number} z
|
|
298
|
-
*/
|
|
299
|
-
setScaleByComponents(x, y, z) {
|
|
300
|
-
this.__cached_object.scale.set(x, y, z);
|
|
301
|
-
|
|
302
|
-
this.updateTransform();
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
*
|
|
307
|
-
* @param {Transform} t
|
|
308
|
-
*/
|
|
309
|
-
applyTransform(t) {
|
|
310
|
-
applyTransformToThreeObject(this.__cached_object, t);
|
|
311
|
-
|
|
312
|
-
this.updateTransform();
|
|
213
|
+
updateNodeByMatrix4AndBBB(this.__bvh_leaf, _aabb3, this.__transform);
|
|
313
214
|
}
|
|
314
215
|
}
|
|
315
216
|
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import {System} from "../../../ecs/System";
|
|
2
2
|
import Engine from "../../../Engine";
|
|
3
|
+
import {ShadedGeometry} from "./ShadedGeometry";
|
|
4
|
+
import {SurfacePoint3} from "../../../../core/geom/3d/SurfacePoint3";
|
|
3
5
|
|
|
4
|
-
export class ShadedGeometrySystem extends System {
|
|
6
|
+
export class ShadedGeometrySystem extends System<ShadedGeometry> {
|
|
5
7
|
constructor(engine: Engine)
|
|
8
|
+
|
|
9
|
+
raycastNearest(
|
|
10
|
+
contact: SurfacePoint3,
|
|
11
|
+
origin_x: number, origin_y: number, origin_z: number,
|
|
12
|
+
direction_x: number, direction_y: number, direction_z: number,
|
|
13
|
+
filter_function?: (entity: number, mesh: ShadedGeometry) => boolean,
|
|
14
|
+
filter_function_context?: any
|
|
15
|
+
): { entity: number, mesh: ShadedGeometry } | undefined
|
|
6
16
|
}
|
|
@@ -9,6 +9,7 @@ import { returnTrue } from "../../../../core/function/Functions.js";
|
|
|
9
9
|
import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
10
10
|
import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
|
|
11
11
|
import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
|
|
12
|
+
import { assert } from "../../../../core/assert.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
*
|
|
@@ -66,6 +67,58 @@ export class ShadedGeometrySystem extends System {
|
|
|
66
67
|
|
|
67
68
|
this.__bvh = new BinaryNode();
|
|
68
69
|
this.__bvh.setNegativelyInfiniteBounds();
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* @type {Map<number, function():AbstractRenderAdapter>}
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
this.__adapter_suppliers = new Map();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {number} index
|
|
82
|
+
* @param {function():AbstractRenderAdapter} supplier
|
|
83
|
+
*/
|
|
84
|
+
register_render_adapter(index, supplier) {
|
|
85
|
+
assert.isNonNegativeInteger(index, 'index');
|
|
86
|
+
|
|
87
|
+
if (this.__adapter_suppliers.has(index)) {
|
|
88
|
+
// slot is already taken
|
|
89
|
+
console.warn(`Render adapter slot '${index}' is already taken, removing old adapter`);
|
|
90
|
+
this.unregister_render_adapter(index);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.__adapter_suppliers.set(index, supplier);
|
|
94
|
+
|
|
95
|
+
this.__view_contexts.forEach((value, key) => {
|
|
96
|
+
value.setAdapter(index, supplier());
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @param {number} index
|
|
103
|
+
* @return {boolean}
|
|
104
|
+
*/
|
|
105
|
+
unregister_render_adapter(index) {
|
|
106
|
+
assert.isNonNegativeInteger(index, 'index');
|
|
107
|
+
|
|
108
|
+
const supplier = this.__adapter_suppliers.get(index);
|
|
109
|
+
|
|
110
|
+
if (supplier === undefined) {
|
|
111
|
+
// not found
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.__adapter_suppliers.delete(index);
|
|
116
|
+
|
|
117
|
+
this.__view_contexts.forEach((value, key) => {
|
|
118
|
+
value.removeAdapter(index);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return true;
|
|
69
122
|
}
|
|
70
123
|
|
|
71
124
|
/**
|
|
@@ -74,7 +127,14 @@ export class ShadedGeometrySystem extends System {
|
|
|
74
127
|
* @private
|
|
75
128
|
*/
|
|
76
129
|
__handle_view_added(view) {
|
|
77
|
-
|
|
130
|
+
const ctx = new ShadedGeometryRendererContext();
|
|
131
|
+
|
|
132
|
+
// attach adapters
|
|
133
|
+
this.__adapter_suppliers.forEach((value, key) => {
|
|
134
|
+
ctx.setAdapter(key, value());
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
this.__view_contexts.set(view, ctx);
|
|
78
138
|
}
|
|
79
139
|
|
|
80
140
|
/**
|
|
@@ -133,11 +193,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
133
193
|
* @param {number} entity
|
|
134
194
|
*/
|
|
135
195
|
link(sg, t, entity) {
|
|
136
|
-
|
|
137
|
-
t.rotation.onChanged.add(sg.setRotationByComponents, sg);
|
|
138
|
-
t.scale.onChanged.add(sg.setScaleByComponents, sg);
|
|
196
|
+
sg.__c_transform = t;
|
|
139
197
|
|
|
140
|
-
sg.
|
|
198
|
+
t.position.onChanged.add(sg.updateTransform, sg);
|
|
199
|
+
t.rotation.onChanged.add(sg.updateTransform, sg);
|
|
200
|
+
t.scale.onChanged.add(sg.updateTransform, sg);
|
|
201
|
+
|
|
202
|
+
sg.updateTransform();
|
|
141
203
|
|
|
142
204
|
const leaf_node = sg.bvh;
|
|
143
205
|
|
|
@@ -157,9 +219,9 @@ export class ShadedGeometrySystem extends System {
|
|
|
157
219
|
* @param {number} entity
|
|
158
220
|
*/
|
|
159
221
|
unlink(sg, t, entity) {
|
|
160
|
-
t.position.onChanged.remove(sg.
|
|
161
|
-
t.rotation.onChanged.remove(sg.
|
|
162
|
-
t.scale.onChanged.remove(sg.
|
|
222
|
+
t.position.onChanged.remove(sg.updateTransform, sg);
|
|
223
|
+
t.rotation.onChanged.remove(sg.updateTransform, sg);
|
|
224
|
+
t.scale.onChanged.remove(sg.updateTransform, sg);
|
|
163
225
|
|
|
164
226
|
sg.bvh.disconnect();
|
|
165
227
|
}
|
|
@@ -173,7 +235,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
173
235
|
* @param {number} direction_x
|
|
174
236
|
* @param {number} direction_y
|
|
175
237
|
* @param {number} direction_z
|
|
176
|
-
* @param {function(entity:number, mesh:ShadedGeometry)} [filter_function]
|
|
238
|
+
* @param {function(entity:number, mesh:ShadedGeometry):boolean} [filter_function]
|
|
177
239
|
* @param {*} [filter_function_context]
|
|
178
240
|
* @returns {{entity:number, mesh:ShadedGeometry}|undefined}
|
|
179
241
|
*/
|
|
@@ -183,7 +245,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
183
245
|
direction_x, direction_y, direction_z,
|
|
184
246
|
filter_function = returnTrue, filter_function_context
|
|
185
247
|
) {
|
|
186
|
-
const root_bvh = this.
|
|
248
|
+
const root_bvh = this.__bvh;
|
|
187
249
|
const stack_frame_address = traversal_cursor;
|
|
188
250
|
|
|
189
251
|
traversal_stack[traversal_cursor++] = root_bvh;
|
|
@@ -242,9 +304,11 @@ export class ShadedGeometrySystem extends System {
|
|
|
242
304
|
mat4.invert(scratch_m4, m4);
|
|
243
305
|
|
|
244
306
|
// transform ray to local space
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
const
|
|
307
|
+
const inv_w = 1 / (scratch_m4[3] * origin_x + scratch_m4[7] * origin_y + scratch_m4[11] * origin_z + scratch_m4[15]);
|
|
308
|
+
|
|
309
|
+
const local_origin_x = (scratch_m4[0] * origin_x + scratch_m4[4] * origin_y + scratch_m4[8] * origin_z + scratch_m4[12]) * inv_w;
|
|
310
|
+
const local_origin_y = (scratch_m4[1] * origin_x + scratch_m4[5] * origin_y + scratch_m4[9] * origin_z + scratch_m4[13]) * inv_w;
|
|
311
|
+
const local_origin_z = (scratch_m4[2] * origin_x + scratch_m4[6] * origin_y + scratch_m4[10] * origin_z + scratch_m4[14]) * inv_w;
|
|
248
312
|
|
|
249
313
|
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
250
314
|
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DrawMode } from "./DrawMode.js";
|
|
2
|
+
import { Line, LineSegments, Mesh } from "three";
|
|
3
|
+
import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {ShadedGeometry} sg
|
|
8
|
+
* @returns {THREE.Object3D}
|
|
9
|
+
*/
|
|
10
|
+
export function build_three_object(sg) {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @type {THREE.Object3D}
|
|
14
|
+
*/
|
|
15
|
+
let object;
|
|
16
|
+
|
|
17
|
+
const mode = sg.mode;
|
|
18
|
+
const shader = sg.material;
|
|
19
|
+
const geo = sg.geometry;
|
|
20
|
+
|
|
21
|
+
if (mode === DrawMode.Triangles) {
|
|
22
|
+
object = new Mesh(geo, shader);
|
|
23
|
+
} else if (mode === DrawMode.Lines) {
|
|
24
|
+
object = new Line(geo, shader);
|
|
25
|
+
} else if (mode === DrawMode.LineSegments) {
|
|
26
|
+
object = new LineSegments(geo, shader);
|
|
27
|
+
} else {
|
|
28
|
+
throw new Error(`Unsupported draw mode '${mode}'`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
object.matrixAutoUpdate = false;
|
|
32
|
+
object.frustumCulled = false;
|
|
33
|
+
object.matrixWorldNeedsUpdate = false;
|
|
34
|
+
|
|
35
|
+
object.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
|
|
36
|
+
object.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
37
|
+
|
|
38
|
+
return object;
|
|
39
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
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";
|
|
2
|
+
import { AbstractRenderAdapter } from "./adapters/AbstractRenderAdapter.js";
|
|
3
|
+
import { InstancedRendererAdapter } from "./adapters/InstancedRendererAdapter.js";
|
|
4
|
+
import { GenericRendererAdapter } from "./adapters/GenericRendererAdapter.js";
|
|
5
|
+
import { assert } from "../../../../../core/assert.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* 1 - collect visible meshes
|
|
@@ -19,7 +20,16 @@ export class ShadedGeometryRendererContext {
|
|
|
19
20
|
];
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {number} index
|
|
26
|
+
* @param {AbstractRenderAdapter} adapter
|
|
27
|
+
*/
|
|
22
28
|
setAdapter(index, adapter) {
|
|
29
|
+
assert.isNonNegativeInteger(index, 'index');
|
|
30
|
+
assert.defined(adapter, 'adapter');
|
|
31
|
+
assert.equal(adapter.isShadedGeometryRenderAdapter, true, 'adapter.isShadedGeometryRenderAdapter !== true');
|
|
32
|
+
|
|
23
33
|
const existing = this.adapters[index];
|
|
24
34
|
if (existing !== undefined) {
|
|
25
35
|
// dispose of existing adapter
|
|
@@ -29,14 +39,36 @@ export class ShadedGeometryRendererContext {
|
|
|
29
39
|
this.adapters[index] = adapter;
|
|
30
40
|
}
|
|
31
41
|
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param {number} index
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
removeAdapter(index) {
|
|
48
|
+
assert.isNonNegativeInteger(index, 'index');
|
|
49
|
+
|
|
50
|
+
const adapter = this.adapters[index];
|
|
51
|
+
|
|
52
|
+
if (adapter === undefined) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
delete this.adapters[index];
|
|
57
|
+
|
|
58
|
+
adapter.dispose();
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
32
63
|
/**
|
|
33
64
|
*
|
|
34
65
|
* @param {THREE.Object3D[]} destination
|
|
35
66
|
* @param {number} destination_offset
|
|
67
|
+
* @param {THREE.WebGLRenderer} renderer
|
|
36
68
|
* @param {CameraView} view
|
|
37
69
|
* @param {BinaryNode<ShadedGeometry>} bvh
|
|
38
70
|
*/
|
|
39
|
-
collect(destination, destination_offset, view, bvh) {
|
|
71
|
+
collect(destination, destination_offset, renderer, view, bvh) {
|
|
40
72
|
const adapters = this.adapters;
|
|
41
73
|
const adapter_count = adapters.length;
|
|
42
74
|
|
|
@@ -44,7 +76,7 @@ export class ShadedGeometryRendererContext {
|
|
|
44
76
|
for (; i < adapter_count; i++) {
|
|
45
77
|
const adapter = adapters[i];
|
|
46
78
|
|
|
47
|
-
adapter.build_start();
|
|
79
|
+
adapter.build_start(renderer);
|
|
48
80
|
}
|
|
49
81
|
|
|
50
82
|
|
|
@@ -35,7 +35,13 @@ export class AbstractRenderAdapter {
|
|
|
35
35
|
throw new Error('Not Implemented');
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param {THREE.WebGLRenderer} renderer
|
|
42
|
+
* @param {CameraView} view
|
|
43
|
+
*/
|
|
44
|
+
build_start(renderer, view) {
|
|
39
45
|
|
|
40
46
|
}
|
|
41
47
|
|
|
@@ -65,3 +71,9 @@ export class AbstractRenderAdapter {
|
|
|
65
71
|
|
|
66
72
|
}
|
|
67
73
|
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @readonly
|
|
77
|
+
* @type {boolean}
|
|
78
|
+
*/
|
|
79
|
+
AbstractRenderAdapter.prototype.isShadedGeometryRenderAdapter = true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { array_copy } from "../../../../../../core/collection/array/copyArray.js";
|
|
3
|
+
import { build_three_object } from "../../build_three_object.js";
|
|
4
4
|
|
|
5
5
|
export class GenericRendererAdapter extends AbstractRenderAdapter {
|
|
6
6
|
constructor() {
|
|
@@ -19,7 +19,12 @@ export class GenericRendererAdapter extends AbstractRenderAdapter {
|
|
|
19
19
|
return 0;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param {THREE.WebGLRenderer} renderer
|
|
25
|
+
* @param {CameraView} view
|
|
26
|
+
*/
|
|
27
|
+
build_start(renderer, view) {
|
|
23
28
|
this.clear();
|
|
24
29
|
}
|
|
25
30
|
|
|
@@ -1,12 +1,43 @@
|
|
|
1
1
|
import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
|
|
2
|
-
import { HashMap } from "
|
|
3
|
-
import { InstancedMeshGroup } from "
|
|
4
|
-
import { ShadedGeometryFlags } from "
|
|
2
|
+
import { HashMap } from "../../../../../../core/collection/HashMap.js";
|
|
3
|
+
import { InstancedMeshGroup } from "../../../../geometry/instancing/InstancedMeshGroup.js";
|
|
4
|
+
import { ShadedGeometryFlags } from "../../ShadedGeometryFlags.js";
|
|
5
|
+
import { DrawMode } from "../../DrawMode.js";
|
|
5
6
|
|
|
6
7
|
const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
|
|
7
8
|
| ShadedGeometryFlags.ReceiveShadow
|
|
8
9
|
;
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {ShadedGeometry} a
|
|
14
|
+
* @param {ShadedGeometry} b
|
|
15
|
+
* @returns {number}
|
|
16
|
+
*/
|
|
17
|
+
function compare(a, b) {
|
|
18
|
+
const d_geometry = a.geometry.id - b.geometry.id;
|
|
19
|
+
if (d_geometry !== 0) {
|
|
20
|
+
return d_geometry;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const d_material = a.material.id - b.material.id;
|
|
24
|
+
if (d_material !== 0) {
|
|
25
|
+
return d_material;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const d_flags = (a.flags & INSTANCED_EQUALITY_FLAGS) - (b.flags & INSTANCED_EQUALITY_FLAGS);
|
|
29
|
+
if (d_flags !== 0) {
|
|
30
|
+
return d_flags;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const d_mode = a.mode - b.mode;
|
|
34
|
+
if (d_mode !== 0) {
|
|
35
|
+
return d_mode;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
10
41
|
export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
11
42
|
constructor() {
|
|
12
43
|
super();
|
|
@@ -18,11 +49,12 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
18
49
|
*/
|
|
19
50
|
this.__instanced_meshes = new HashMap({
|
|
20
51
|
keyHashFunction(sg) {
|
|
21
|
-
return sg.geometry.id ^ sg.material.id;
|
|
52
|
+
return sg.geometry.id ^ sg.material.id ^ sg.mode;
|
|
22
53
|
},
|
|
23
54
|
keyEqualityFunction(a, b) {
|
|
24
55
|
return a.material.id === b.material.id
|
|
25
56
|
&& a.geometry.id === b.geometry.id
|
|
57
|
+
&& a.mode === b.mode
|
|
26
58
|
&& (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
|
|
27
59
|
;
|
|
28
60
|
}
|
|
@@ -45,7 +77,17 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
45
77
|
__get_instanced_mesh(sg) {
|
|
46
78
|
let im = this.__instanced_meshes.get(sg);
|
|
47
79
|
|
|
48
|
-
|
|
80
|
+
|
|
81
|
+
if (im !== undefined) {
|
|
82
|
+
|
|
83
|
+
return im;
|
|
84
|
+
|
|
85
|
+
} else {
|
|
86
|
+
|
|
87
|
+
if (sg.mode !== DrawMode.Triangles) {
|
|
88
|
+
throw new Error(`Unsupported draw mode ${sg.mode}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
49
91
|
im = new InstancedMeshGroup();
|
|
50
92
|
im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
|
|
51
93
|
|
|
@@ -56,9 +98,10 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
56
98
|
im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
|
|
57
99
|
|
|
58
100
|
this.__instanced_meshes.set(sg, im);
|
|
59
|
-
}
|
|
60
101
|
|
|
61
|
-
|
|
102
|
+
return im;
|
|
103
|
+
|
|
104
|
+
}
|
|
62
105
|
}
|
|
63
106
|
|
|
64
107
|
add(sg) {
|
|
@@ -66,7 +109,11 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
66
109
|
|
|
67
110
|
const index = mesh.count;
|
|
68
111
|
|
|
69
|
-
|
|
112
|
+
const new_size = index + 1;
|
|
113
|
+
|
|
114
|
+
if (new_size > mesh.capacity) {
|
|
115
|
+
mesh.ensureCapacity(new_size);
|
|
116
|
+
}
|
|
70
117
|
|
|
71
118
|
mesh.setTransformAt(index, sg.transform);
|
|
72
119
|
|
|
@@ -75,18 +122,24 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
|
|
|
75
122
|
this.__active_meshes.add(mesh);
|
|
76
123
|
}
|
|
77
124
|
|
|
78
|
-
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* @param {THREE.WebGLRenderer} renderer
|
|
128
|
+
* @param {CameraView} view
|
|
129
|
+
*/
|
|
130
|
+
build_start(renderer, view) {
|
|
79
131
|
this.clear();
|
|
80
132
|
}
|
|
81
133
|
|
|
82
134
|
build_end() {
|
|
135
|
+
const objects = this.__objects;
|
|
83
136
|
|
|
84
137
|
for (const activeMesh of this.__active_meshes) {
|
|
85
138
|
// force underlying geometry to update
|
|
86
139
|
activeMesh.setCount(activeMesh.getCount());
|
|
87
140
|
activeMesh.requestAttributeUpdate();
|
|
88
141
|
|
|
89
|
-
|
|
142
|
+
objects[this.__object_count++] = activeMesh.mesh;
|
|
90
143
|
}
|
|
91
144
|
|
|
92
145
|
}
|
|
@@ -16,6 +16,7 @@ import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
|
|
|
16
16
|
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
17
17
|
import Quaternion from "../../../../../core/geom/Quaternion.js";
|
|
18
18
|
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
19
|
+
import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
|
|
19
20
|
|
|
20
21
|
const eh = new EngineHarness();
|
|
21
22
|
|
|
@@ -51,23 +52,31 @@ async function main(engine) {
|
|
|
51
52
|
|
|
52
53
|
window.material = material;
|
|
53
54
|
|
|
54
|
-
const geometry = new BoxBufferGeometry();
|
|
55
|
-
|
|
56
55
|
const random = seededRandom(0);
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
const INSTANCE_COUNT = 20000;
|
|
58
|
+
|
|
59
|
+
const geometries = [];
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < 1000; i++) {
|
|
62
|
+
geometries.push(new BoxBufferGeometry());
|
|
63
|
+
}
|
|
59
64
|
|
|
65
|
+
for (let i = 0; i < INSTANCE_COUNT; i++) {
|
|
66
|
+
const geometry = randomFromArray(random, geometries);
|
|
60
67
|
const sg = ShadedGeometry.from(geometry, material);
|
|
61
68
|
|
|
69
|
+
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
62
70
|
sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
71
|
+
// sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
|
|
63
72
|
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
64
73
|
|
|
65
74
|
new EntityBuilder()
|
|
66
75
|
.add(Transform.fromJSON({
|
|
67
76
|
position: {
|
|
68
|
-
x: randomFloatBetween(random,
|
|
77
|
+
x: randomFloatBetween(random, 0, 20),
|
|
69
78
|
y: randomFloatBetween(random, 0, 10),
|
|
70
|
-
z: randomFloatBetween(random,
|
|
79
|
+
z: randomFloatBetween(random, 0, 20)
|
|
71
80
|
},
|
|
72
81
|
rotation: Quaternion.random(random),
|
|
73
82
|
scale: 0.05
|
|
@@ -11,6 +11,7 @@ import { StaticMaterialCache } from "../../../asset/loaders/material/StaticMater
|
|
|
11
11
|
import { composeCompile } from "../../material/composeCompile.js";
|
|
12
12
|
import { typed_array_copy } from "../../../../core/collection/array/typed/typed_array_copy.js";
|
|
13
13
|
import { rewriteMaterial } from "./rewriteMaterial.js";
|
|
14
|
+
import { max3 } from "../../../../core/math/max3.js";
|
|
14
15
|
|
|
15
16
|
export class InstancedMeshGroup {
|
|
16
17
|
/**
|
|
@@ -69,6 +70,13 @@ export class InstancedMeshGroup {
|
|
|
69
70
|
*/
|
|
70
71
|
this.__attributeTransform = null;
|
|
71
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Shortcut to buffer attribute data
|
|
75
|
+
* @type {Float32Array}
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
this.__attributeTransformArray = null;
|
|
79
|
+
|
|
72
80
|
/**
|
|
73
81
|
*
|
|
74
82
|
* @type {Material}
|
|
@@ -167,7 +175,7 @@ export class InstancedMeshGroup {
|
|
|
167
175
|
if (currentCapacity < size) {
|
|
168
176
|
// grow
|
|
169
177
|
|
|
170
|
-
const newCapacityRaw =
|
|
178
|
+
const newCapacityRaw = max3(
|
|
171
179
|
size,
|
|
172
180
|
currentCapacity * this.growFactor,
|
|
173
181
|
currentCapacity + this.growConstant
|
|
@@ -193,7 +201,7 @@ export class InstancedMeshGroup {
|
|
|
193
201
|
* @param {number[]|ArrayLike<number>|Float32Array} transform 4x4 transform matrix of the instance
|
|
194
202
|
*/
|
|
195
203
|
setTransformAt(index, transform) {
|
|
196
|
-
this.
|
|
204
|
+
this.__attributeTransformArray.set(transform, index * 16);
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
requestAttributeUpdate() {
|
|
@@ -357,6 +365,7 @@ export class InstancedMeshGroup {
|
|
|
357
365
|
}
|
|
358
366
|
|
|
359
367
|
//rewrite old attributes
|
|
368
|
+
this.__attributeTransformArray = newTransformArray;
|
|
360
369
|
this.__attributeTransform = new InstancedBufferAttribute(newTransformArray, 16);
|
|
361
370
|
this.__attributeTransform.setUsage(StreamDrawUsage);
|
|
362
371
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { AbstractRenderAdapter } from "../../../ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js";
|
|
2
|
+
import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
3
|
+
import { MaterialVertexSpec } from "../../render/v1/MaterialVertexSpec.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @type {MaterialVertexSpec}
|
|
8
|
+
*/
|
|
9
|
+
const scratch_mvc = new MaterialVertexSpec();
|
|
10
|
+
|
|
11
|
+
class MicronRenderContext {
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
16
|
+
constructor({
|
|
17
|
+
vgtr
|
|
18
|
+
}) {
|
|
19
|
+
super();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @type {VGThreeRenderer}
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
this.__vgtr = vgtr;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @type {VirtualGeometry|null}
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
this.__vg = null;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {VirtualGeometryBuilder|null}
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
this.__vgb = null;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @type {Map<number, MicronGeometry>}
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
this.__geometry_map = new Map();
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @type {Set<MaterialContext>}
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
this.__active_contexts = new Set();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
add(sg) {
|
|
57
|
+
|
|
58
|
+
const micron_geometry = this.__geometry_map.get(sg.geometry.id);
|
|
59
|
+
|
|
60
|
+
// populate virtual geometry for this instance
|
|
61
|
+
this.__vgb.buildForMesh(sg.entity, micron_geometry, sg.transform);
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {THREE.WebGLRenderer} renderer
|
|
68
|
+
* @param {CameraView} view
|
|
69
|
+
*/
|
|
70
|
+
build_start(renderer, view) {
|
|
71
|
+
const resolution = new Vector2();
|
|
72
|
+
let pixelRatio = 1;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
* @type {THREE.RenderTarget}
|
|
77
|
+
*/
|
|
78
|
+
const render_target = renderer.getRenderTarget();
|
|
79
|
+
|
|
80
|
+
if (render_target !== null) {
|
|
81
|
+
resolution.set(render_target.width, render_target.height);
|
|
82
|
+
} else {
|
|
83
|
+
renderer.getSize(resolution);
|
|
84
|
+
pixelRatio = renderer.getPixelRatio();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const vg_builder = this.__vgb;
|
|
88
|
+
|
|
89
|
+
vg_builder.resolution.set(resolution.x * pixelRatio, resolution.y * pixelRatio);
|
|
90
|
+
vg_builder.setMatricesFromCamera(view.camera);
|
|
91
|
+
vg_builder.setOutput(this.__vg);
|
|
92
|
+
|
|
93
|
+
vg_builder.build();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
build_end() {
|
|
97
|
+
const contexts = this.__contexts_array;
|
|
98
|
+
const context_count = contexts.length;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @type {Map<number, MaterialContext>}
|
|
103
|
+
*/
|
|
104
|
+
const instance_to_ctx = new Map();
|
|
105
|
+
|
|
106
|
+
for (let i = 0; i < context_count; i++) {
|
|
107
|
+
const ctx = contexts[i];
|
|
108
|
+
ctx.__patch_count = 0;
|
|
109
|
+
|
|
110
|
+
for (const instance of ctx.instances) {
|
|
111
|
+
instance_to_ctx.set(instance, ctx);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// sort patches into relevant contexts
|
|
116
|
+
const geometry = this.geometry;
|
|
117
|
+
const patch_count = geometry.patch_count;
|
|
118
|
+
const patches = geometry.patches;
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < patch_count; i++) {
|
|
121
|
+
const i3 = i * 3;
|
|
122
|
+
|
|
123
|
+
const instance_id = patches[i3];
|
|
124
|
+
const geometry_id = patches[i3 + 1];
|
|
125
|
+
const patch_id = patches[i3 + 2];
|
|
126
|
+
|
|
127
|
+
const ctx = instance_to_ctx.get(instance_id);
|
|
128
|
+
|
|
129
|
+
const target_address = ctx.__patch_count * 3;
|
|
130
|
+
ctx.__patch_count++;
|
|
131
|
+
|
|
132
|
+
const ctx_patches = ctx.__patches;
|
|
133
|
+
|
|
134
|
+
ctx_patches[target_address] = instance_id;
|
|
135
|
+
ctx_patches[target_address + 1] = geometry_id;
|
|
136
|
+
ctx_patches[target_address + 2] = patch_id;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// build each context
|
|
140
|
+
for (let i = 0; i < context_count; i++) {
|
|
141
|
+
const ctx = contexts[i];
|
|
142
|
+
|
|
143
|
+
ctx.build(this.geometry);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
dispose() {
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -141,13 +141,11 @@ export class VirtualGeometryBuilder {
|
|
|
141
141
|
* @param {number} instance_id
|
|
142
142
|
* @param {MicronGeometry} geometry
|
|
143
143
|
* @param {number[]} transform world transform matrix of the instance
|
|
144
|
-
* @param {ActivePatchList} apl
|
|
145
144
|
*/
|
|
146
145
|
buildForMesh(
|
|
147
146
|
instance_id,
|
|
148
147
|
geometry,
|
|
149
|
-
transform
|
|
150
|
-
apl
|
|
148
|
+
transform
|
|
151
149
|
) {
|
|
152
150
|
refinement_spec.build(transform, this.view_projection_matrix);
|
|
153
151
|
|
|
@@ -42,13 +42,6 @@ export class ThreeInstancedAdapter {
|
|
|
42
42
|
|
|
43
43
|
this.__uniforms = Object.assign({}, this.__patch_data.genUniforms());
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* @type {WebGL2RenderingContext|null}
|
|
48
|
-
* @private
|
|
49
|
-
*/
|
|
50
|
-
this.__gl_context = null;
|
|
51
|
-
|
|
52
45
|
/**
|
|
53
46
|
*
|
|
54
47
|
* @type {Signal}
|
|
@@ -19,13 +19,6 @@ export class VGThreeRenderer {
|
|
|
19
19
|
|
|
20
20
|
this.builder = new VirtualGeometryBuilder();
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @type {WebGL2RenderingContext|null}
|
|
25
|
-
* @private
|
|
26
|
-
*/
|
|
27
|
-
this.__gl_context = null;
|
|
28
|
-
|
|
29
22
|
/**
|
|
30
23
|
*
|
|
31
24
|
* @type {Map<MaterialVertexSpec, MaterialContext>}
|
|
@@ -89,7 +82,7 @@ export class VGThreeRenderer {
|
|
|
89
82
|
|
|
90
83
|
const ctx = new MaterialContext(spec, m);
|
|
91
84
|
|
|
92
|
-
ctx.init(
|
|
85
|
+
ctx.init();
|
|
93
86
|
|
|
94
87
|
this.material_contexts.set(key, ctx);
|
|
95
88
|
this.__contexts_array.push(ctx);
|
|
@@ -189,12 +182,13 @@ export class VGThreeRenderer {
|
|
|
189
182
|
const ctx = instance_to_ctx.get(instance_id);
|
|
190
183
|
|
|
191
184
|
const target_address = ctx.__patch_count * 3;
|
|
185
|
+
ctx.__patch_count++;
|
|
192
186
|
|
|
193
|
-
ctx.__patches
|
|
194
|
-
ctx.__patches[target_address + 1] = geometry_id;
|
|
195
|
-
ctx.__patches[target_address + 2] = patch_id;
|
|
187
|
+
const ctx_patches = ctx.__patches;
|
|
196
188
|
|
|
197
|
-
|
|
189
|
+
ctx_patches[target_address] = instance_id;
|
|
190
|
+
ctx_patches[target_address + 1] = geometry_id;
|
|
191
|
+
ctx_patches[target_address + 2] = patch_id;
|
|
198
192
|
}
|
|
199
193
|
|
|
200
194
|
// build each context
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ParticleEmitterFlag } from "../../emitter/ParticleEmitterFlag.js";
|
|
2
2
|
import { PARTICLE_ATTRIBUTE_DEATH_AGE, PARTICLE_ATTRIBUTE_POSITION } from "../../emitter/PARTICLE_ATTRIBUTES.js";
|
|
3
|
-
import { EmissionShapeType } from "../../emitter/EmissionShapeType.js";
|
|
4
3
|
import { Matrix4 } from "three";
|
|
5
4
|
import { composeMatrix4 } from "../../../../../util/composeMatrix4.js";
|
|
6
5
|
import Quaternion from "../../../../../../../core/geom/Quaternion.js";
|
|
@@ -14,55 +13,6 @@ import { SerializationMetadata } from "../../../../../../ecs/components/Serializ
|
|
|
14
13
|
import { UnitCubeShape3D } from "../../../../../../../core/geom/3d/shape/UnitCubeShape3D.js";
|
|
15
14
|
import { shape_from_json } from "../../../../../../../core/geom/3d/shape/json/shape_from_json.js";
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
* @param {ParticleLayer} layer
|
|
20
|
-
* @returns {number}
|
|
21
|
-
*/
|
|
22
|
-
function computeLayerVolume(layer) {
|
|
23
|
-
let base_volume = 0;
|
|
24
|
-
|
|
25
|
-
switch (layer.emissionShape) {
|
|
26
|
-
case EmissionShapeType.Box:
|
|
27
|
-
base_volume = 1;
|
|
28
|
-
break;
|
|
29
|
-
case EmissionShapeType.Sphere:
|
|
30
|
-
base_volume = 0.5236;
|
|
31
|
-
break;
|
|
32
|
-
case EmissionShapeType.Point:
|
|
33
|
-
base_volume = 0;
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const scale_volume = layer.scale.x * layer.scale.y * layer.scale.z;
|
|
38
|
-
|
|
39
|
-
return base_volume * scale_volume;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @param {ParticleEmitter} emitter
|
|
45
|
-
* @param {Transform} transform
|
|
46
|
-
* @returns {number}
|
|
47
|
-
*/
|
|
48
|
-
function computeEmitterVolume(emitter, transform) {
|
|
49
|
-
|
|
50
|
-
const layers = emitter.layers;
|
|
51
|
-
const n = layers.length;
|
|
52
|
-
|
|
53
|
-
let layer_volume_sum = 0;
|
|
54
|
-
|
|
55
|
-
for (let i = 0; i < n; i++) {
|
|
56
|
-
const particleLayer = layers.get(i);
|
|
57
|
-
|
|
58
|
-
layer_volume_sum += computeLayerVolume(particleLayer);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const scale_volume = transform.scale.x * transform.scale.y * transform.scale.z;
|
|
62
|
-
|
|
63
|
-
return layer_volume_sum * scale_volume;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
16
|
const DEFAULT_ATTRIBUTE_VALUES = {
|
|
67
17
|
color: [1, 1, 1, 1],
|
|
68
18
|
age: [0],
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.35.
|
|
8
|
+
"version": "2.35.4",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|