@woosh/meep-engine 2.35.8 → 2.35.12
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 +8 -2
- 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 +13 -12
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +2 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +43 -1
- package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +138 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +32 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +16 -0
- package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +153 -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 +156 -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/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +1 -0
- 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
|
*
|
|
@@ -313,13 +313,19 @@ export class ShadedGeometrySystem extends System {
|
|
|
313
313
|
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
314
314
|
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
315
315
|
const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
|
|
316
|
-
|
|
316
|
+
|
|
317
|
+
const local_direction_magnitude = Math.hypot(local_direction_x, local_direction_y, local_direction_z);
|
|
318
|
+
const local_direction_magnitude_inverse = 1 / local_direction_magnitude;
|
|
319
|
+
|
|
320
|
+
const local_direction_normalized_x = local_direction_x * local_direction_magnitude_inverse;
|
|
321
|
+
const local_direction_normalized_y = local_direction_y * local_direction_magnitude_inverse;
|
|
322
|
+
const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
|
|
317
323
|
|
|
318
324
|
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_primitive(
|
|
319
325
|
scratch_point,
|
|
320
326
|
sg.geometry,
|
|
321
327
|
local_origin_x, local_origin_y, local_origin_z,
|
|
322
|
-
|
|
328
|
+
local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
|
|
323
329
|
);
|
|
324
330
|
|
|
325
331
|
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
|
|
|
@@ -323,8 +324,8 @@ function main(engine) {
|
|
|
323
324
|
EngineHarness.buildBasics({ engine });
|
|
324
325
|
|
|
325
326
|
const _p = new Path();
|
|
326
|
-
|
|
327
|
-
_p.interpolation = InterpolationType.Linear;
|
|
327
|
+
_p.interpolation = InterpolationType.CatmullRom;
|
|
328
|
+
// _p.interpolation = InterpolationType.Linear;
|
|
328
329
|
|
|
329
330
|
// _p.setPositionsFromVectorArray(Path.smoothPath([
|
|
330
331
|
// new Vector3(3, 1, 1),
|
|
@@ -352,14 +353,14 @@ function main(engine) {
|
|
|
352
353
|
|
|
353
354
|
const pathDisplay = new PathDisplay();
|
|
354
355
|
pathDisplay.specs.push(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
356
|
+
PathDisplaySpec.from(
|
|
357
|
+
PathDisplayType.Ribbon,
|
|
358
|
+
trailPathStyle
|
|
359
|
+
),
|
|
360
|
+
PathDisplaySpec.from(
|
|
361
|
+
PathDisplayType.Entity,
|
|
362
|
+
sample_style_entity()
|
|
363
|
+
),
|
|
363
364
|
PathDisplaySpec.from(
|
|
364
365
|
PathDisplayType.Tube,
|
|
365
366
|
sample_style_tube()
|
|
@@ -5,8 +5,15 @@ import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
|
5
5
|
|
|
6
6
|
export class TubePathStyle {
|
|
7
7
|
constructor() {
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @type {Color}
|
|
11
|
+
*/
|
|
8
12
|
this.color = new Color(1, 1, 1);
|
|
9
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @type {TubeMaterialType}
|
|
16
|
+
*/
|
|
10
17
|
this.material_type = TubeMaterialType.Unknown;
|
|
11
18
|
|
|
12
19
|
/**
|
|
@@ -15,13 +22,43 @@ export class TubePathStyle {
|
|
|
15
22
|
*/
|
|
16
23
|
this.material = null;
|
|
17
24
|
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @type {number}
|
|
28
|
+
*/
|
|
18
29
|
this.opacity = 1;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @type {number}
|
|
34
|
+
*/
|
|
19
35
|
this.width = 1;
|
|
20
36
|
|
|
21
37
|
// TODO expose shading style "flat/smooth"
|
|
22
38
|
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @type {number}
|
|
42
|
+
*/
|
|
23
43
|
this.resolution = 10;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @type {number}
|
|
48
|
+
*/
|
|
24
49
|
this.radial_resolution = 16;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @type {boolean}
|
|
54
|
+
*/
|
|
55
|
+
this.cast_shadow = false;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @type {boolean}
|
|
60
|
+
*/
|
|
61
|
+
this.receive_shadow = false;
|
|
25
62
|
}
|
|
26
63
|
|
|
27
64
|
static fromJSON(j) {
|
|
@@ -39,7 +76,9 @@ export class TubePathStyle {
|
|
|
39
76
|
opacity = 1,
|
|
40
77
|
width = 1,
|
|
41
78
|
resolution = 10,
|
|
42
|
-
radial_resolution = 16
|
|
79
|
+
radial_resolution = 16,
|
|
80
|
+
cast_shadow = false,
|
|
81
|
+
receive_shadow = false
|
|
43
82
|
}) {
|
|
44
83
|
assert.enum(material_type, TubeMaterialType, 'material_type');
|
|
45
84
|
|
|
@@ -55,6 +94,9 @@ export class TubePathStyle {
|
|
|
55
94
|
this.resolution = resolution;
|
|
56
95
|
this.radial_resolution = radial_resolution;
|
|
57
96
|
|
|
97
|
+
this.cast_shadow = cast_shadow;
|
|
98
|
+
this.receive_shadow = receive_shadow;
|
|
99
|
+
|
|
58
100
|
switch (material_type) {
|
|
59
101
|
case TubeMaterialType.Matcap:
|
|
60
102
|
this.material = new MatcapMaterialDefinition();
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { BufferGeometry, MeshMatcapMaterial, MeshStandardMaterial, Vector3 } from "three";
|
|
2
|
+
import { InterpolationType } from "../../../../../navigation/ecs/components/InterpolationType.js";
|
|
3
|
+
import EntityBuilder from "../../../../../ecs/EntityBuilder.js";
|
|
4
|
+
import { Transform } from "../../../../../ecs/transform/Transform.js";
|
|
5
|
+
import { TubeMaterialType } from "../TubeMaterialType.js";
|
|
6
|
+
import { GameAssetType } from "../../../../../asset/GameAssetType.js";
|
|
7
|
+
import { build_geometry_linear } from "./build_geometry_linear.js";
|
|
8
|
+
import { build_geometry_catmullrom } from "./build_geometry_catmullrom.js";
|
|
9
|
+
import { ShadedGeometry } from "../../../mesh-v2/ShadedGeometry.js";
|
|
10
|
+
import { ShadedGeometryFlags } from "../../../mesh-v2/ShadedGeometryFlags.js";
|
|
11
|
+
|
|
12
|
+
export class TubePathBuilder {
|
|
13
|
+
constructor() {
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @type {TubePathStyle|null}
|
|
17
|
+
*/
|
|
18
|
+
this.style = null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @type {Path|null}
|
|
23
|
+
*/
|
|
24
|
+
this.path = null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @type {MaterialManager|null}
|
|
29
|
+
*/
|
|
30
|
+
this.materials = null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @type {AssetManager|null}
|
|
35
|
+
*/
|
|
36
|
+
this.assetManager = null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setPath(path) {
|
|
40
|
+
this.path = path;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setStyle(style) {
|
|
44
|
+
this.style = style;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setMaterials(m) {
|
|
48
|
+
this.materials = m;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setAssetManager(assetManager) {
|
|
52
|
+
this.assetManager = assetManager;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @param {EntityBuilder[]} destination
|
|
58
|
+
*/
|
|
59
|
+
build(destination) {
|
|
60
|
+
const style = this.style;
|
|
61
|
+
|
|
62
|
+
// generate three.js curve from path
|
|
63
|
+
const path_component = this.path;
|
|
64
|
+
|
|
65
|
+
const three_points = [];
|
|
66
|
+
|
|
67
|
+
const pointCount = path_component.getPointCount();
|
|
68
|
+
|
|
69
|
+
if (pointCount < 2) {
|
|
70
|
+
// no curve possible without at least 2 points
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < pointCount; i++) {
|
|
75
|
+
const v3 = new Vector3();
|
|
76
|
+
|
|
77
|
+
path_component.getPosition(i, v3);
|
|
78
|
+
|
|
79
|
+
three_points.push(v3);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @type {THREE.BufferGeometry}
|
|
85
|
+
*/
|
|
86
|
+
let geometry;
|
|
87
|
+
|
|
88
|
+
if (path_component.interpolation === InterpolationType.Linear) {
|
|
89
|
+
geometry = build_geometry_linear(three_points, pointCount, style);
|
|
90
|
+
} else if (path_component.interpolation === InterpolationType.CatmullRom) {
|
|
91
|
+
geometry = build_geometry_catmullrom(three_points, pointCount, style);
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error(`Unsupported interpolation type '${path_component.interpolation}'`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
let material_def;
|
|
98
|
+
|
|
99
|
+
if (style.material_type === TubeMaterialType.Standard) {
|
|
100
|
+
material_def = new MeshStandardMaterial({
|
|
101
|
+
metalness: style.material.metalness,
|
|
102
|
+
roughness: style.material.roughness
|
|
103
|
+
});
|
|
104
|
+
} else if (style.material_type === TubeMaterialType.Matcap) {
|
|
105
|
+
|
|
106
|
+
material_def = new MeshMatcapMaterial();
|
|
107
|
+
|
|
108
|
+
this.assetManager.get(style.material.texture, GameAssetType.Texture, asset => {
|
|
109
|
+
material_def.matcap = asset.create();
|
|
110
|
+
|
|
111
|
+
material_def.needsUpdate = true;
|
|
112
|
+
}, console.error);
|
|
113
|
+
|
|
114
|
+
} else {
|
|
115
|
+
throw new Error(`Unsupported material type '${style.material_type}'`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
material_def.color.set(style.color.toUint());
|
|
119
|
+
|
|
120
|
+
if (style.opacity < 1) {
|
|
121
|
+
material_def.transparent = true;
|
|
122
|
+
material_def.opacity = style.opacity;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const entityBuilder = new EntityBuilder();
|
|
126
|
+
|
|
127
|
+
entityBuilder.add(new Transform());
|
|
128
|
+
|
|
129
|
+
const shaded_geometry = ShadedGeometry.from(geometry, material_def);
|
|
130
|
+
|
|
131
|
+
shaded_geometry.writeFlag(ShadedGeometryFlags.CastShadow, style.cast_shadow);
|
|
132
|
+
shaded_geometry.writeFlag(ShadedGeometryFlags.ReceiveShadow, style.receive_shadow);
|
|
133
|
+
|
|
134
|
+
entityBuilder.add(shaded_geometry);
|
|
135
|
+
|
|
136
|
+
destination.push(entityBuilder);
|
|
137
|
+
}
|
|
138
|
+
}
|