@woosh/meep-engine 2.167.0 → 2.168.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.
@@ -1 +1 @@
1
- {"version":3,"file":"Trail3DSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail3d/Trail3DSystem.js"],"names":[],"mappings":";AAyBA;IAiCI;;;OAGG;IACH,4BAkBC;IAtDD,oDAAoC;IAEpC,+DAEE;IAEF;;OAEG;IACH,WAFU,0BAA0B,CAES;IAiB7C;;;OAGG;IACH,YAAgB;IAeZ;;OAEG;IACH,UAFU,cAAc,CAEO;IAE/B;;OAEG;IACH,aAFU,cAAY,IAAI,CAEH;IAG3B,2CAmBC;IAED,4CAIC;IA2DD;;;;OAIG;IACH,YAJW,OAAO,aACP,SAAS,YACT,MAAM,QAgBhB;IAED;;;;OAIG;IACH,kBAJW,OAAO,aACP,SAAS,UACT,MAAM,QAQhB;IAED;;;OAGG;IACH,yBAHW,OAAO,aACP,SAAS,QAkCnB;IAED,6BAWC;;CACJ;uBAlPsB,wBAAwB;0BACrB,qCAAqC;oBAW3C,cAAc;4CAbU,uDAAuD;2CAUxD,0DAA0D;+BANtE,yBAAyB"}
1
+ {"version":3,"file":"Trail3DSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/trail3d/Trail3DSystem.js"],"names":[],"mappings":";AAsDA;IAiCI;;;OAGG;IACH,4BAkBC;IAtDD,oDAAoC;IAEpC,+DAEE;IAEF;;OAEG;IACH,WAFU,0BAA0B,CAES;IAiB7C;;;OAGG;IACH,YAAgB;IAeZ;;OAEG;IACH,UAFU,cAAc,CAEO;IAE/B;;OAEG;IACH,aAFU,cAAY,IAAI,CAEH;IAG3B,2CAmBC;IAED,4CAIC;IA4DD;;;;OAIG;IACH,YAJW,OAAO,aACP,SAAS,YACT,MAAM,QAgBhB;IAED;;;;OAIG;IACH,kBAJW,OAAO,aACP,SAAS,UACT,MAAM,QAQhB;IAED;;;OAGG;IACH,yBAHW,OAAO,aACP,SAAS,QAiCnB;IAED,6BAWC;;CACJ;uBA/QsB,wBAAwB;0BACrB,qCAAqC;oBAW3C,cAAc;4CAbU,uDAAuD;2CAUxD,0DAA0D;+BANtE,yBAAyB"}
@@ -1,253 +1,282 @@
1
- import { assert } from "../../../../core/assert.js";
2
- import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
3
- import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
4
- import Vector3 from '../../../../core/geom/Vector3.js';
5
- import { clamp } from "../../../../core/math/clamp.js";
6
- import { max2 } from "../../../../core/math/max2.js";
7
- import { ResourceAccessKind } from "../../../../core/model/ResourceAccessKind.js";
8
- import { ResourceAccessSpecification } from "../../../../core/model/ResourceAccessSpecification.js";
9
- import { System } from '../../../ecs/System.js';
10
- import { Transform } from '../../../ecs/transform/Transform.js';
11
- import { Reference } from "../../../reference/v2/Reference.js";
12
- import { GraphicsEngine } from "../../GraphicsEngine.js";
13
- import { make_bvh_visibility_builder } from "../../render/make_bvh_visibility_builder.js";
14
- import {
15
- TUBE_ATTRIBUTE_ADDRESS_AGE,
16
- TUBE_ATTRIBUTE_ADDRESS_UV_V
17
- } from "../../trail/tube/tube_attributes_spec.js";
18
- import { TubeXFixedPhysicsSimulator } from "../../trail/tube/simulator/TubeXFixedPhysicsSimulator.js";
19
- import { TubeXPlugin } from "../../trail/tube/TubeXPlugin.js";
20
-
21
- import Trail3D from './Trail3D.js';
22
- import { Trail3DFlags } from "./Trail3DFlags.js";
23
-
24
- const v3Temp1 = new Vector3();
25
-
26
- class Trail3DSystem extends System {
27
- dependencies = [Trail3D, Transform];
28
-
29
- components_used = [
30
- ResourceAccessSpecification.from(Trail3D, ResourceAccessKind.Write)
31
- ];
32
-
33
- /**
34
- * @type {TubeXFixedPhysicsSimulator}
35
- */
36
- simulator = new TubeXFixedPhysicsSimulator();
37
-
38
- /**
39
- * @type {Reference<TubeXPlugin>}
40
- */
41
- #tube_plugin = Reference.NULL;
42
-
43
- /**
44
- * @type {number}
45
- */
46
- #timeDelta = 0;
47
-
48
- /**
49
- * @type {Engine}
50
- */
51
- #engine = null;
52
-
53
- /**
54
- * @private
55
- * @type {BVH}
56
- */
57
- bvh = new BVH();
58
-
59
- /**
60
- * @param {Engine} engine
61
- * @constructor
62
- */
63
- constructor(engine) {
64
- super();
65
-
66
- assert.defined(engine, 'engine');
67
- assert.notNull(engine, 'engine');
68
- assert.equal(engine.isEngine, true, 'engine.isEngine !== true');
69
-
70
- this.#engine = engine;
71
-
72
- /**
73
- * @type {GraphicsEngine}
74
- */
75
- this.graphics = engine.graphics;
76
-
77
- /**
78
- * @type {RenderLayer|null}
79
- */
80
- this.renderLayer = null;
81
- }
82
-
83
- async startup(entityManager) {
84
- this.entityManager = entityManager;
85
-
86
- this.renderLayer = this.graphics.layers.create('trail-3d-system');
87
-
88
- this.renderLayer.buildVisibleSet = make_bvh_visibility_builder(
89
- this.entityManager, this.bvh,
90
- (destination, offset, entity, ecd) => {
91
- destination[offset] = ecd.getComponent(entity, Trail3D).mesh
92
- return 1;
93
- }
94
- );
95
-
96
- const bvh = this.bvh;
97
- this.renderLayer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
98
- bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
99
- };
100
-
101
- this.#tube_plugin = await this.#engine.plugins.acquire(TubeXPlugin);
102
- }
103
-
104
- async shutdown(entityManager) {
105
- this.graphics.layers.remove(this.renderLayer);
106
-
107
- this.#tube_plugin.release();
108
- }
109
-
110
- /**
111
- * @param {Trail3D} trail
112
- * @param {Transform} transform
113
- */
114
- #build_trail(trail, transform) {
115
- const segmentsPerSecond = 60;
116
- const maxSegments = 1024;
117
-
118
- const segment_count = Math.ceil(clamp(trail.maxAge * segmentsPerSecond, 2, maxSegments));
119
-
120
- trail.build(segment_count);
121
-
122
- const tube = trail.tube;
123
-
124
- const tubes = this.#tube_plugin.getValue();
125
-
126
- const material = tubes.obtain_material_x(trail.material);
127
-
128
- trail.mesh.material = material;
129
-
130
- trail.time = 0;
131
- trail.trailingIndex = 0;
132
- trail.timeSinceLastUpdate = 0;
133
- trail.distanceSinceLastUpdate = 0;
134
-
135
- const trail_offset = trail.offset;
136
- const transform_position = transform.position;
137
-
138
- const position_x = trail_offset.x + transform_position.x;
139
- const position_y = trail_offset.y + transform_position.y;
140
- const position_z = trail_offset.z + transform_position.z;
141
-
142
- const color = trail.color;
143
-
144
- // initialize knots. setCount has already seeded a valid default frame on every
145
- // knot, so the freshly built (collapsed) tube is well-formed — a zero-length,
146
- // invisible point — until the head starts moving and supplies real tangents.
147
- for (let i = 0; i < segment_count; i++) {
148
- const f = i / (segment_count - 1);
149
-
150
- tube.setKnotColor(i, color.x * 255, color.y * 255, color.z * 255);
151
- tube.setKnotPosition(i, position_x, position_y, position_z);
152
- tube.setKnotThickness(i, trail.width);
153
- tube.setKnotAttribute_Scalar(i, TUBE_ATTRIBUTE_ADDRESS_UV_V, f);
154
- // seeded age = maxAge means "already expired", so alpha follows the fade law: 0
155
- tube.setKnotAlpha(i, 0);
156
- tube.setKnotAttribute_Scalar(i, TUBE_ATTRIBUTE_ADDRESS_AGE, trail.maxAge);
157
- }
158
-
159
- trail.bvh.resize(
160
- position_x, position_y, position_z,
161
- position_x, position_y, position_z
162
- );
163
-
164
- trail.setFlag(Trail3DFlags.Built);
165
- }
166
-
167
- /**
168
- * @param {Trail3D} trail
169
- * @param {Transform} transform
170
- * @param {number} entityId
171
- */
172
- link(trail, transform, entityId) {
173
- // Trail3DFlags.Lit is final by link time — bake it into the material spec
174
- // (the material cache key) so lit and unlit trails obtain distinct materials
175
- trail.material.lit = trail.getFlag(Trail3DFlags.Lit);
176
-
177
- if (!trail.getFlag(Trail3DFlags.Built)) {
178
- this.#build_trail(trail, transform);
179
- } else {
180
-
181
- const material = this.#tube_plugin.getValue().obtain_material_x(trail.material);
182
- trail.mesh.material = material;
183
- }
184
-
185
- trail.bvh.link(this.bvh, entityId);
186
- }
187
-
188
- /**
189
- * @param {Trail3D} component
190
- * @param {Transform} transform
191
- * @param {number} entity
192
- */
193
- unlink(component, transform, entity) {
194
-
195
- component.bvh.unlink();
196
-
197
- // release resources
198
- component.dispose();
199
- }
200
-
201
- /**
202
- * @param {Trail3D} trail
203
- * @param {Transform} transform
204
- */
205
- updateTrailEntity(trail, transform) {
206
- const timeDelta = this.#timeDelta;
207
-
208
- /**
209
- * @type {TubeX|null}
210
- */
211
- const tube = trail.tube;
212
-
213
- const newPosition = v3Temp1;
214
-
215
- newPosition.copy(trail.offset);
216
- newPosition.applyMatrix4(transform.matrix);
217
-
218
- trail.timeSinceLastUpdate += timeDelta;
219
- trail.time += timeDelta;
220
-
221
- const ageOffset = max2(0, trail.maxAge - trail.time);
222
-
223
- this.simulator.update(tube, trail.maxAge, timeDelta, trail.color.w);
224
-
225
- if (trail.getFlag(Trail3DFlags.Spawning)) {
226
- trail.updateHead(newPosition.x, newPosition.y, newPosition.z, ageOffset);
227
- }
228
-
229
- if (trail.getFlag(Trail3DFlags.BoundsNeedUpdate)) {
230
- const bvh = trail.bvh;
231
-
232
- tube.computeBoundingBox(bvh.bounds);
233
- bvh.write_bounds();
234
-
235
- trail.clearFlag(Trail3DFlags.BoundsNeedUpdate);
236
- }
237
- }
238
-
239
- update(timeDelta) {
240
-
241
- const em = this.entityManager;
242
-
243
- const dataset = em.dataset;
244
-
245
- this.#timeDelta = timeDelta;
246
-
247
- if (dataset !== null) {
248
- dataset.traverseEntities([Trail3D, Transform], this.updateTrailEntity, this);
249
- }
250
- }
251
- }
252
-
253
- export default Trail3DSystem;
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { BVH } from "../../../../core/bvh2/bvh3/BVH.js";
3
+ import { bvh_query_depth_range_in_frustum } from "../../../../core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js";
4
+ import Vector3 from '../../../../core/geom/Vector3.js';
5
+ import { clamp } from "../../../../core/math/clamp.js";
6
+ import { max2 } from "../../../../core/math/max2.js";
7
+ import { ResourceAccessKind } from "../../../../core/model/ResourceAccessKind.js";
8
+ import { ResourceAccessSpecification } from "../../../../core/model/ResourceAccessSpecification.js";
9
+ import { System } from '../../../ecs/System.js';
10
+ import { Transform } from '../../../ecs/transform/Transform.js';
11
+ import { Reference } from "../../../reference/v2/Reference.js";
12
+ import { GraphicsEngine } from "../../GraphicsEngine.js";
13
+ import { make_bvh_visibility_builder } from "../../render/make_bvh_visibility_builder.js";
14
+ import {
15
+ TUBE_ATTRIBUTE_ADDRESS_AGE,
16
+ TUBE_ATTRIBUTE_ADDRESS_UV_V
17
+ } from "../../trail/tube/tube_attributes_spec.js";
18
+ import { TubeXFixedPhysicsSimulator } from "../../trail/tube/simulator/TubeXFixedPhysicsSimulator.js";
19
+ import { TubeXPlugin } from "../../trail/tube/TubeXPlugin.js";
20
+
21
+ import Trail3D from './Trail3D.js';
22
+ import { Trail3DFlags } from "./Trail3DFlags.js";
23
+
24
+ const v3Temp1 = new Vector3();
25
+
26
+ /**
27
+ * Separate from {@link v3Temp1}: the build path runs from `link`, the head path
28
+ * from `update`, and sharing one scratch across the two would couple them for no
29
+ * gain.
30
+ * @type {Vector3}
31
+ */
32
+ const v3_build_position = new Vector3();
33
+
34
+ /**
35
+ * World point the trail's head tracks: the component's {@link Trail3D#offset},
36
+ * which lives in the entity's LOCAL frame, carried through the entity's full
37
+ * transform — so it rides the entity's rotation and scales with it.
38
+ *
39
+ * Build-time seeding and the per-frame head update must agree on this. If they
40
+ * disagree, the freshly built tube sits collapsed somewhere the head never
41
+ * visits, and the head's first move draws a segment bridging the two — a
42
+ * one-frame streak as long as the disagreement, in a direction fixed by the
43
+ * offset rather than by travel.
44
+ *
45
+ * @param {Vector3} result
46
+ * @param {Trail3D} trail
47
+ * @param {Transform} transform
48
+ * @returns {void}
49
+ */
50
+ function compute_head_position(result, trail, transform) {
51
+ result.copy(trail.offset);
52
+ result.applyMatrix4(transform.matrix);
53
+ }
54
+
55
+ class Trail3DSystem extends System {
56
+ dependencies = [Trail3D, Transform];
57
+
58
+ components_used = [
59
+ ResourceAccessSpecification.from(Trail3D, ResourceAccessKind.Write)
60
+ ];
61
+
62
+ /**
63
+ * @type {TubeXFixedPhysicsSimulator}
64
+ */
65
+ simulator = new TubeXFixedPhysicsSimulator();
66
+
67
+ /**
68
+ * @type {Reference<TubeXPlugin>}
69
+ */
70
+ #tube_plugin = Reference.NULL;
71
+
72
+ /**
73
+ * @type {number}
74
+ */
75
+ #timeDelta = 0;
76
+
77
+ /**
78
+ * @type {Engine}
79
+ */
80
+ #engine = null;
81
+
82
+ /**
83
+ * @private
84
+ * @type {BVH}
85
+ */
86
+ bvh = new BVH();
87
+
88
+ /**
89
+ * @param {Engine} engine
90
+ * @constructor
91
+ */
92
+ constructor(engine) {
93
+ super();
94
+
95
+ assert.defined(engine, 'engine');
96
+ assert.notNull(engine, 'engine');
97
+ assert.equal(engine.isEngine, true, 'engine.isEngine !== true');
98
+
99
+ this.#engine = engine;
100
+
101
+ /**
102
+ * @type {GraphicsEngine}
103
+ */
104
+ this.graphics = engine.graphics;
105
+
106
+ /**
107
+ * @type {RenderLayer|null}
108
+ */
109
+ this.renderLayer = null;
110
+ }
111
+
112
+ async startup(entityManager) {
113
+ this.entityManager = entityManager;
114
+
115
+ this.renderLayer = this.graphics.layers.create('trail-3d-system');
116
+
117
+ this.renderLayer.buildVisibleSet = make_bvh_visibility_builder(
118
+ this.entityManager, this.bvh,
119
+ (destination, offset, entity, ecd) => {
120
+ destination[offset] = ecd.getComponent(entity, Trail3D).mesh
121
+ return 1;
122
+ }
123
+ );
124
+
125
+ const bvh = this.bvh;
126
+ this.renderLayer.compute_depth_range = (result, frustum, nx, ny, nz, c) => {
127
+ bvh_query_depth_range_in_frustum(result, bvh, frustum, nx, ny, nz, c);
128
+ };
129
+
130
+ this.#tube_plugin = await this.#engine.plugins.acquire(TubeXPlugin);
131
+ }
132
+
133
+ async shutdown(entityManager) {
134
+ this.graphics.layers.remove(this.renderLayer);
135
+
136
+ this.#tube_plugin.release();
137
+ }
138
+
139
+ /**
140
+ * @param {Trail3D} trail
141
+ * @param {Transform} transform
142
+ */
143
+ #build_trail(trail, transform) {
144
+ const segmentsPerSecond = 60;
145
+ const maxSegments = 1024;
146
+
147
+ const segment_count = Math.ceil(clamp(trail.maxAge * segmentsPerSecond, 2, maxSegments));
148
+
149
+ trail.build(segment_count);
150
+
151
+ const tube = trail.tube;
152
+
153
+ const tubes = this.#tube_plugin.getValue();
154
+
155
+ const material = tubes.obtain_material_x(trail.material);
156
+
157
+ trail.mesh.material = material;
158
+
159
+ trail.time = 0;
160
+ trail.trailingIndex = 0;
161
+ trail.timeSinceLastUpdate = 0;
162
+ trail.distanceSinceLastUpdate = 0;
163
+
164
+ // seed exactly where updateTrailEntity will place the head, or the first
165
+ // head move bridges the gap with a visible segment
166
+ compute_head_position(v3_build_position, trail, transform);
167
+
168
+ const position_x = v3_build_position.x;
169
+ const position_y = v3_build_position.y;
170
+ const position_z = v3_build_position.z;
171
+
172
+ const color = trail.color;
173
+
174
+ // initialize knots. setCount has already seeded a valid default frame on every
175
+ // knot, so the freshly built (collapsed) tube is well-formed — a zero-length,
176
+ // invisible point — until the head starts moving and supplies real tangents.
177
+ for (let i = 0; i < segment_count; i++) {
178
+ const f = i / (segment_count - 1);
179
+
180
+ tube.setKnotColor(i, color.x * 255, color.y * 255, color.z * 255);
181
+ tube.setKnotPosition(i, position_x, position_y, position_z);
182
+ tube.setKnotThickness(i, trail.width);
183
+ tube.setKnotAttribute_Scalar(i, TUBE_ATTRIBUTE_ADDRESS_UV_V, f);
184
+ // seeded age = maxAge means "already expired", so alpha follows the fade law: 0
185
+ tube.setKnotAlpha(i, 0);
186
+ tube.setKnotAttribute_Scalar(i, TUBE_ATTRIBUTE_ADDRESS_AGE, trail.maxAge);
187
+ }
188
+
189
+ trail.bvh.resize(
190
+ position_x, position_y, position_z,
191
+ position_x, position_y, position_z
192
+ );
193
+
194
+ trail.setFlag(Trail3DFlags.Built);
195
+ }
196
+
197
+ /**
198
+ * @param {Trail3D} trail
199
+ * @param {Transform} transform
200
+ * @param {number} entityId
201
+ */
202
+ link(trail, transform, entityId) {
203
+ // Trail3DFlags.Lit is final by link time — bake it into the material spec
204
+ // (the material cache key) so lit and unlit trails obtain distinct materials
205
+ trail.material.lit = trail.getFlag(Trail3DFlags.Lit);
206
+
207
+ if (!trail.getFlag(Trail3DFlags.Built)) {
208
+ this.#build_trail(trail, transform);
209
+ } else {
210
+
211
+ const material = this.#tube_plugin.getValue().obtain_material_x(trail.material);
212
+ trail.mesh.material = material;
213
+ }
214
+
215
+ trail.bvh.link(this.bvh, entityId);
216
+ }
217
+
218
+ /**
219
+ * @param {Trail3D} component
220
+ * @param {Transform} transform
221
+ * @param {number} entity
222
+ */
223
+ unlink(component, transform, entity) {
224
+
225
+ component.bvh.unlink();
226
+
227
+ // release resources
228
+ component.dispose();
229
+ }
230
+
231
+ /**
232
+ * @param {Trail3D} trail
233
+ * @param {Transform} transform
234
+ */
235
+ updateTrailEntity(trail, transform) {
236
+ const timeDelta = this.#timeDelta;
237
+
238
+ /**
239
+ * @type {TubeX|null}
240
+ */
241
+ const tube = trail.tube;
242
+
243
+ const newPosition = v3Temp1;
244
+
245
+ compute_head_position(newPosition, trail, transform);
246
+
247
+ trail.timeSinceLastUpdate += timeDelta;
248
+ trail.time += timeDelta;
249
+
250
+ const ageOffset = max2(0, trail.maxAge - trail.time);
251
+
252
+ this.simulator.update(tube, trail.maxAge, timeDelta, trail.color.w);
253
+
254
+ if (trail.getFlag(Trail3DFlags.Spawning)) {
255
+ trail.updateHead(newPosition.x, newPosition.y, newPosition.z, ageOffset);
256
+ }
257
+
258
+ if (trail.getFlag(Trail3DFlags.BoundsNeedUpdate)) {
259
+ const bvh = trail.bvh;
260
+
261
+ tube.computeBoundingBox(bvh.bounds);
262
+ bvh.write_bounds();
263
+
264
+ trail.clearFlag(Trail3DFlags.BoundsNeedUpdate);
265
+ }
266
+ }
267
+
268
+ update(timeDelta) {
269
+
270
+ const em = this.entityManager;
271
+
272
+ const dataset = em.dataset;
273
+
274
+ this.#timeDelta = timeDelta;
275
+
276
+ if (dataset !== null) {
277
+ dataset.traverseEntities([Trail3D, Transform], this.updateTrailEntity, this);
278
+ }
279
+ }
280
+ }
281
+
282
+ export default Trail3DSystem;