@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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @enum {boolean}
|
|
4
4
|
*/
|
|
5
5
|
import { assert } from "../assert.js";
|
|
6
|
+
import { array_copy } from "../collection/array/copyArray.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -30,17 +31,50 @@ function BinaryBuffer() {
|
|
|
30
31
|
*/
|
|
31
32
|
this.endianness = EndianType.BigEndian;
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
33
38
|
this.position = 0;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @type {number}
|
|
43
|
+
*/
|
|
34
44
|
this.length = 0;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {number}
|
|
49
|
+
*/
|
|
35
50
|
this.capacity = 0;
|
|
36
51
|
|
|
37
52
|
/**
|
|
38
53
|
*
|
|
39
54
|
* @type {ArrayBuffer}
|
|
55
|
+
* @private
|
|
40
56
|
*/
|
|
41
57
|
this.data = new ArrayBuffer(0);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @type {DataView}
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
42
64
|
this.dataView = new DataView(this.data);
|
|
43
65
|
|
|
66
|
+
/**
|
|
67
|
+
*
|
|
68
|
+
* @type {Uint8Array}
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
this.__data_uint8 = new Uint8Array(0);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
* @type {number}
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
44
78
|
this.__growFactor = 1.1;
|
|
45
79
|
}
|
|
46
80
|
|
|
@@ -50,6 +84,7 @@ function BinaryBuffer() {
|
|
|
50
84
|
BinaryBuffer.prototype.fromArrayBuffer = function (arrayBuffer) {
|
|
51
85
|
this.data = arrayBuffer;
|
|
52
86
|
this.dataView = new DataView(arrayBuffer);
|
|
87
|
+
this.__data_uint8 = new Uint8Array(arrayBuffer);
|
|
53
88
|
|
|
54
89
|
this.capacity = arrayBuffer.byteLength;
|
|
55
90
|
//assume that all the data is useful
|
|
@@ -85,7 +120,7 @@ BinaryBuffer.prototype.trim = function () {
|
|
|
85
120
|
* @param {number} capacity
|
|
86
121
|
*/
|
|
87
122
|
BinaryBuffer.prototype.setCapacity = function (capacity) {
|
|
88
|
-
const oldData =
|
|
123
|
+
const oldData = this.__data_uint8;
|
|
89
124
|
const newData = new Uint8Array(capacity);
|
|
90
125
|
|
|
91
126
|
//copy old data
|
|
@@ -93,7 +128,7 @@ BinaryBuffer.prototype.setCapacity = function (capacity) {
|
|
|
93
128
|
newData.set(oldData.subarray(0, copyLength), 0);
|
|
94
129
|
|
|
95
130
|
this.data = newData.buffer;
|
|
96
|
-
|
|
131
|
+
this.__data_uint8 = newData;
|
|
97
132
|
this.dataView = new DataView(this.data);
|
|
98
133
|
|
|
99
134
|
this.capacity = capacity;
|
|
@@ -680,11 +715,11 @@ BinaryBuffer.prototype.writeUint32LE = function (value) {
|
|
|
680
715
|
/**
|
|
681
716
|
*
|
|
682
717
|
* @param {Uint8Array|Uint8ClampedArray} array
|
|
683
|
-
* @param {number}
|
|
718
|
+
* @param {number} source_offset
|
|
684
719
|
* @param {number} length
|
|
685
720
|
*/
|
|
686
|
-
BinaryBuffer.prototype.writeBytes = function (array,
|
|
687
|
-
const source_end =
|
|
721
|
+
BinaryBuffer.prototype.writeBytes = function (array, source_offset, length) {
|
|
722
|
+
const source_end = source_offset + length;
|
|
688
723
|
assert.greaterThanOrEqual(array.length, source_end, 'source array underflow');
|
|
689
724
|
|
|
690
725
|
const targetAddress = this.position;
|
|
@@ -693,18 +728,21 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
|
|
|
693
728
|
|
|
694
729
|
this.ensureCapacity(end);
|
|
695
730
|
|
|
696
|
-
|
|
731
|
+
if (source_offset === 0 && array.length === length) {
|
|
732
|
+
// copying entire source array
|
|
697
733
|
|
|
698
|
-
|
|
734
|
+
this.__data_uint8.set(array, targetAddress);
|
|
735
|
+
|
|
736
|
+
} else if (typeof array.subarray === "function") {
|
|
699
737
|
// typed array, use "subarray" method
|
|
700
738
|
|
|
701
|
-
|
|
739
|
+
this.__data_uint8.set(array.subarray(source_offset, source_end), targetAddress);
|
|
702
740
|
|
|
703
741
|
} else {
|
|
704
742
|
// not a typed array, copy byte by byte manually
|
|
705
743
|
|
|
706
744
|
for (let i = 0; i < length; i++) {
|
|
707
|
-
|
|
745
|
+
this.__data_uint8[targetAddress + i] = array[source_offset + i];
|
|
708
746
|
}
|
|
709
747
|
|
|
710
748
|
}
|
|
@@ -714,14 +752,23 @@ BinaryBuffer.prototype.writeBytes = function (array, sourceOffset, length) {
|
|
|
714
752
|
|
|
715
753
|
/**
|
|
716
754
|
*
|
|
717
|
-
* @param {Uint8Array}
|
|
718
|
-
* @param {number}
|
|
755
|
+
* @param {Uint8Array} destination
|
|
756
|
+
* @param {number} destination_offset
|
|
719
757
|
* @param {number} length
|
|
720
758
|
*/
|
|
721
|
-
BinaryBuffer.prototype.readBytes = function (
|
|
722
|
-
const
|
|
723
|
-
|
|
724
|
-
|
|
759
|
+
BinaryBuffer.prototype.readBytes = function (destination, destination_offset, length) {
|
|
760
|
+
const source_position = this.position;
|
|
761
|
+
|
|
762
|
+
const end = source_position + length;
|
|
763
|
+
|
|
764
|
+
const uint8 = this.__data_uint8;
|
|
765
|
+
|
|
766
|
+
if (length < 128) {
|
|
767
|
+
// small copy
|
|
768
|
+
array_copy(uint8, source_position, destination, destination_offset, length);
|
|
769
|
+
} else {
|
|
770
|
+
destination.set(uint8.subarray(source_position, end), destination_offset);
|
|
771
|
+
}
|
|
725
772
|
|
|
726
773
|
this.position = end;
|
|
727
774
|
};
|
|
@@ -764,7 +811,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
|
|
|
764
811
|
|
|
765
812
|
this.ensureCapacity(tlen + at);
|
|
766
813
|
|
|
767
|
-
let target =
|
|
814
|
+
let target = this.__data_uint8; // ... but at 8 byte offset
|
|
768
815
|
|
|
769
816
|
|
|
770
817
|
while (pos < len) {
|
|
@@ -791,7 +838,7 @@ BinaryBuffer.prototype.writeUTF8String = function (string) {
|
|
|
791
838
|
|
|
792
839
|
this.ensureCapacity(tlen + startPosition);
|
|
793
840
|
|
|
794
|
-
target =
|
|
841
|
+
target = this.__data_uint8;
|
|
795
842
|
}
|
|
796
843
|
|
|
797
844
|
if ((value & 0xffffff80) === 0) { // 1-byte
|
|
@@ -851,7 +898,7 @@ BinaryBuffer.prototype.readUTF8String = function () {
|
|
|
851
898
|
return undefined;
|
|
852
899
|
}
|
|
853
900
|
|
|
854
|
-
const bytes =
|
|
901
|
+
const bytes = this.__data_uint8;
|
|
855
902
|
|
|
856
903
|
|
|
857
904
|
let result = "";
|
|
@@ -26,7 +26,7 @@ export const ProjectionType = {
|
|
|
26
26
|
export class Camera {
|
|
27
27
|
constructor() {
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Whether clipping planes should be automatically calculated or not
|
|
30
30
|
* @type {boolean}
|
|
31
31
|
*/
|
|
32
32
|
this.autoClip = true;
|
|
@@ -56,6 +56,44 @@ export class Camera {
|
|
|
56
56
|
* @type {ObservedBoolean}
|
|
57
57
|
*/
|
|
58
58
|
this.active = new ObservedBoolean(false);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Near clipping plane
|
|
62
|
+
* @type {number}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
this.__clip_far = 100;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Far clipping plane
|
|
69
|
+
* @type {number}
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
this.__clip_near = 0.1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get clip_far() {
|
|
76
|
+
return this.__clip_far;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set clip_far(v) {
|
|
80
|
+
this.__clip_far = v;
|
|
81
|
+
|
|
82
|
+
if (this.object !== null) {
|
|
83
|
+
this.object.far = v;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get clip_near() {
|
|
88
|
+
return this.__clip_near;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
set clip_near(v) {
|
|
92
|
+
this.__clip_near = v;
|
|
93
|
+
|
|
94
|
+
if (this.object !== null) {
|
|
95
|
+
this.object.near = v;
|
|
96
|
+
}
|
|
59
97
|
}
|
|
60
98
|
|
|
61
99
|
updateMatrices() {
|
|
@@ -9,7 +9,6 @@ import { Transform } from '../../../ecs/transform/Transform.js';
|
|
|
9
9
|
import {
|
|
10
10
|
Frustum as ThreeFrustum,
|
|
11
11
|
Matrix4,
|
|
12
|
-
Matrix4 as ThreeMatrix4,
|
|
13
12
|
OrthographicCamera as ThreeOrthographicCamera,
|
|
14
13
|
PerspectiveCamera as ThreePerspectiveCamera,
|
|
15
14
|
Vector3 as ThreeVector3,
|
|
@@ -76,16 +75,25 @@ function setAspectRatio(camera, width, height) {
|
|
|
76
75
|
* @returns {PerspectiveCamera| OrthographicCamera}
|
|
77
76
|
*/
|
|
78
77
|
function buildThreeCamera(component) {
|
|
78
|
+
|
|
79
|
+
let result;
|
|
79
80
|
switch (component.projectionType.getValue()) {
|
|
80
81
|
default:
|
|
81
82
|
console.error(`Unsupported camera projection type "${component.projectionType.getValue()}", defaulting to perspective projection`);
|
|
82
83
|
//fallthrough
|
|
83
84
|
case Camera.ProjectionType.Perspective:
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
result = new ThreePerspectiveCamera(component.fov.getValue(), 1, 1, 50);
|
|
86
|
+
break;
|
|
86
87
|
case Camera.ProjectionType.Orthographic:
|
|
87
|
-
|
|
88
|
+
result = new ThreeOrthographicCamera(-10, 10, 20, -20, 1, 1);
|
|
89
|
+
break;
|
|
88
90
|
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
result.far = component.clip_far;
|
|
94
|
+
result.near = component.clip_near;
|
|
95
|
+
|
|
96
|
+
return result;
|
|
89
97
|
}
|
|
90
98
|
|
|
91
99
|
export class CameraSystem extends System {
|
|
@@ -289,8 +297,19 @@ export class CameraSystem extends System {
|
|
|
289
297
|
* @param {Camera} c
|
|
290
298
|
*/
|
|
291
299
|
function visitCameraEntity(c) {
|
|
292
|
-
if (c.
|
|
300
|
+
if (c.object === null) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (!c.active.getValue()) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (c.autoClip === true) {
|
|
293
309
|
autoSetClippingPlanes(c, layers);
|
|
310
|
+
} else {
|
|
311
|
+
c.object.far = c.clip_far;
|
|
312
|
+
c.object.near = c.clip_near;
|
|
294
313
|
}
|
|
295
314
|
}
|
|
296
315
|
|
|
@@ -376,7 +395,7 @@ export class CameraSystem extends System {
|
|
|
376
395
|
}
|
|
377
396
|
}
|
|
378
397
|
|
|
379
|
-
const matrix4 = new
|
|
398
|
+
const matrix4 = new Matrix4();
|
|
380
399
|
|
|
381
400
|
/**
|
|
382
401
|
*
|
|
@@ -74,6 +74,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
74
74
|
* @private
|
|
75
75
|
*/
|
|
76
76
|
this.__adapter_suppliers = new Map();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Keeps count of usage for each geometry by ID
|
|
80
|
+
* @type {Map<number, number>}
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
this.__geometry_usage_counters = new Map();
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/**
|
|
@@ -166,7 +173,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
166
173
|
this.__render_layer.buildVisibleSet = ((destination, destination_offset, view) => {
|
|
167
174
|
const ctx = this.__view_contexts.get(view);
|
|
168
175
|
|
|
169
|
-
return ctx.collect(destination, destination_offset,graphics.renderer, view, this.__bvh);
|
|
176
|
+
return ctx.collect(destination, destination_offset, graphics.renderer, view, this.__bvh);
|
|
170
177
|
});
|
|
171
178
|
|
|
172
179
|
readyCallback();
|
|
@@ -210,6 +217,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
210
217
|
sg.__entity = entity;
|
|
211
218
|
|
|
212
219
|
this.__bvh.insertNode(leaf_node);
|
|
220
|
+
|
|
221
|
+
// update usage count
|
|
222
|
+
const geometry_id = sg.geometry.id;
|
|
223
|
+
const count_existing = this.__geometry_usage_counters.get(geometry_id);
|
|
224
|
+
const count_new = count_existing !== undefined ? count_existing + 1 : 1;
|
|
225
|
+
|
|
226
|
+
this.__geometry_usage_counters.set(geometry_id, count_new);
|
|
213
227
|
}
|
|
214
228
|
|
|
215
229
|
/**
|
|
@@ -224,6 +238,21 @@ export class ShadedGeometrySystem extends System {
|
|
|
224
238
|
t.scale.onChanged.remove(sg.updateTransform, sg);
|
|
225
239
|
|
|
226
240
|
sg.bvh.disconnect();
|
|
241
|
+
|
|
242
|
+
const geometry_id = sg.geometry.id;
|
|
243
|
+
const count_existing = this.__geometry_usage_counters.get(geometry_id);
|
|
244
|
+
|
|
245
|
+
if (count_existing === 1) {
|
|
246
|
+
|
|
247
|
+
// last instance
|
|
248
|
+
this.__geometry_usage_counters.delete(geometry_id);
|
|
249
|
+
|
|
250
|
+
// release GPU memory
|
|
251
|
+
sg.geometry.dispose();
|
|
252
|
+
|
|
253
|
+
} else {
|
|
254
|
+
this.__geometry_usage_counters.set(geometry_id, count_existing - 1);
|
|
255
|
+
}
|
|
227
256
|
}
|
|
228
257
|
|
|
229
258
|
/**
|
|
@@ -313,13 +342,19 @@ export class ShadedGeometrySystem extends System {
|
|
|
313
342
|
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
314
343
|
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
315
344
|
const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
|
|
316
|
-
|
|
345
|
+
|
|
346
|
+
const local_direction_magnitude = Math.hypot(local_direction_x, local_direction_y, local_direction_z);
|
|
347
|
+
const local_direction_magnitude_inverse = 1 / local_direction_magnitude;
|
|
348
|
+
|
|
349
|
+
const local_direction_normalized_x = local_direction_x * local_direction_magnitude_inverse;
|
|
350
|
+
const local_direction_normalized_y = local_direction_y * local_direction_magnitude_inverse;
|
|
351
|
+
const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
|
|
317
352
|
|
|
318
353
|
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_primitive(
|
|
319
354
|
scratch_point,
|
|
320
355
|
sg.geometry,
|
|
321
356
|
local_origin_x, local_origin_y, local_origin_z,
|
|
322
|
-
|
|
357
|
+
local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
|
|
323
358
|
);
|
|
324
359
|
|
|
325
360
|
if (!geometry_hit_found) {
|
|
@@ -20,6 +20,9 @@ import { randomFromArray } from "../../../../../core/math/random/randomFromArray
|
|
|
20
20
|
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
21
21
|
import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
|
|
22
22
|
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
23
|
+
import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
|
|
24
|
+
import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
|
|
25
|
+
import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
|
|
23
26
|
|
|
24
27
|
const eh = new EngineHarness();
|
|
25
28
|
|
|
@@ -50,7 +53,17 @@ async function main(engine) {
|
|
|
50
53
|
|
|
51
54
|
const em = engine.entityManager;
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
const sgs = new ShadedGeometrySystem(engine);
|
|
57
|
+
|
|
58
|
+
const mrc = new MicronRenderContext();
|
|
59
|
+
sgs.register_render_adapter(2, () => {
|
|
60
|
+
const adapter = new MicronShadedGeometryRenderAdapter();
|
|
61
|
+
adapter.ctx = mrc;
|
|
62
|
+
|
|
63
|
+
return adapter;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await em.addSystem(sgs);
|
|
54
67
|
await em.addSystem(new BehaviorSystem(engine));
|
|
55
68
|
|
|
56
69
|
EngineHarness.buildBasics({
|
|
@@ -74,7 +87,7 @@ async function main(engine) {
|
|
|
74
87
|
|
|
75
88
|
const random = seededRandom(0);
|
|
76
89
|
|
|
77
|
-
const INSTANCE_COUNT =
|
|
90
|
+
const INSTANCE_COUNT = 10000;
|
|
78
91
|
|
|
79
92
|
const geometries = [];
|
|
80
93
|
|
|
@@ -87,7 +100,9 @@ async function main(engine) {
|
|
|
87
100
|
const sg = ShadedGeometry.from(geometry, material);
|
|
88
101
|
|
|
89
102
|
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
90
|
-
sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
103
|
+
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
104
|
+
// sg.draw_method = 2;
|
|
105
|
+
sg.draw_method = randomIntegerBetween(random, 0, 2);
|
|
91
106
|
// sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
|
|
92
107
|
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
93
108
|
|
|
@@ -105,7 +120,7 @@ async function main(engine) {
|
|
|
105
120
|
.build(ecd);
|
|
106
121
|
}
|
|
107
122
|
|
|
108
|
-
makeMovingShadedGeometry().build(ecd);
|
|
123
|
+
// makeMovingShadedGeometry().build(ecd);
|
|
109
124
|
|
|
110
125
|
debug_button(engine, () => {
|
|
111
126
|
const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
|
|
@@ -10,7 +10,7 @@ import { RibbonXPlugin } from "../../trail/x/RibbonXPlugin.js";
|
|
|
10
10
|
import { RibbonPathBuilder } from "./ribbon/RibbonPathBuilder.js";
|
|
11
11
|
import { PathEvents } from "../../../navigation/ecs/components/PathEvents.js";
|
|
12
12
|
import { assert } from "../../../../core/assert.js";
|
|
13
|
-
import { TubePathBuilder } from "./tube/TubePathBuilder.js";
|
|
13
|
+
import { TubePathBuilder } from "./tube/build/TubePathBuilder.js";
|
|
14
14
|
|
|
15
15
|
const builders = {
|
|
16
16
|
[PathDisplayType.None]: function (style, path, result) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { EngineHarness } from "../../../EngineHarness.js";
|
|
2
|
-
import RenderSystem from "../../../ecs/systems/RenderSystem.js";
|
|
3
2
|
import { makeEngineOptionsModel } from "../../../../../model/game/options/makeEngineOptionsModel.js";
|
|
4
3
|
import Path from "../../../navigation/ecs/components/Path.js";
|
|
5
4
|
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
@@ -68,6 +67,7 @@ import { TubePathStyle } from "./tube/TubePathStyle.js";
|
|
|
68
67
|
import { TubeMaterialType } from "./tube/TubeMaterialType.js";
|
|
69
68
|
import { MatcapMaterialDefinition } from "./tube/MatcapMaterialDefinition.js";
|
|
70
69
|
import { TextureAssetLoader } from "../../../asset/loaders/texture/TextureAssetLoader.js";
|
|
70
|
+
import { ShadedGeometrySystem } from "../mesh-v2/ShadedGeometrySystem.js";
|
|
71
71
|
|
|
72
72
|
const engineHarness = new EngineHarness();
|
|
73
73
|
|
|
@@ -156,7 +156,8 @@ function makeConfig(engine) {
|
|
|
156
156
|
async function init(harness) {
|
|
157
157
|
const engine = harness.engine;
|
|
158
158
|
|
|
159
|
-
engine.entityManager.addSystem(new RenderSystem(engine.graphics));
|
|
159
|
+
// engine.entityManager.addSystem(new RenderSystem(engine.graphics));
|
|
160
|
+
engine.entityManager.addSystem(new ShadedGeometrySystem(engine));
|
|
160
161
|
|
|
161
162
|
makeEngineOptionsModel(engine.options, engine);
|
|
162
163
|
|
|
@@ -315,6 +316,12 @@ function sample_style_tube() {
|
|
|
315
316
|
|
|
316
317
|
style.width = 0.1;
|
|
317
318
|
|
|
319
|
+
style.path_mask = [
|
|
320
|
+
0.1, 0.12,
|
|
321
|
+
0.3, 0.8,
|
|
322
|
+
0.9, 1
|
|
323
|
+
];
|
|
324
|
+
|
|
318
325
|
return style;
|
|
319
326
|
}
|
|
320
327
|
|
|
@@ -323,8 +330,8 @@ function main(engine) {
|
|
|
323
330
|
EngineHarness.buildBasics({ engine });
|
|
324
331
|
|
|
325
332
|
const _p = new Path();
|
|
326
|
-
|
|
327
|
-
_p.interpolation = InterpolationType.Linear;
|
|
333
|
+
_p.interpolation = InterpolationType.CatmullRom;
|
|
334
|
+
// _p.interpolation = InterpolationType.Linear;
|
|
328
335
|
|
|
329
336
|
// _p.setPositionsFromVectorArray(Path.smoothPath([
|
|
330
337
|
// new Vector3(3, 1, 1),
|
|
@@ -352,14 +359,14 @@ function main(engine) {
|
|
|
352
359
|
|
|
353
360
|
const pathDisplay = new PathDisplay();
|
|
354
361
|
pathDisplay.specs.push(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
362
|
+
PathDisplaySpec.from(
|
|
363
|
+
PathDisplayType.Ribbon,
|
|
364
|
+
trailPathStyle
|
|
365
|
+
),
|
|
366
|
+
PathDisplaySpec.from(
|
|
367
|
+
PathDisplayType.Entity,
|
|
368
|
+
sample_style_entity()
|
|
369
|
+
),
|
|
363
370
|
PathDisplaySpec.from(
|
|
364
371
|
PathDisplayType.Tube,
|
|
365
372
|
sample_style_tube()
|
|
@@ -3,10 +3,19 @@ import { TubeMaterialType } from "./TubeMaterialType.js";
|
|
|
3
3
|
import { assert } from "../../../../../core/assert.js";
|
|
4
4
|
import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
5
5
|
|
|
6
|
+
const DEFAULT_COLOR = Object.freeze({ r: 1, g: 1, b: 1 });
|
|
7
|
+
|
|
6
8
|
export class TubePathStyle {
|
|
7
9
|
constructor() {
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @type {Color}
|
|
13
|
+
*/
|
|
8
14
|
this.color = new Color(1, 1, 1);
|
|
9
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @type {TubeMaterialType}
|
|
18
|
+
*/
|
|
10
19
|
this.material_type = TubeMaterialType.Unknown;
|
|
11
20
|
|
|
12
21
|
/**
|
|
@@ -15,13 +24,53 @@ export class TubePathStyle {
|
|
|
15
24
|
*/
|
|
16
25
|
this.material = null;
|
|
17
26
|
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @type {number}
|
|
30
|
+
*/
|
|
18
31
|
this.opacity = 1;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @type {number}
|
|
36
|
+
*/
|
|
19
37
|
this.width = 1;
|
|
20
38
|
|
|
21
39
|
// TODO expose shading style "flat/smooth"
|
|
22
40
|
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @type {number}
|
|
44
|
+
*/
|
|
23
45
|
this.resolution = 10;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @type {number}
|
|
50
|
+
*/
|
|
24
51
|
this.radial_resolution = 16;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @type {boolean}
|
|
56
|
+
*/
|
|
57
|
+
this.cast_shadow = false;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @type {boolean}
|
|
62
|
+
*/
|
|
63
|
+
this.receive_shadow = false;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Which parts of the path to visualise, in normalized offsets
|
|
67
|
+
* @example [ 0, 1 ] = whole path
|
|
68
|
+
* @example [ 0, 0.5 ] = first half of the path
|
|
69
|
+
* @example [ 0.5, 0.6 ] = segment from 50% along the path, to 60% along the path
|
|
70
|
+
* @example [ 0, 0.1, 0.9, 1] = first 10% of the path, and last 10% of the path
|
|
71
|
+
* @type {number[]}
|
|
72
|
+
*/
|
|
73
|
+
this.path_mask = [0, 1];
|
|
25
74
|
}
|
|
26
75
|
|
|
27
76
|
static fromJSON(j) {
|
|
@@ -33,15 +82,30 @@ export class TubePathStyle {
|
|
|
33
82
|
}
|
|
34
83
|
|
|
35
84
|
fromJSON({
|
|
36
|
-
color,
|
|
85
|
+
color = DEFAULT_COLOR,
|
|
37
86
|
material_type,
|
|
38
87
|
material,
|
|
39
88
|
opacity = 1,
|
|
40
89
|
width = 1,
|
|
41
90
|
resolution = 10,
|
|
42
|
-
radial_resolution = 16
|
|
91
|
+
radial_resolution = 16,
|
|
92
|
+
cast_shadow = false,
|
|
93
|
+
receive_shadow = false,
|
|
94
|
+
path_mask = [0, 1]
|
|
43
95
|
}) {
|
|
44
96
|
assert.enum(material_type, TubeMaterialType, 'material_type');
|
|
97
|
+
assert.isNumber(opacity, 'opacity');
|
|
98
|
+
assert.isNumber(width, 'width');
|
|
99
|
+
assert.isNumber(resolution, 'resolution');
|
|
100
|
+
assert.isNumber(radial_resolution, 'radial_resolution');
|
|
101
|
+
assert.isBoolean(cast_shadow, 'cast_shadow');
|
|
102
|
+
assert.isBoolean(receive_shadow, 'receive_shadow');
|
|
103
|
+
|
|
104
|
+
assert.defined(path_mask, 'path_mask');
|
|
105
|
+
assert.notNull(path_mask, 'path_mask');
|
|
106
|
+
|
|
107
|
+
assert.greaterThanOrEqual(path_mask.length, 2, 'path_mask length bust be at least 2');
|
|
108
|
+
assert.ok(path_mask.length % 2 === 0, 'path_mask length bust be multiple of 2');
|
|
45
109
|
|
|
46
110
|
if (typeof color === 'string') {
|
|
47
111
|
this.color.parse(color);
|
|
@@ -55,6 +119,11 @@ export class TubePathStyle {
|
|
|
55
119
|
this.resolution = resolution;
|
|
56
120
|
this.radial_resolution = radial_resolution;
|
|
57
121
|
|
|
122
|
+
this.cast_shadow = cast_shadow;
|
|
123
|
+
this.receive_shadow = receive_shadow;
|
|
124
|
+
|
|
125
|
+
this.path_mask = path_mask;
|
|
126
|
+
|
|
58
127
|
switch (material_type) {
|
|
59
128
|
case TubeMaterialType.Matcap:
|
|
60
129
|
this.material = new MatcapMaterialDefinition();
|