@woosh/meep-engine 2.35.9 → 2.35.13
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/BinaryBuffer.js +65 -18
- package/engine/graphics/ecs/camera/Camera.d.ts +3 -0
- package/engine/graphics/ecs/camera/Camera.js +39 -1
- package/engine/graphics/ecs/camera/CameraSystem.js +25 -6
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +38 -3
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +19 -4
- package/engine/graphics/ecs/path/PathDisplaySystem.js +1 -1
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +19 -12
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +3 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +71 -2
- package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +160 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +61 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +56 -0
- package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +165 -0
- package/engine/graphics/ecs/path/tube/build/estimatePathLength.js +17 -0
- package/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.js +37 -0
- package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +161 -0
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -1
- package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +45 -76
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +19 -24
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -1
- package/engine/graphics/micron/render/v1/MaterialContext.js +1 -11
- package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +55 -2
- package/engine/graphics/micron/render/v1/MicronRenderContext.js +151 -0
- package/engine/graphics/micron/render/v1/VGThreeRenderer.js +24 -117
- package/engine/navigation/ecs/components/Path.js +5 -6
- package/package.json +1 -1
- package/engine/graphics/ecs/path/tube/TubePathBuilder.js +0 -522
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { AbstractRenderAdapter } from "../../../ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js";
|
|
2
2
|
import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
3
|
-
import {
|
|
3
|
+
import { buildMicronGeometryFromBufferGeometry } from "../../build/buildMicronGeometryFromBufferGeometry.js";
|
|
4
|
+
import { ShadedGeometryFlags } from "../../../ecs/mesh-v2/ShadedGeometryFlags.js";
|
|
5
|
+
import { MaterialVertexSpec, MaterialVertexSpecFlags } from "../../render/v1/MaterialVertexSpec.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
*
|
|
@@ -8,35 +10,16 @@ import { MaterialVertexSpec } from "../../render/v1/MaterialVertexSpec.js";
|
|
|
8
10
|
*/
|
|
9
11
|
const scratch_mvc = new MaterialVertexSpec();
|
|
10
12
|
|
|
11
|
-
class MicronRenderContext {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
13
|
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
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* @type {VirtualGeometry|null}
|
|
30
|
-
* @private
|
|
31
|
-
*/
|
|
32
|
-
this.__vg = null;
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
33
17
|
|
|
34
18
|
/**
|
|
35
19
|
*
|
|
36
|
-
* @type {
|
|
37
|
-
* @private
|
|
20
|
+
* @type {MicronRenderContext|null}
|
|
38
21
|
*/
|
|
39
|
-
this.
|
|
22
|
+
this.ctx = null;
|
|
40
23
|
|
|
41
24
|
/**
|
|
42
25
|
*
|
|
@@ -47,18 +30,41 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
|
47
30
|
|
|
48
31
|
/**
|
|
49
32
|
*
|
|
50
|
-
* @type {
|
|
33
|
+
* @type {Map<number, Promise>}
|
|
51
34
|
* @private
|
|
52
35
|
*/
|
|
53
|
-
this.
|
|
36
|
+
this.__geometry_building_promises = new Map();
|
|
54
37
|
}
|
|
55
38
|
|
|
56
39
|
add(sg) {
|
|
57
40
|
|
|
58
|
-
const
|
|
41
|
+
const geometry_id = sg.geometry.id;
|
|
42
|
+
|
|
43
|
+
const micron_geometry = this.__geometry_map.get(geometry_id);
|
|
44
|
+
|
|
45
|
+
if (micron_geometry === undefined) {
|
|
46
|
+
// no micron geometry
|
|
47
|
+
if (!this.__geometry_building_promises.has(geometry_id)) {
|
|
48
|
+
const p = buildMicronGeometryFromBufferGeometry(sg.geometry);
|
|
49
|
+
|
|
50
|
+
this.__geometry_building_promises.set(geometry_id, p);
|
|
51
|
+
|
|
52
|
+
p.then(mg => this.__geometry_map.set(geometry_id, mg));
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
59
56
|
|
|
60
57
|
// populate virtual geometry for this instance
|
|
61
|
-
this.
|
|
58
|
+
this.ctx.builder.buildForMesh(sg.entity, micron_geometry, sg.transform);
|
|
59
|
+
|
|
60
|
+
scratch_mvc.material = sg.material;
|
|
61
|
+
scratch_mvc.spec = micron_geometry.vertex_spec;
|
|
62
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.CastShadow, sg.getFlag(ShadedGeometryFlags.CastShadow));
|
|
63
|
+
scratch_mvc.writeFlag(MaterialVertexSpecFlags.ReceiveShadow, sg.getFlag(ShadedGeometryFlags.ReceiveShadow));
|
|
64
|
+
|
|
65
|
+
const material_context = this.ctx.obtain_material(scratch_mvc);
|
|
66
|
+
|
|
67
|
+
material_context.instances.add(sg.entity);
|
|
62
68
|
|
|
63
69
|
}
|
|
64
70
|
|
|
@@ -84,67 +90,30 @@ export class MicronShadedGeometryRenderAdapter extends AbstractRenderAdapter {
|
|
|
84
90
|
pixelRatio = renderer.getPixelRatio();
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
const vg_builder = this.
|
|
93
|
+
const vg_builder = this.ctx.builder;
|
|
88
94
|
|
|
89
95
|
vg_builder.resolution.set(resolution.x * pixelRatio, resolution.y * pixelRatio);
|
|
90
96
|
vg_builder.setMatricesFromCamera(view.camera);
|
|
91
|
-
vg_builder.setOutput(this.
|
|
97
|
+
vg_builder.setOutput(this.ctx.geometry);
|
|
92
98
|
|
|
93
|
-
vg_builder.
|
|
99
|
+
vg_builder.initialize_build();
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
build_end() {
|
|
97
|
-
|
|
98
|
-
const context_count = contexts.length;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
*
|
|
102
|
-
* @type {Map<number, MaterialContext>}
|
|
103
|
-
*/
|
|
104
|
-
const instance_to_ctx = new Map();
|
|
103
|
+
this.ctx.render();
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
const material_contexts = this.ctx.contexts_array;
|
|
106
|
+
const contexts_count = material_contexts.length;
|
|
107
|
+
for (let i = 0; i < contexts_count; i++) {
|
|
108
|
+
const mc = material_contexts[i];
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
if (mc.instances.size > 0) {
|
|
111
|
+
this.__objects[this.__object_count++] = mc.mesh;
|
|
112
112
|
}
|
|
113
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
114
|
}
|
|
146
115
|
|
|
147
116
|
dispose() {
|
|
148
|
-
|
|
117
|
+
// rendering context is not owned, do nothing
|
|
149
118
|
}
|
|
150
119
|
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { array_copy } from "../../../../core/collection/array/copyArray.js";
|
|
2
2
|
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
3
3
|
import { RefinementSpec } from "./refinement/RefinementSpec.js";
|
|
4
|
-
import { ActivePatchList } from "./refinement/ActivePatchList.js";
|
|
5
4
|
import { mat4 } from "gl-matrix";
|
|
6
5
|
import { get_geometry_patch_cut } from "./refinement/get_geometry_patch_cut.js";
|
|
7
6
|
import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
|
|
8
7
|
|
|
9
|
-
/**
|
|
10
|
-
* @readonly
|
|
11
|
-
* @type {RefinementSpec}
|
|
12
|
-
*/
|
|
13
|
-
const refinement_spec = new RefinementSpec();
|
|
14
|
-
|
|
15
8
|
export class VirtualGeometryBuilder {
|
|
16
9
|
constructor() {
|
|
17
10
|
|
|
@@ -60,13 +53,6 @@ export class VirtualGeometryBuilder {
|
|
|
60
53
|
*/
|
|
61
54
|
this.resolution = new Vector2();
|
|
62
55
|
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* @type {ActivePatchList}
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
|
-
this.__acl = new ActivePatchList();
|
|
69
|
-
|
|
70
56
|
/**
|
|
71
57
|
* How much error to accept when deciding to subdivide a cluster
|
|
72
58
|
* Measured in pixels
|
|
@@ -74,10 +60,15 @@ export class VirtualGeometryBuilder {
|
|
|
74
60
|
* @type {number}
|
|
75
61
|
*/
|
|
76
62
|
this.error_bias = 2;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @type {RefinementSpec}
|
|
67
|
+
*/
|
|
68
|
+
this.refinement_spec = new RefinementSpec();
|
|
77
69
|
}
|
|
78
70
|
|
|
79
71
|
dropCache() {
|
|
80
|
-
this.__acl.clear();
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
/**
|
|
@@ -103,7 +94,7 @@ export class VirtualGeometryBuilder {
|
|
|
103
94
|
mat4.multiply(this.view_projection_matrix, this.matrix_projection, this.matrix_world_inverse);
|
|
104
95
|
|
|
105
96
|
//
|
|
106
|
-
refinement_spec.focal_length = camera.fov / 180;
|
|
97
|
+
this.refinement_spec.focal_length = camera.fov / 180;
|
|
107
98
|
}
|
|
108
99
|
|
|
109
100
|
/**
|
|
@@ -121,17 +112,15 @@ export class VirtualGeometryBuilder {
|
|
|
121
112
|
* @type {MicronGeometry|undefined}
|
|
122
113
|
*/
|
|
123
114
|
const micron_geometry = object.geometry;
|
|
124
|
-
if (micron_geometry !== undefined) {
|
|
125
|
-
// get acl
|
|
126
|
-
const acl = this.__acl;
|
|
127
115
|
|
|
116
|
+
if (micron_geometry !== undefined) {
|
|
128
117
|
|
|
129
118
|
this.buildForMesh(
|
|
130
119
|
object.instance_id,
|
|
131
120
|
micron_geometry,
|
|
132
|
-
object.matrixWorld.elements
|
|
133
|
-
acl
|
|
121
|
+
object.matrixWorld.elements
|
|
134
122
|
);
|
|
123
|
+
|
|
135
124
|
}
|
|
136
125
|
}
|
|
137
126
|
}
|
|
@@ -147,6 +136,8 @@ export class VirtualGeometryBuilder {
|
|
|
147
136
|
geometry,
|
|
148
137
|
transform
|
|
149
138
|
) {
|
|
139
|
+
const refinement_spec = this.refinement_spec;
|
|
140
|
+
|
|
150
141
|
refinement_spec.build(transform, this.view_projection_matrix);
|
|
151
142
|
|
|
152
143
|
const output = this.output;
|
|
@@ -183,17 +174,21 @@ export class VirtualGeometryBuilder {
|
|
|
183
174
|
this.input_scene_length += object_count;
|
|
184
175
|
}
|
|
185
176
|
|
|
186
|
-
|
|
177
|
+
initialize_build() {
|
|
187
178
|
|
|
188
179
|
// update refinement spec
|
|
189
|
-
refinement_spec.error_threshold = this.error_bias;
|
|
180
|
+
this.refinement_spec.error_threshold = this.error_bias;
|
|
190
181
|
|
|
191
182
|
const resolution = this.resolution;
|
|
192
183
|
|
|
193
|
-
refinement_spec.setResolution(resolution.x, resolution.y);
|
|
184
|
+
this.refinement_spec.setResolution(resolution.x, resolution.y);
|
|
194
185
|
|
|
195
186
|
// clear output
|
|
196
187
|
this.output.clear();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
build() {
|
|
191
|
+
this.initialize_build();
|
|
197
192
|
|
|
198
193
|
|
|
199
194
|
const n = this.input_scene_length;
|
|
@@ -52,7 +52,7 @@ export class MaterialContext {
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
*
|
|
55
|
-
* @type {
|
|
55
|
+
* @type {Uint32Array|number[]}
|
|
56
56
|
*/
|
|
57
57
|
this.__patches = [];
|
|
58
58
|
|
|
@@ -63,16 +63,6 @@ export class MaterialContext {
|
|
|
63
63
|
this.__patch_count = 0;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {MicronGeometryPatchOccurrence} occurrence
|
|
70
|
-
* @returns {boolean}
|
|
71
|
-
*/
|
|
72
|
-
filter(occurrence) {
|
|
73
|
-
return this.instances.has(occurrence.instance_id);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
66
|
init() {
|
|
77
67
|
|
|
78
68
|
const material = this.material.clone();
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export const MaterialVertexSpecFlags = {
|
|
2
|
+
CastShadow: 1,
|
|
3
|
+
ReceiveShadow: 2
|
|
4
|
+
};
|
|
5
|
+
|
|
1
6
|
export class MaterialVertexSpec {
|
|
2
7
|
constructor() {
|
|
3
8
|
/**
|
|
@@ -10,6 +15,52 @@ export class MaterialVertexSpec {
|
|
|
10
15
|
* @type {THREE.Material|null}
|
|
11
16
|
*/
|
|
12
17
|
this.material = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {number}
|
|
22
|
+
*/
|
|
23
|
+
this.flags = 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
29
|
+
* @returns {void}
|
|
30
|
+
*/
|
|
31
|
+
setFlag(flag) {
|
|
32
|
+
this.flags |= flag;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
clearFlag(flag) {
|
|
41
|
+
this.flags &= ~flag;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
47
|
+
* @param {boolean} value
|
|
48
|
+
*/
|
|
49
|
+
writeFlag(flag, value) {
|
|
50
|
+
if (value) {
|
|
51
|
+
this.setFlag(flag);
|
|
52
|
+
} else {
|
|
53
|
+
this.clearFlag(flag);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param {number|MaterialVertexSpecFlags} flag
|
|
60
|
+
* @returns {boolean}
|
|
61
|
+
*/
|
|
62
|
+
getFlag(flag) {
|
|
63
|
+
return (this.flags & flag) === flag;
|
|
13
64
|
}
|
|
14
65
|
|
|
15
66
|
/**
|
|
@@ -19,6 +70,7 @@ export class MaterialVertexSpec {
|
|
|
19
70
|
copy(other) {
|
|
20
71
|
this.spec = other.spec;
|
|
21
72
|
this.material = other.material;
|
|
73
|
+
this.flags = other.flags;
|
|
22
74
|
}
|
|
23
75
|
|
|
24
76
|
/**
|
|
@@ -47,7 +99,7 @@ export class MaterialVertexSpec {
|
|
|
47
99
|
}
|
|
48
100
|
|
|
49
101
|
hash() {
|
|
50
|
-
return this.spec.hash() ^ this.material.id;
|
|
102
|
+
return this.spec.hash() ^ this.material.id ^ this.flags;
|
|
51
103
|
}
|
|
52
104
|
|
|
53
105
|
equals(other) {
|
|
@@ -55,8 +107,9 @@ export class MaterialVertexSpec {
|
|
|
55
107
|
return true;
|
|
56
108
|
}
|
|
57
109
|
|
|
58
|
-
return this.
|
|
110
|
+
return this.flags === other.flags
|
|
59
111
|
&& this.material === other.material
|
|
112
|
+
&& this.spec.equals(other.spec)
|
|
60
113
|
;
|
|
61
114
|
}
|
|
62
115
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { VirtualGeometry } from "../../format/VirtualGeometry.js";
|
|
2
|
+
import { VirtualGeometryBuilder } from "../VirtualGeometryBuilder.js";
|
|
3
|
+
import { HashMap } from "../../../../../core/collection/HashMap.js";
|
|
4
|
+
import Signal from "../../../../../core/events/signal/Signal.js";
|
|
5
|
+
import { MaterialContext } from "./MaterialContext.js";
|
|
6
|
+
import { MaterialVertexSpec, MaterialVertexSpecFlags } from "./MaterialVertexSpec.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @type {MaterialVertexSpec}
|
|
11
|
+
*/
|
|
12
|
+
const scratch_mvc = new MaterialVertexSpec();
|
|
13
|
+
|
|
14
|
+
export class MicronRenderContext {
|
|
15
|
+
constructor() {
|
|
16
|
+
|
|
17
|
+
this.geometry = new VirtualGeometry();
|
|
18
|
+
|
|
19
|
+
this.builder = new VirtualGeometryBuilder();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @type {Map<MaterialVertexSpec, MaterialContext>}
|
|
24
|
+
*/
|
|
25
|
+
this.material_contexts = new HashMap();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @type {MaterialContext[]}
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
this.__contexts_array = [];
|
|
33
|
+
|
|
34
|
+
this.on = {
|
|
35
|
+
/**
|
|
36
|
+
* @type {Signal<MaterialContext>}
|
|
37
|
+
*/
|
|
38
|
+
contextAdded: new Signal()
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @returns {MaterialContext[]}
|
|
45
|
+
*/
|
|
46
|
+
get contexts_array() {
|
|
47
|
+
return this.__contexts_array;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Enable/disable wireframe rendering
|
|
52
|
+
* @param {boolean} x
|
|
53
|
+
*/
|
|
54
|
+
set wireframe(x) {
|
|
55
|
+
this.material_contexts.forEach((ctx, mv) => {
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
ctx.compiled_material.wireframe = x;
|
|
59
|
+
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param {MaterialVertexSpec} descriptor
|
|
67
|
+
* @returns {MaterialContext}
|
|
68
|
+
*/
|
|
69
|
+
obtain_material(descriptor) {
|
|
70
|
+
|
|
71
|
+
const existing = this.material_contexts.get(descriptor);
|
|
72
|
+
|
|
73
|
+
if (existing !== undefined) {
|
|
74
|
+
return existing;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// create a separate instance to be stored alongside the context
|
|
78
|
+
const key = descriptor.clone();
|
|
79
|
+
|
|
80
|
+
const ctx = new MaterialContext(descriptor.spec, descriptor.material);
|
|
81
|
+
|
|
82
|
+
ctx.init();
|
|
83
|
+
|
|
84
|
+
ctx.mesh.castShadow = descriptor.getFlag(MaterialVertexSpecFlags.CastShadow);
|
|
85
|
+
ctx.mesh.receiveShadow = descriptor.getFlag(MaterialVertexSpecFlags.ReceiveShadow);
|
|
86
|
+
|
|
87
|
+
this.material_contexts.set(key, ctx);
|
|
88
|
+
this.__contexts_array.push(ctx);
|
|
89
|
+
|
|
90
|
+
this.on.contextAdded.send1(ctx);
|
|
91
|
+
|
|
92
|
+
return ctx;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
render() {
|
|
96
|
+
const render_context = this;
|
|
97
|
+
const contexts = render_context.__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
|
+
let i = 0;
|
|
107
|
+
|
|
108
|
+
for (i = 0; i < context_count; i++) {
|
|
109
|
+
const ctx = contexts[i];
|
|
110
|
+
ctx.__patch_count = 0;
|
|
111
|
+
|
|
112
|
+
for (const instance of ctx.instances) {
|
|
113
|
+
instance_to_ctx.set(instance, ctx);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// sort patches into relevant contexts
|
|
118
|
+
const geometry = render_context.geometry;
|
|
119
|
+
const patch_count = geometry.patch_count;
|
|
120
|
+
const patches = geometry.patches;
|
|
121
|
+
|
|
122
|
+
for (i = 0; i < patch_count; i++) {
|
|
123
|
+
const i3 = i * 3;
|
|
124
|
+
|
|
125
|
+
const instance_id = patches[i3];
|
|
126
|
+
const geometry_id = patches[i3 + 1];
|
|
127
|
+
const patch_id = patches[i3 + 2];
|
|
128
|
+
|
|
129
|
+
const ctx = instance_to_ctx.get(instance_id);
|
|
130
|
+
|
|
131
|
+
const target_index = ctx.__patch_count;
|
|
132
|
+
const target_address = target_index * 3;
|
|
133
|
+
|
|
134
|
+
ctx.__patch_count++;
|
|
135
|
+
|
|
136
|
+
const ctx_patches = ctx.__patches;
|
|
137
|
+
|
|
138
|
+
ctx_patches[target_address] = instance_id;
|
|
139
|
+
ctx_patches[target_address + 1] = geometry_id;
|
|
140
|
+
ctx_patches[target_address + 2] = patch_id;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// build each context
|
|
144
|
+
for (i = 0; i < context_count; i++) {
|
|
145
|
+
const ctx = contexts[i];
|
|
146
|
+
|
|
147
|
+
ctx.build(geometry);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
}
|