@woosh/meep-engine 2.35.14 → 2.35.17
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/collection/array/typed/uint_array_for_count.js +17 -0
- package/core/geom/3d/ray/ray3_array_apply_matrix4.js +42 -0
- package/core/geom/3d/ray/ray3_array_compose.js +19 -0
- package/core/geom/3d/ray/ray3_array_compose.spec.js +14 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +18 -24
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +2 -3
- package/engine/graphics/ecs/mesh-v2/sample/prototype_sg_raycast.js +212 -0
- package/engine/graphics/ecs/path/PathDisplaySystem.js +2 -1
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +8 -8
- package/engine/graphics/ecs/path/tube/CapType.d.ts +5 -0
- package/engine/graphics/ecs/path/tube/CapType.js +9 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +2 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +10 -1
- package/engine/graphics/ecs/path/tube/build/GeometryOutput.js +90 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +3 -2
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +1 -1
- package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +353 -91
- package/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +390 -0
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +16 -0
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +1 -18
- package/engine/graphics/micron/format/MicronGeometry.js +7 -4
- package/engine/graphics/micron/format/micron_build_proxy_geometry.js +203 -0
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +21 -0
- package/engine/graphics/micron/prototypeMicronProxyBuild.js +227 -0
- package/engine/graphics/util/composeMatrix4RotationScale.js +4 -27
- package/engine/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
- package/engine/navigation/grid/FastBinaryHeap.js +13 -2
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number} count
|
|
4
|
+
* @returns {function}
|
|
5
|
+
*/
|
|
6
|
+
export function UintArrayForCount(count) {
|
|
7
|
+
|
|
8
|
+
if (count <= 256) {
|
|
9
|
+
return Uint8Array;
|
|
10
|
+
} else if (count <= 65536) {
|
|
11
|
+
return Uint16Array;
|
|
12
|
+
} else if (count <= 4294967295) {
|
|
13
|
+
return Uint32Array;
|
|
14
|
+
} else {
|
|
15
|
+
throw new Error(`Unsupported size ${count}`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]|ArrayLike<number>|Float32Array} output 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
4
|
+
* @param {number[]|ArrayLike<number>|Float32Array} input 6 component vector, [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
|
|
5
|
+
* @param {number[]|ArrayLike<number>|Float32Array} m4 4x4 matrix
|
|
6
|
+
*/
|
|
7
|
+
export function ray3_array_apply_matrix4(output, input, m4) {
|
|
8
|
+
const origin_x = input[0];
|
|
9
|
+
const origin_y = input[1];
|
|
10
|
+
const origin_z = input[2];
|
|
11
|
+
|
|
12
|
+
const direction_x = input[3];
|
|
13
|
+
const direction_y = input[4];
|
|
14
|
+
const direction_z = input[5];
|
|
15
|
+
|
|
16
|
+
// transform ray to local space (inlined for speed)
|
|
17
|
+
const inv_w = 1 / (m4[3] * origin_x + m4[7] * origin_y + m4[11] * origin_z + m4[15]);
|
|
18
|
+
|
|
19
|
+
const out_origin_x = (m4[0] * origin_x + m4[4] * origin_y + m4[8] * origin_z + m4[12]) * inv_w;
|
|
20
|
+
const out_origin_y = (m4[1] * origin_x + m4[5] * origin_y + m4[9] * origin_z + m4[13]) * inv_w;
|
|
21
|
+
const out_origin_z = (m4[2] * origin_x + m4[6] * origin_y + m4[10] * origin_z + m4[14]) * inv_w;
|
|
22
|
+
|
|
23
|
+
const out_direction_x = m4[0] * direction_x + m4[4] * direction_y + m4[8] * direction_z;
|
|
24
|
+
const out_direction_y = m4[1] * direction_x + m4[5] * direction_y + m4[9] * direction_z;
|
|
25
|
+
const out_direction_z = m4[2] * direction_x + m4[6] * direction_y + m4[10] * direction_z;
|
|
26
|
+
|
|
27
|
+
// normalize direction
|
|
28
|
+
const out_direction_magnitude = Math.hypot(out_direction_x, out_direction_y, out_direction_z);
|
|
29
|
+
const out_direction_magnitude_inverse = 1 / out_direction_magnitude;
|
|
30
|
+
|
|
31
|
+
const out_direction_normalized_x = out_direction_x * out_direction_magnitude_inverse;
|
|
32
|
+
const out_direction_normalized_y = out_direction_y * out_direction_magnitude_inverse;
|
|
33
|
+
const out_direction_normalized_z = out_direction_z * out_direction_magnitude_inverse;
|
|
34
|
+
|
|
35
|
+
output[0] = out_origin_x;
|
|
36
|
+
output[1] = out_origin_y;
|
|
37
|
+
output[2] = out_origin_z;
|
|
38
|
+
|
|
39
|
+
output[3] = out_direction_normalized_x;
|
|
40
|
+
output[4] = out_direction_normalized_y;
|
|
41
|
+
output[5] = out_direction_normalized_z;
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]|ArrayLike<number>|Float32Array} output
|
|
4
|
+
* @param {number} origin_x
|
|
5
|
+
* @param {number} origin_y
|
|
6
|
+
* @param {number} origin_z
|
|
7
|
+
* @param {number} direction_x
|
|
8
|
+
* @param {number} direction_y
|
|
9
|
+
* @param {number} direction_z
|
|
10
|
+
*/
|
|
11
|
+
export function ray3_array_compose(output, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z) {
|
|
12
|
+
output[0] = origin_x;
|
|
13
|
+
output[1] = origin_y;
|
|
14
|
+
output[2] = origin_z;
|
|
15
|
+
|
|
16
|
+
output[3] = direction_x;
|
|
17
|
+
output[4] = direction_y;
|
|
18
|
+
output[5] = direction_z;
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ray3_array_compose } from "./ray3_array_compose.js";
|
|
2
|
+
|
|
3
|
+
test('correctness', () => {
|
|
4
|
+
const result = [];
|
|
5
|
+
ray3_array_compose(result, 1, -3, 7, -11, 13, -17);
|
|
6
|
+
|
|
7
|
+
expect(result[0]).toBe(1);
|
|
8
|
+
expect(result[1]).toBe(-3);
|
|
9
|
+
expect(result[2]).toBe(7);
|
|
10
|
+
|
|
11
|
+
expect(result[3]).toBe(-11);
|
|
12
|
+
expect(result[4]).toBe(13);
|
|
13
|
+
expect(result[5]).toBe(-17);
|
|
14
|
+
});
|
|
@@ -10,6 +10,8 @@ import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersec
|
|
|
10
10
|
import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
|
|
11
11
|
import { BinaryNode } from "../../../../core/bvh2/BinaryNode.js";
|
|
12
12
|
import { assert } from "../../../../core/assert.js";
|
|
13
|
+
import { ray3_array_compose } from "../../../../core/geom/3d/ray/ray3_array_compose.js";
|
|
14
|
+
import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
*
|
|
@@ -35,6 +37,9 @@ const scratch_point = new SurfacePoint3();
|
|
|
35
37
|
*/
|
|
36
38
|
const scratch_m4 = new Float32Array(16);
|
|
37
39
|
|
|
40
|
+
const scratch_ray_0 = new Float32Array(6);
|
|
41
|
+
const scratch_ray_1 = new Float32Array(6);
|
|
42
|
+
|
|
38
43
|
export class ShadedGeometrySystem extends System {
|
|
39
44
|
/**
|
|
40
45
|
*
|
|
@@ -332,29 +337,19 @@ export class ShadedGeometrySystem extends System {
|
|
|
332
337
|
// get transform in local space
|
|
333
338
|
mat4.invert(scratch_m4, m4);
|
|
334
339
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const local_origin_z = (scratch_m4[2] * origin_x + scratch_m4[6] * origin_y + scratch_m4[10] * origin_z + scratch_m4[14]) * inv_w;
|
|
341
|
-
|
|
342
|
-
const local_direction_x = scratch_m4[0] * direction_x + scratch_m4[4] * direction_y + scratch_m4[8] * direction_z;
|
|
343
|
-
const local_direction_y = scratch_m4[1] * direction_x + scratch_m4[5] * direction_y + scratch_m4[9] * direction_z;
|
|
344
|
-
const local_direction_z = scratch_m4[2] * direction_x + scratch_m4[6] * direction_y + scratch_m4[10] * direction_z;
|
|
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;
|
|
340
|
+
ray3_array_compose(
|
|
341
|
+
scratch_ray_0,
|
|
342
|
+
origin_x, origin_y, origin_z,
|
|
343
|
+
direction_x, direction_y, direction_z
|
|
344
|
+
);
|
|
348
345
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const local_direction_normalized_z = local_direction_z * local_direction_magnitude_inverse;
|
|
346
|
+
// transform ray to local space
|
|
347
|
+
ray3_array_apply_matrix4(scratch_ray_0, scratch_ray_0, scratch_m4);
|
|
352
348
|
|
|
353
|
-
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.
|
|
349
|
+
const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_array(
|
|
354
350
|
scratch_point,
|
|
355
351
|
sg.geometry,
|
|
356
|
-
|
|
357
|
-
local_direction_normalized_x, local_direction_normalized_y, local_direction_normalized_z
|
|
352
|
+
scratch_ray_0
|
|
358
353
|
);
|
|
359
354
|
|
|
360
355
|
if (!geometry_hit_found) {
|
|
@@ -373,13 +368,12 @@ export class ShadedGeometrySystem extends System {
|
|
|
373
368
|
origin_x, origin_y, origin_z
|
|
374
369
|
);
|
|
375
370
|
|
|
376
|
-
if (distance_sqr
|
|
377
|
-
|
|
378
|
-
|
|
371
|
+
if (distance_sqr < best_distance) {
|
|
372
|
+
contact.copy(scratch_point);
|
|
373
|
+
best_result = sg;
|
|
374
|
+
best_distance = distance_sqr;
|
|
379
375
|
}
|
|
380
376
|
|
|
381
|
-
contact.copy(scratch_point);
|
|
382
|
-
best_result = sg;
|
|
383
377
|
}
|
|
384
378
|
}
|
|
385
379
|
|
|
@@ -22,7 +22,6 @@ import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/Orb
|
|
|
22
22
|
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
23
23
|
import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
|
|
24
24
|
import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
|
|
25
|
-
import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
|
|
26
25
|
|
|
27
26
|
const eh = new EngineHarness();
|
|
28
27
|
|
|
@@ -102,8 +101,8 @@ async function main(engine) {
|
|
|
102
101
|
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
103
102
|
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
104
103
|
// sg.draw_method = 2;
|
|
105
|
-
sg.draw_method =
|
|
106
|
-
// sg.draw_method = random() > 0.
|
|
104
|
+
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
105
|
+
// sg.draw_method = random() > 0.5 ? DRAW_METHOD_INSTANCED : 2;
|
|
107
106
|
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
108
107
|
|
|
109
108
|
new EntityBuilder()
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
+
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
|
|
3
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.js";
|
|
4
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
5
|
+
import { ShadedGeometry } from "../ShadedGeometry.js";
|
|
6
|
+
import {
|
|
7
|
+
BoxBufferGeometry,
|
|
8
|
+
MeshBasicMaterial,
|
|
9
|
+
MeshStandardMaterial,
|
|
10
|
+
OctahedronGeometry,
|
|
11
|
+
SphereBufferGeometry
|
|
12
|
+
} from "three";
|
|
13
|
+
import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
|
|
14
|
+
import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
|
|
15
|
+
import ViewportPosition from "../../../../ecs/gui/position/ViewportPosition.js";
|
|
16
|
+
import GUIElement from "../../../../ecs/gui/GUIElement.js";
|
|
17
|
+
import ButtonView from "../../../../../view/elements/button/ButtonView.js";
|
|
18
|
+
import { downloadAsFile } from "../../../../../core/binary/ByteArrayTools.js";
|
|
19
|
+
import { convert_bvh_to_dot_format_string } from "../../../../../core/bvh2/visual/convert_bvh_to_dot_format_string.js";
|
|
20
|
+
import ViewportPositionSystem from "../../../../ecs/gui/position/ViewportPositionSystem.js";
|
|
21
|
+
import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
|
|
22
|
+
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
23
|
+
import Quaternion from "../../../../../core/geom/Quaternion.js";
|
|
24
|
+
import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
|
|
25
|
+
import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
|
|
26
|
+
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
27
|
+
import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
|
|
28
|
+
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
29
|
+
import { MicronShadedGeometryRenderAdapter } from "../../../micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js";
|
|
30
|
+
import { MicronRenderContext } from "../../../micron/render/v1/MicronRenderContext.js";
|
|
31
|
+
import { randomIntegerBetween } from "../../../../../core/math/random/randomIntegerBetween.js";
|
|
32
|
+
import Vector2 from "../../../../../core/geom/Vector2.js";
|
|
33
|
+
import { SurfacePoint3 } from "../../../../../core/geom/3d/SurfacePoint3.js";
|
|
34
|
+
|
|
35
|
+
const eh = new EngineHarness();
|
|
36
|
+
|
|
37
|
+
const DRAW_METHOD_PLAIN = 0;
|
|
38
|
+
const DRAW_METHOD_INSTANCED = 1;
|
|
39
|
+
|
|
40
|
+
function makeMovingShadedGeometry() {
|
|
41
|
+
const b = new OrbitingBehavior();
|
|
42
|
+
b.offset.set(4, 1, 4);
|
|
43
|
+
b.radius = 2;
|
|
44
|
+
b.rate = 1;
|
|
45
|
+
|
|
46
|
+
const sg = ShadedGeometry.from(new OctahedronGeometry(0.5, 5), new MeshStandardMaterial({ color: 0xFF0000 }));
|
|
47
|
+
|
|
48
|
+
sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
49
|
+
|
|
50
|
+
return new EntityBuilder()
|
|
51
|
+
.add(new Transform())
|
|
52
|
+
.add(sg)
|
|
53
|
+
.add(BehaviorComponent.fromOne(b));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {Engine} engine
|
|
59
|
+
*/
|
|
60
|
+
async function main(engine) {
|
|
61
|
+
|
|
62
|
+
const em = engine.entityManager;
|
|
63
|
+
|
|
64
|
+
const sgs = new ShadedGeometrySystem(engine);
|
|
65
|
+
|
|
66
|
+
const mrc = new MicronRenderContext();
|
|
67
|
+
sgs.register_render_adapter(2, () => {
|
|
68
|
+
const adapter = new MicronShadedGeometryRenderAdapter();
|
|
69
|
+
adapter.ctx = mrc;
|
|
70
|
+
|
|
71
|
+
return adapter;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await em.addSystem(sgs);
|
|
75
|
+
await em.addSystem(new BehaviorSystem(engine));
|
|
76
|
+
|
|
77
|
+
EngineHarness.buildBasics({
|
|
78
|
+
engine,
|
|
79
|
+
yaw: -0.8,
|
|
80
|
+
pitch: 1,
|
|
81
|
+
distance: 46,
|
|
82
|
+
focus: new Vector3(10, 0, 10)
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
const ecd = em.dataset;
|
|
87
|
+
|
|
88
|
+
const material = new MeshStandardMaterial({
|
|
89
|
+
color: 0xFFFFFF,
|
|
90
|
+
transparent: true,
|
|
91
|
+
opacity: 0.5
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// material.visible = false;
|
|
95
|
+
|
|
96
|
+
window.material = material;
|
|
97
|
+
|
|
98
|
+
const random = seededRandom(0);
|
|
99
|
+
|
|
100
|
+
const INSTANCE_COUNT = 100;
|
|
101
|
+
|
|
102
|
+
const geometries = [];
|
|
103
|
+
|
|
104
|
+
for (let i = 0; i < 1; i++) {
|
|
105
|
+
geometries.push(new BoxBufferGeometry());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (let i = 0; i < INSTANCE_COUNT; i++) {
|
|
109
|
+
const geometry = randomFromArray(random, geometries);
|
|
110
|
+
const sg = ShadedGeometry.from(geometry, material);
|
|
111
|
+
|
|
112
|
+
// sg.draw_method = DRAW_METHOD_PLAIN;
|
|
113
|
+
// sg.draw_method = DRAW_METHOD_INSTANCED;
|
|
114
|
+
// sg.draw_method = 2;
|
|
115
|
+
sg.draw_method = randomIntegerBetween(random, 0, 2);
|
|
116
|
+
// sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
|
|
117
|
+
sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
|
|
118
|
+
|
|
119
|
+
new EntityBuilder()
|
|
120
|
+
.add(Transform.fromJSON({
|
|
121
|
+
position: {
|
|
122
|
+
x: randomFloatBetween(random, 0, 20),
|
|
123
|
+
y: randomFloatBetween(random, 0, 10),
|
|
124
|
+
z: randomFloatBetween(random, 0, 20)
|
|
125
|
+
},
|
|
126
|
+
rotation: Quaternion.random(random),
|
|
127
|
+
scale: 1
|
|
128
|
+
}))
|
|
129
|
+
.add(sg)
|
|
130
|
+
.build(ecd);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// makeMovingShadedGeometry().build(ecd);
|
|
134
|
+
|
|
135
|
+
debug_button(engine, () => {
|
|
136
|
+
const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
|
|
137
|
+
downloadAsFile(dot, 'bvh.dot', 'text');
|
|
138
|
+
|
|
139
|
+
}, 'save dot file');
|
|
140
|
+
|
|
141
|
+
const raycast_marker = new EntityBuilder()
|
|
142
|
+
.add(ShadedGeometry.from(new SphereBufferGeometry(1), new MeshBasicMaterial({
|
|
143
|
+
color: 0xFF0000
|
|
144
|
+
})))
|
|
145
|
+
.add(Transform.fromJSON({
|
|
146
|
+
scale: 0.07
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
raycast_marker.build(engine.entityManager.dataset);
|
|
150
|
+
|
|
151
|
+
engine.devices.pointer.position.onChanged.add((p_x, p_y) => {
|
|
152
|
+
const p = new Vector2(p_x, p_y);
|
|
153
|
+
const ndc = new Vector2();
|
|
154
|
+
const ray_origin = new Vector3();
|
|
155
|
+
const ray_direction = new Vector3();
|
|
156
|
+
|
|
157
|
+
engine.graphics.normalizeViewportPoint(p, ndc);
|
|
158
|
+
engine.graphics.viewportProjectionRay(ndc.x, ndc.y, ray_origin, ray_direction);
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* @type {ShadedGeometrySystem}
|
|
163
|
+
*/
|
|
164
|
+
const sgm = engine.entityManager.getSystem(ShadedGeometrySystem);
|
|
165
|
+
|
|
166
|
+
const sp = new SurfacePoint3();
|
|
167
|
+
|
|
168
|
+
sgm.raycastNearest(sp, ray_origin.x, ray_origin.y, ray_origin.z, ray_direction.x, ray_direction.y, ray_direction.z, ((entity, mesh) => {
|
|
169
|
+
return (entity !== raycast_marker.entity);
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
const t = raycast_marker.getComponent(Transform);
|
|
173
|
+
|
|
174
|
+
t.position.copy(sp.position);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
const entityManager = engine.entityManager;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
*
|
|
183
|
+
* @param {Engine} engine
|
|
184
|
+
* @param {function} action
|
|
185
|
+
* @param {string} [name]
|
|
186
|
+
* @param {EntityComponentDataset} ecd
|
|
187
|
+
*/
|
|
188
|
+
function debug_button(engine, action, name = "Button", ecd = entityManager.dataset) {
|
|
189
|
+
if (entityManager.getSystem(ViewportPositionSystem) === null) {
|
|
190
|
+
entityManager.addSystem(new ViewportPositionSystem(engine.graphics.viewport.size));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (entityManager.getSystem(GUIElementSystem) === null) {
|
|
194
|
+
entityManager.addSystem(new GUIElementSystem(engine.gui.view, engine));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
new EntityBuilder()
|
|
198
|
+
.add(ViewportPosition.fromJSON({}))
|
|
199
|
+
.add(GUIElement.fromView(new ButtonView({
|
|
200
|
+
action,
|
|
201
|
+
name,
|
|
202
|
+
css: {
|
|
203
|
+
background: 'rgba(255,255,255,0.8)',
|
|
204
|
+
border: '1px solid black',
|
|
205
|
+
borderRadius: '4px',
|
|
206
|
+
padding: '2px',
|
|
207
|
+
}
|
|
208
|
+
})))
|
|
209
|
+
.build(ecd);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
eh.initialize().then(main);
|
|
@@ -125,7 +125,8 @@ class PathDisplayContext extends SystemEntityContext {
|
|
|
125
125
|
try {
|
|
126
126
|
builder(spec.style, path, this.system, ownedEntities);
|
|
127
127
|
} catch (e) {
|
|
128
|
-
console.error(`Failed to build path of type '${spec.type}'
|
|
128
|
+
console.error(`Failed to build path of type '${spec.type}'`);
|
|
129
|
+
console.error(e);
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
|
|
@@ -359,14 +359,14 @@ function main(engine) {
|
|
|
359
359
|
|
|
360
360
|
const pathDisplay = new PathDisplay();
|
|
361
361
|
pathDisplay.specs.push(
|
|
362
|
-
PathDisplaySpec.from(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
),
|
|
366
|
-
PathDisplaySpec.from(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
),
|
|
362
|
+
// PathDisplaySpec.from(
|
|
363
|
+
// PathDisplayType.Ribbon,
|
|
364
|
+
// trailPathStyle
|
|
365
|
+
// ),
|
|
366
|
+
// PathDisplaySpec.from(
|
|
367
|
+
// PathDisplayType.Entity,
|
|
368
|
+
// sample_style_entity()
|
|
369
|
+
// ),
|
|
370
370
|
PathDisplaySpec.from(
|
|
371
371
|
PathDisplayType.Tube,
|
|
372
372
|
sample_style_tube()
|
|
@@ -2,6 +2,7 @@ import {Color} from "../../../../../core/color/Color";
|
|
|
2
2
|
import {TubeMaterialType} from "./TubeMaterialType";
|
|
3
3
|
import {StandardMaterialDefinition} from "./StandardMaterialDefinition";
|
|
4
4
|
import {MatcapMaterialDefinition} from "./MatcapMaterialDefinition";
|
|
5
|
+
import {CapType} from "./CapType";
|
|
5
6
|
|
|
6
7
|
export class TubePathStyle {
|
|
7
8
|
public color: Color
|
|
@@ -14,4 +15,5 @@ export class TubePathStyle {
|
|
|
14
15
|
public cast_shadow: boolean
|
|
15
16
|
public receive_shadow: boolean
|
|
16
17
|
public path_mask: number[]
|
|
18
|
+
public cap_type: CapType
|
|
17
19
|
}
|
|
@@ -2,6 +2,7 @@ import { Color } from "../../../../../core/color/Color.js";
|
|
|
2
2
|
import { TubeMaterialType } from "./TubeMaterialType.js";
|
|
3
3
|
import { assert } from "../../../../../core/assert.js";
|
|
4
4
|
import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
5
|
+
import { CapType } from "./CapType.js";
|
|
5
6
|
|
|
6
7
|
const DEFAULT_COLOR = Object.freeze({ r: 1, g: 1, b: 1 });
|
|
7
8
|
|
|
@@ -71,6 +72,11 @@ export class TubePathStyle {
|
|
|
71
72
|
* @type {number[]}
|
|
72
73
|
*/
|
|
73
74
|
this.path_mask = [0, 1];
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @type {CapType}
|
|
78
|
+
*/
|
|
79
|
+
this.cap_type = CapType.Flat;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
static fromJSON(j) {
|
|
@@ -91,7 +97,8 @@ export class TubePathStyle {
|
|
|
91
97
|
radial_resolution = 16,
|
|
92
98
|
cast_shadow = false,
|
|
93
99
|
receive_shadow = false,
|
|
94
|
-
path_mask = [0, 1]
|
|
100
|
+
path_mask = [0, 1],
|
|
101
|
+
cap_type = CapType.None
|
|
95
102
|
}) {
|
|
96
103
|
assert.enum(material_type, TubeMaterialType, 'material_type');
|
|
97
104
|
assert.isNumber(opacity, 'opacity');
|
|
@@ -106,6 +113,7 @@ export class TubePathStyle {
|
|
|
106
113
|
|
|
107
114
|
assert.greaterThanOrEqual(path_mask.length, 2, 'path_mask length bust be at least 2');
|
|
108
115
|
assert.ok(path_mask.length % 2 === 0, 'path_mask length bust be multiple of 2');
|
|
116
|
+
assert.enum(cap_type, CapType, 'cap_type');
|
|
109
117
|
|
|
110
118
|
if (typeof color === 'string') {
|
|
111
119
|
this.color.parse(color);
|
|
@@ -123,6 +131,7 @@ export class TubePathStyle {
|
|
|
123
131
|
this.receive_shadow = receive_shadow;
|
|
124
132
|
|
|
125
133
|
this.path_mask = path_mask;
|
|
134
|
+
this.cap_type = cap_type;
|
|
126
135
|
|
|
127
136
|
switch (material_type) {
|
|
128
137
|
case TubeMaterialType.Matcap:
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { UintArrayForCount } from "../../../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
2
|
+
import { BufferAttribute, BufferGeometry } from "three";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Helper class, allowing us to treat geometry build process as a stream without having to create intermediate arrays and performing unnecessary copying
|
|
6
|
+
*/
|
|
7
|
+
export class GeometryOutput {
|
|
8
|
+
constructor() {
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @type {number}
|
|
12
|
+
*/
|
|
13
|
+
this.cursor_vertices = 0;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
this.cursor_indices = 0;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @type {Float32Array|number[]|null}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
this.__vertex_positions = null;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @type {Float32Array|number[]|null}
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
this.__vertex_normals = null;
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @type {Float32Array|number[]|null}
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
this.__vertex_uvs = null;
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @type {Uint8Array|Uint16Array|Uint32Array|number[]|null}
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
this.__indices = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get positions() {
|
|
48
|
+
return this.__vertex_positions;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get normals() {
|
|
52
|
+
return this.__vertex_normals;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get uvs() {
|
|
56
|
+
return this.__vertex_uvs;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get indices() {
|
|
60
|
+
return this.__indices;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param {number} vertex_count
|
|
66
|
+
* @param {number} polygon_count
|
|
67
|
+
*/
|
|
68
|
+
allocate(vertex_count, polygon_count) {
|
|
69
|
+
this.__vertex_positions = new Float32Array(vertex_count * 3);
|
|
70
|
+
this.__vertex_normals = new Float32Array(vertex_count * 3);
|
|
71
|
+
this.__vertex_uvs = new Float32Array(vertex_count * 2);
|
|
72
|
+
|
|
73
|
+
const INDEX_BUFFER_CLASS = UintArrayForCount(vertex_count);
|
|
74
|
+
this.__indices = new INDEX_BUFFER_CLASS(polygon_count * 3);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @returns {THREE.BufferGeometry}
|
|
79
|
+
*/
|
|
80
|
+
build() {
|
|
81
|
+
const geometry = new BufferGeometry();
|
|
82
|
+
|
|
83
|
+
geometry.setIndex(new BufferAttribute(this.__indices, 1));
|
|
84
|
+
geometry.setAttribute('position', new BufferAttribute(this.__vertex_positions, 3));
|
|
85
|
+
geometry.setAttribute('normal', new BufferAttribute(this.__vertex_normals, 3));
|
|
86
|
+
geometry.setAttribute('uv', new BufferAttribute(this.__vertex_uvs, 2));
|
|
87
|
+
|
|
88
|
+
return geometry;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -36,6 +36,7 @@ export function build_geometry_catmullrom(path, style, segment_start, segment_en
|
|
|
36
36
|
|
|
37
37
|
const max_i = segment_end * (total_points - 1);
|
|
38
38
|
for (i = Math.ceil(segment_start * total_points + 0.0001); i < max_i; i++) {
|
|
39
|
+
// TODO initial i value can potentially result in sample being produced before the "segment start"
|
|
39
40
|
const t = i / (total_points - 1);
|
|
40
41
|
|
|
41
42
|
path.sample_catmull_rom(point, path_length * t);
|
|
@@ -45,7 +46,7 @@ export function build_geometry_catmullrom(path, style, segment_start, segment_en
|
|
|
45
46
|
added_points++
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
if (((i - 1) / (total_points - 1))
|
|
49
|
+
if (segment_end - ((i - 1) / (total_points - 1)) > 0.0001) {
|
|
49
50
|
// end
|
|
50
51
|
|
|
51
52
|
path.sample_catmull_rom(point, segment_end * path_length);
|
|
@@ -57,5 +58,5 @@ export function build_geometry_catmullrom(path, style, segment_start, segment_en
|
|
|
57
58
|
|
|
58
59
|
const frames = computeFrenetFrames(points_f32, false);
|
|
59
60
|
|
|
60
|
-
return makeTubeGeometry(points_f32, frames.normals, frames.binormals, style.width, style.radial_resolution, false);
|
|
61
|
+
return makeTubeGeometry(points_f32, frames.normals, frames.binormals, style.width, style.radial_resolution, false, style.cap_type);
|
|
61
62
|
}
|
|
@@ -52,5 +52,5 @@ export function build_geometry_linear(path, style, segment_start, segment_end) {
|
|
|
52
52
|
|
|
53
53
|
const frames = computeFrenetFrames(points, false);
|
|
54
54
|
|
|
55
|
-
return makeTubeGeometry(points, frames.normals, frames.binormals, style.width, style.radial_resolution, false);
|
|
55
|
+
return makeTubeGeometry(points, frames.normals, frames.binormals, style.width, style.radial_resolution, false, style.cap_type);
|
|
56
56
|
}
|