@woosh/meep-engine 2.35.16 → 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/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +2 -3
- 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/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
- package/package.json +1 -1
|
@@ -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()
|
|
@@ -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
|
}
|
|
@@ -1,161 +1,423 @@
|
|
|
1
|
-
import { BufferGeometry,
|
|
1
|
+
import { BufferGeometry, Vector3 } from "three";
|
|
2
|
+
import { GeometryOutput } from "./GeometryOutput.js";
|
|
3
|
+
import { CapType } from "../CapType.js";
|
|
4
|
+
import { max2 } from "../../../../../../core/math/max2.js";
|
|
5
|
+
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {
|
|
8
|
+
*
|
|
9
|
+
* @param {GeometryOutput} out
|
|
10
|
+
* @param {number} Px
|
|
11
|
+
* @param {number} Py
|
|
12
|
+
* @param {number} Pz
|
|
13
|
+
* @param {Vector3} N normal
|
|
14
|
+
* @param {Vector3} B binormal
|
|
15
|
+
* @param {number} u X component of UV
|
|
8
16
|
* @param {number} radius
|
|
9
|
-
* @param {number}
|
|
10
|
-
* @param {
|
|
11
|
-
* @returns {BufferGeometry}
|
|
17
|
+
* @param {number} angular_step
|
|
18
|
+
* @param {number} radial_segments
|
|
12
19
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
function make_ring_vertices(
|
|
21
|
+
out,
|
|
22
|
+
Px, Py, Pz,
|
|
23
|
+
N, B,
|
|
24
|
+
u,
|
|
25
|
+
radius, angular_step, radial_segments
|
|
26
|
+
) {
|
|
27
|
+
const out_positions = out.positions;
|
|
28
|
+
const out_normals = out.normals;
|
|
29
|
+
const out_uvs = out.uvs;
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
for (let j = 0; j <= radial_segments; j++) {
|
|
32
|
+
const angle = j * angular_step;
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
const sin = Math.sin(angle);
|
|
35
|
+
const cos = -Math.cos(angle);
|
|
21
36
|
|
|
22
|
-
|
|
23
|
-
const normals = [];
|
|
24
|
-
const uvs = [];
|
|
25
|
-
const indices = [];
|
|
37
|
+
// normal
|
|
26
38
|
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
const normal_x_r = (cos * N.x + sin * B.x);
|
|
40
|
+
const normal_y_r = (cos * N.y + sin * B.y);
|
|
41
|
+
const normal_z_r = (cos * N.z + sin * B.z);
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
const normal_length = 1 / Math.hypot(normal_x_r, normal_y_r, normal_z_r);
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
const normal_x = normal_x_r * normal_length;
|
|
46
|
+
const normal_y = normal_y_r * normal_length;
|
|
47
|
+
const normal_z = normal_z_r * normal_length;
|
|
33
48
|
|
|
34
|
-
|
|
49
|
+
const cv = out.cursor_vertices;
|
|
50
|
+
const cv3 = cv * 3;
|
|
35
51
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
geometry.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
|
|
52
|
+
out_normals[cv3] = normal_x;
|
|
53
|
+
out_normals[cv3 + 1] = normal_y;
|
|
54
|
+
out_normals[cv3 + 2] = normal_z;
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
// position
|
|
42
57
|
|
|
43
|
-
|
|
58
|
+
const vx = Px + radius * normal_x;
|
|
59
|
+
const vy = Py + radius * normal_y;
|
|
60
|
+
const vz = Pz + radius * normal_z;
|
|
44
61
|
|
|
45
|
-
|
|
62
|
+
out_positions[cv3] = vx;
|
|
63
|
+
out_positions[cv3 + 1] = vy;
|
|
64
|
+
out_positions[cv3 + 2] = vz;
|
|
46
65
|
|
|
47
|
-
|
|
66
|
+
// UV
|
|
67
|
+
const v = j / radial_segments;
|
|
68
|
+
|
|
69
|
+
const cv2 = cv * 2;
|
|
70
|
+
|
|
71
|
+
out_uvs[cv2] = u;
|
|
72
|
+
out_uvs[cv2 + 1] = v;
|
|
73
|
+
|
|
74
|
+
out.cursor_vertices++;
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {GeometryOutput} out
|
|
82
|
+
* @param {number} index_offset
|
|
83
|
+
* @param {number} tubular_segments
|
|
84
|
+
* @param {number} radial_segments
|
|
85
|
+
*/
|
|
86
|
+
function make_ring_faces(out, index_offset, tubular_segments, radial_segments) {
|
|
87
|
+
const indices = out.indices;
|
|
88
|
+
|
|
89
|
+
let i = 0, j = 0;
|
|
90
|
+
|
|
91
|
+
for (j = 1; j <= tubular_segments; j++) {
|
|
92
|
+
|
|
93
|
+
for (i = 1; i <= radial_segments; i++) {
|
|
94
|
+
|
|
95
|
+
const s_1 = radial_segments + 1;
|
|
96
|
+
|
|
97
|
+
const a = index_offset + s_1 * (j - 1) + (i - 1);
|
|
98
|
+
const b = index_offset + s_1 * j + (i - 1);
|
|
99
|
+
const c = index_offset + s_1 * j + i;
|
|
100
|
+
const d = index_offset + s_1 * (j - 1) + i;
|
|
101
|
+
|
|
102
|
+
// faces
|
|
103
|
+
|
|
104
|
+
const ci = out.cursor_indices;
|
|
105
|
+
|
|
106
|
+
indices[ci] = a;
|
|
107
|
+
indices[ci + 1] = b;
|
|
108
|
+
indices[ci + 2] = d;
|
|
48
109
|
|
|
110
|
+
indices[ci + 3] = b;
|
|
111
|
+
indices[ci + 4] = c;
|
|
112
|
+
indices[ci + 5] = d;
|
|
113
|
+
|
|
114
|
+
out.cursor_indices += 6;
|
|
49
115
|
}
|
|
50
116
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
*
|
|
122
|
+
* @param {number} radial_segments
|
|
123
|
+
* @returns {number}
|
|
124
|
+
*/
|
|
125
|
+
function compute_cap_round_segment_count(radial_segments) {
|
|
126
|
+
return max2(3, Math.ceil(radial_segments / 4));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
* @param {number} index
|
|
132
|
+
* @param {Float32Array|number[]} in_positions
|
|
133
|
+
* @param {Vector3[]} in_normals
|
|
134
|
+
* @param {Vector3[]} in_binormals
|
|
135
|
+
* @param {GeometryOutput} out
|
|
136
|
+
* @param {number} radius
|
|
137
|
+
* @param {number} radial_segments
|
|
138
|
+
* @param {number} direction
|
|
139
|
+
*/
|
|
140
|
+
function make_cap_round(
|
|
141
|
+
out,
|
|
142
|
+
index,
|
|
143
|
+
in_positions, in_normals, in_binormals,
|
|
144
|
+
radius, radial_segments, direction
|
|
145
|
+
) {
|
|
146
|
+
// how many radial segments will be placed laterally to make up the cap
|
|
147
|
+
const cap_segment_count = compute_cap_round_segment_count(radial_segments);
|
|
55
148
|
|
|
56
|
-
|
|
149
|
+
const i3 = index * 3;
|
|
57
150
|
|
|
58
|
-
|
|
59
|
-
|
|
151
|
+
const Px = in_positions[i3];
|
|
152
|
+
const Py = in_positions[i3 + 1];
|
|
153
|
+
const Pz = in_positions[i3 + 2];
|
|
60
154
|
|
|
61
|
-
|
|
155
|
+
// retrieve corresponding normal and binormal
|
|
62
156
|
|
|
63
|
-
|
|
157
|
+
const N = in_normals[index];
|
|
158
|
+
const B = in_binormals[index];
|
|
159
|
+
|
|
160
|
+
const tangent = new Vector3();
|
|
161
|
+
tangent.crossVectors(N, B);
|
|
162
|
+
tangent.normalize();
|
|
163
|
+
|
|
164
|
+
const normal = direction > 0 ? N : N.clone().negate();
|
|
165
|
+
|
|
166
|
+
const angular_step_i = (Math.PI / 2) / cap_segment_count;
|
|
167
|
+
const angular_step_j = (Math.PI * 2) / radial_segments;
|
|
168
|
+
|
|
169
|
+
const uv_u = index / (in_positions.length / 3 - 1);
|
|
170
|
+
let i, j;
|
|
64
171
|
|
|
65
|
-
|
|
172
|
+
const index_offset = out.cursor_vertices;
|
|
66
173
|
|
|
174
|
+
for (i = 0; i <= cap_segment_count; i++) {
|
|
175
|
+
const angle_b = i * angular_step_i;
|
|
176
|
+
|
|
177
|
+
const sin_b = Math.sin(angle_b);
|
|
178
|
+
const cos_b = Math.cos(angle_b);
|
|
179
|
+
|
|
180
|
+
const cap_ring_radius = sin_b * radius;
|
|
181
|
+
|
|
182
|
+
const _d = -radius * direction;
|
|
183
|
+
|
|
184
|
+
const _px = Px + tangent.x * cos_b * _d;
|
|
185
|
+
const _py = Py + tangent.y * cos_b * _d;
|
|
186
|
+
const _pz = Pz + tangent.z * cos_b * _d;
|
|
187
|
+
|
|
188
|
+
make_ring_vertices(
|
|
189
|
+
out,
|
|
190
|
+
_px, _py, _pz,
|
|
191
|
+
normal, B, uv_u,
|
|
192
|
+
cap_ring_radius, angular_step_j, radial_segments
|
|
193
|
+
);
|
|
67
194
|
}
|
|
68
195
|
|
|
69
|
-
|
|
196
|
+
make_ring_faces(out, index_offset, cap_segment_count, radial_segments);
|
|
197
|
+
}
|
|
70
198
|
|
|
71
|
-
|
|
199
|
+
/**
|
|
200
|
+
*
|
|
201
|
+
* @param {number} index
|
|
202
|
+
* @param {Float32Array|number[]} in_positions
|
|
203
|
+
* @param {Vector3[]} in_normals
|
|
204
|
+
* @param {Vector3[]} in_binormals
|
|
205
|
+
* @param {GeometryOutput} out
|
|
206
|
+
* @param {number} radius
|
|
207
|
+
* @param {number} radial_segments
|
|
208
|
+
* @param {number} direction
|
|
209
|
+
*/
|
|
210
|
+
function make_cap_flat(
|
|
211
|
+
out,
|
|
212
|
+
index,
|
|
213
|
+
in_positions, in_normals, in_binormals,
|
|
214
|
+
radius, radial_segments, direction
|
|
215
|
+
) {
|
|
216
|
+
// how many radial segments will be placed laterally to make up the cap
|
|
217
|
+
const i3 = index * 3;
|
|
72
218
|
|
|
73
|
-
|
|
219
|
+
const Px = in_positions[i3];
|
|
220
|
+
const Py = in_positions[i3 + 1];
|
|
221
|
+
const Pz = in_positions[i3 + 2];
|
|
74
222
|
|
|
75
|
-
|
|
76
|
-
const Py = points[i3 + 1];
|
|
77
|
-
const Pz = points[i3 + 2];
|
|
223
|
+
// retrieve corresponding normal and binormal
|
|
78
224
|
|
|
79
|
-
|
|
225
|
+
const N = in_normals[index];
|
|
226
|
+
const B = in_binormals[index];
|
|
80
227
|
|
|
81
|
-
|
|
82
|
-
|
|
228
|
+
const tangent = new Vector3();
|
|
229
|
+
tangent.crossVectors(N, B);
|
|
230
|
+
tangent.normalize();
|
|
83
231
|
|
|
84
|
-
|
|
232
|
+
const normal = direction > 0 ? N.clone().negate() : N;
|
|
233
|
+
|
|
234
|
+
const angular_step_j = (Math.PI * 2) / radial_segments;
|
|
85
235
|
|
|
86
|
-
|
|
236
|
+
const uv_u = index / (in_positions.length / 3 - 1);
|
|
87
237
|
|
|
88
|
-
|
|
89
|
-
const v = j * angular_step;
|
|
238
|
+
const index_offset = out.cursor_vertices;
|
|
90
239
|
|
|
91
|
-
|
|
92
|
-
|
|
240
|
+
make_ring_vertices(
|
|
241
|
+
out,
|
|
242
|
+
Px, Py, Pz,
|
|
243
|
+
normal, B, uv_u,
|
|
244
|
+
radius, angular_step_j, radial_segments
|
|
245
|
+
);
|
|
93
246
|
|
|
94
|
-
|
|
247
|
+
make_ring_vertices(
|
|
248
|
+
out,
|
|
249
|
+
Px, Py, Pz,
|
|
250
|
+
normal, B, uv_u,
|
|
251
|
+
0, angular_step_j, radial_segments
|
|
252
|
+
);
|
|
95
253
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
normal.z = (cos * N.z + sin * B.z);
|
|
99
|
-
normal.normalize();
|
|
254
|
+
make_ring_faces(out, index_offset, 1, radial_segments);
|
|
255
|
+
}
|
|
100
256
|
|
|
101
|
-
|
|
257
|
+
/**
|
|
258
|
+
*
|
|
259
|
+
* @param {number} index
|
|
260
|
+
* @param {Float32Array|number[]} in_positions
|
|
261
|
+
* @param {Vector3[]} in_normals
|
|
262
|
+
* @param {Vector3[]} in_binormals
|
|
263
|
+
* @param {GeometryOutput} out
|
|
264
|
+
* @param {number} radius
|
|
265
|
+
* @param {number} radial_segments
|
|
266
|
+
* @param {number} direction
|
|
267
|
+
* @param {CapType} type
|
|
268
|
+
*/
|
|
269
|
+
function make_cap(
|
|
270
|
+
out,
|
|
271
|
+
index,
|
|
272
|
+
in_positions, in_normals, in_binormals,
|
|
273
|
+
radius, radial_segments, direction, type
|
|
274
|
+
) {
|
|
275
|
+
if (type === CapType.None) {
|
|
276
|
+
// do nothing
|
|
277
|
+
} else if (type === CapType.Round) {
|
|
278
|
+
make_cap_round(
|
|
279
|
+
out,
|
|
280
|
+
index,
|
|
281
|
+
in_positions, in_normals, in_binormals,
|
|
282
|
+
radius, radial_segments,
|
|
283
|
+
direction
|
|
284
|
+
);
|
|
285
|
+
} else if (type === CapType.Flat) {
|
|
286
|
+
make_cap_flat(
|
|
287
|
+
out,
|
|
288
|
+
index,
|
|
289
|
+
in_positions, in_normals, in_binormals,
|
|
290
|
+
radius, radial_segments,
|
|
291
|
+
direction
|
|
292
|
+
);
|
|
293
|
+
} else {
|
|
294
|
+
throw new Error(`Unsupported cap type '${type}'`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
102
297
|
|
|
103
|
-
|
|
298
|
+
/**
|
|
299
|
+
*
|
|
300
|
+
* @param {number} count how many caps
|
|
301
|
+
* @param {{polygon_count:number, vertex_count:number}} out
|
|
302
|
+
* @param {number} radial_segments
|
|
303
|
+
* @param {CapType} type
|
|
304
|
+
*/
|
|
305
|
+
function compute_cap_geometry_size(count, out, radial_segments, type) {
|
|
306
|
+
|
|
307
|
+
if (type === CapType.None) {
|
|
308
|
+
// do nothing
|
|
309
|
+
} else if (type === CapType.Round) {
|
|
310
|
+
const cap_segment_count = compute_cap_round_segment_count(radial_segments);
|
|
311
|
+
|
|
312
|
+
out.vertex_count += count * (cap_segment_count + 1) * (radial_segments + 1);
|
|
313
|
+
out.polygon_count += count * cap_segment_count * (radial_segments) * 2;
|
|
314
|
+
} else if (type === CapType.Flat) {
|
|
315
|
+
out.vertex_count += count * (2) * (radial_segments + 1);
|
|
316
|
+
out.polygon_count += count * (radial_segments) * 2;
|
|
317
|
+
} else {
|
|
318
|
+
throw new Error(`Unsupported cap type '${type}'`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
104
321
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
322
|
+
/**
|
|
323
|
+
* @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
|
|
324
|
+
* @param {Float32Array|number[]} in_positions
|
|
325
|
+
* @param {Vector3[]} in_normals
|
|
326
|
+
* @param {Vector3[]} in_binormals
|
|
327
|
+
* @param {number} radius
|
|
328
|
+
* @param {number} radial_segments
|
|
329
|
+
* @param {boolean} [closed]
|
|
330
|
+
* @param {CapType} [cap_type]
|
|
331
|
+
* @returns {BufferGeometry}
|
|
332
|
+
*/
|
|
333
|
+
export function makeTubeGeometry(in_positions, in_normals, in_binormals, radius, radial_segments, closed = false, cap_type = CapType.Round) {
|
|
108
334
|
|
|
109
|
-
|
|
335
|
+
const out = new GeometryOutput();
|
|
110
336
|
|
|
111
|
-
|
|
337
|
+
// helper variables
|
|
338
|
+
|
|
339
|
+
const point_count = in_positions.length / 3;
|
|
340
|
+
const tubular_segments = point_count - 1;
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
const geometry_size = {
|
|
344
|
+
vertex_count: (tubular_segments + 1) * (radial_segments + 1),
|
|
345
|
+
polygon_count: tubular_segments * radial_segments * 2
|
|
346
|
+
};
|
|
112
347
|
|
|
348
|
+
if (!closed) {
|
|
349
|
+
compute_cap_geometry_size(2, geometry_size, radial_segments, cap_type);
|
|
113
350
|
}
|
|
114
351
|
|
|
115
|
-
|
|
116
|
-
|
|
352
|
+
out.allocate(
|
|
353
|
+
geometry_size.vertex_count,
|
|
354
|
+
geometry_size.polygon_count
|
|
355
|
+
);
|
|
117
356
|
|
|
118
|
-
|
|
357
|
+
// create buffer data
|
|
358
|
+
if (!closed) {
|
|
359
|
+
// start cap
|
|
360
|
+
make_cap(out, 0, in_positions, in_normals, in_binormals, radius, radial_segments, 1, cap_type);
|
|
361
|
+
}
|
|
119
362
|
|
|
120
|
-
|
|
363
|
+
generateBufferData();
|
|
121
364
|
|
|
122
|
-
|
|
365
|
+
if (!closed) {
|
|
366
|
+
// end cap
|
|
367
|
+
make_cap(out, point_count - 1, in_positions, in_normals, in_binormals, radius, radial_segments, -1, cap_type);
|
|
368
|
+
}
|
|
123
369
|
|
|
124
|
-
|
|
125
|
-
const b = s_1 * j + (i - 1);
|
|
126
|
-
const c = s_1 * j + i;
|
|
127
|
-
const d = s_1 * (j - 1) + i;
|
|
370
|
+
// functions
|
|
128
371
|
|
|
129
|
-
|
|
372
|
+
function generateBufferData() {
|
|
373
|
+
const index_offset = out.cursor_vertices;
|
|
130
374
|
|
|
131
|
-
|
|
132
|
-
indices.push(b, c, d);
|
|
375
|
+
for (let i = 0; i < tubular_segments; i++) {
|
|
133
376
|
|
|
134
|
-
|
|
377
|
+
generateSegment(i);
|
|
135
378
|
|
|
136
379
|
}
|
|
137
380
|
|
|
381
|
+
// if the geometry is not closed, generate the last row of vertices and normals
|
|
382
|
+
// at the regular position on the given path
|
|
383
|
+
//
|
|
384
|
+
// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
|
|
385
|
+
|
|
386
|
+
generateSegment((closed === false) ? tubular_segments : 0);
|
|
387
|
+
|
|
388
|
+
// finally create faces
|
|
389
|
+
make_ring_faces(out, index_offset, tubular_segments, radial_segments);
|
|
390
|
+
|
|
138
391
|
}
|
|
139
392
|
|
|
140
|
-
function
|
|
141
|
-
let i = 0, j = 0;
|
|
393
|
+
function generateSegment(i) {
|
|
142
394
|
|
|
143
|
-
|
|
395
|
+
// we use getPointAt to sample evenly distributed points from the given path
|
|
396
|
+
|
|
397
|
+
const i3 = i * 3;
|
|
144
398
|
|
|
145
|
-
|
|
399
|
+
const Px = in_positions[i3];
|
|
400
|
+
const Py = in_positions[i3 + 1];
|
|
401
|
+
const Pz = in_positions[i3 + 2];
|
|
146
402
|
|
|
147
|
-
|
|
403
|
+
// retrieve corresponding normal and binormal
|
|
148
404
|
|
|
149
|
-
|
|
405
|
+
const N = in_normals[i];
|
|
406
|
+
const B = in_binormals[i];
|
|
150
407
|
|
|
151
|
-
|
|
408
|
+
// generate normals and vertices for the current segment
|
|
152
409
|
|
|
153
|
-
|
|
410
|
+
const angular_step = (Math.PI * 2) / radial_segments;
|
|
154
411
|
|
|
155
|
-
|
|
412
|
+
make_ring_vertices(
|
|
413
|
+
out,
|
|
414
|
+
Px, Py, Pz,
|
|
415
|
+
N, B, i / tubular_segments,
|
|
416
|
+
radius, angular_step, radial_segments
|
|
417
|
+
);
|
|
156
418
|
|
|
157
419
|
}
|
|
158
420
|
|
|
159
421
|
|
|
160
|
-
return
|
|
422
|
+
return out.build();
|
|
161
423
|
}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
+
import { EngineConfiguration } from "../../../../EngineConfiguration.js";
|
|
3
|
+
import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
|
|
4
|
+
import HeadsUpDisplaySystem from "../../../../ecs/gui/hud/HeadsUpDisplaySystem.js";
|
|
5
|
+
import ScriptSystem from "../../../../ecs/systems/ScriptSystem.js";
|
|
6
|
+
import FacingDirectionSystem from "../../../../../../model/game/ecs/system/FacingDirectionSystem.js";
|
|
7
|
+
import PathFollowingSystem from "../../../../navigation/ecs/path_following/PathFollowingSystem.js";
|
|
8
|
+
import SteeringSystem from "../../../../ecs/systems/SteeringSystem.js";
|
|
9
|
+
import MotionSystem from "../../../../ecs/systems/MotionSystem.js";
|
|
10
|
+
import TagSystem from "../../../../ecs/systems/TagSystem.js";
|
|
11
|
+
import { AttachmentSystem } from "../../../../ecs/attachment/AttachmentSystem.js";
|
|
12
|
+
import { SoundEmitterSystem } from "../../../../sound/ecs/emitter/SoundEmitterSystem.js";
|
|
13
|
+
import SoundControllerSystem from "../../../../sound/ecs/SoundControllerSystem.js";
|
|
14
|
+
import SoundListenerSystem from "../../../../sound/ecs/SoundListenerSystem.js";
|
|
15
|
+
import TimerSystem from "../../../../ecs/systems/TimerSystem.js";
|
|
16
|
+
import AnimationSystem from "../../../../ecs/systems/AnimationSystem.js";
|
|
17
|
+
import TopDownCameraControllerSystem from "../../camera/topdown/TopDownCameraControllerSystem.js";
|
|
18
|
+
import { TopDownCameraLanderSystem } from "../../camera/topdown/TopDownCameraLanderSystem.js";
|
|
19
|
+
import { CameraSystem } from "../../camera/CameraSystem.js";
|
|
20
|
+
import { MeshSystem } from "../../mesh/MeshSystem.js";
|
|
21
|
+
import ClingToTerrainSystem from "../../../../ecs/terrain/ecs/ClingToTerrainSystem.js";
|
|
22
|
+
import TerrainSystem from "../../../../ecs/terrain/ecs/TerrainSystem.js";
|
|
23
|
+
import WaterSystem from "../../water/WaterSystem.js";
|
|
24
|
+
import Trail2DSystem from "../../trail2d/Trail2DSystem.js";
|
|
25
|
+
import { Foliage2System } from "../../../../ecs/foliage/ecs/Foliage2System.js";
|
|
26
|
+
import ViewportPositionSystem from "../../../../ecs/gui/position/ViewportPositionSystem.js";
|
|
27
|
+
import { GridPosition2TransformSystem } from "../../../../grid/systems/GridPosition2TransformSystem.js";
|
|
28
|
+
import { Transform2GridPositionSystem } from "../../../../grid/transform2grid/Transform2GridPositionSystem.js";
|
|
29
|
+
import SynchronizePositionSystem from "../../../../ecs/systems/SynchronizePositionSystem.js";
|
|
30
|
+
import GridObstacleSystem from "../../../../grid/systems/GridObstacleSystem.js";
|
|
31
|
+
import GridPositionSystem from "../../../../grid/systems/GridPositionSystem.js";
|
|
32
|
+
import InputControllerSystem from "../../../../input/ecs/systems/InputControllerSystem.js";
|
|
33
|
+
import { InputSystem } from "../../../../input/ecs/systems/InputSystem.js";
|
|
34
|
+
import MeshHighlightSystem from "../../highlight/system/MeshHighlightSystem.js";
|
|
35
|
+
import LightSystem from "../../light/LightSystem.js";
|
|
36
|
+
import AnimationControllerSystem from "../../animation/AnimationControllerSystem.js";
|
|
37
|
+
import { AnimationGraphSystem } from "../../animation/animator/AnimationGraphSystem.js";
|
|
38
|
+
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
39
|
+
import { SerializationMetadataSystem } from "../../../../ecs/systems/SerializationMetadataSystem.js";
|
|
40
|
+
import { InverseKinematicsSystem } from "../../../../ecs/animation/InverseKinematicsSystem.js";
|
|
41
|
+
import { PathDisplaySystem } from "../PathDisplaySystem.js";
|
|
42
|
+
import { AmbientOcclusionPostProcessEffect } from "../../../render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js";
|
|
43
|
+
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
44
|
+
import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
|
|
45
|
+
import { JsonAssetLoader } from "../../../../asset/loaders/JsonAssetLoader.js";
|
|
46
|
+
import { TextureAssetLoader } from "../../../../asset/loaders/texture/TextureAssetLoader.js";
|
|
47
|
+
import { ImageRGBADataLoader } from "../../../../asset/loaders/image/ImageRGBADataLoader.js";
|
|
48
|
+
import { ShadedGeometrySystem } from "../../mesh-v2/ShadedGeometrySystem.js";
|
|
49
|
+
import { makeEngineOptionsModel } from "../../../../../../model/game/options/makeEngineOptionsModel.js";
|
|
50
|
+
import { enableEditor } from "../../../../../editor/enableEditor.js";
|
|
51
|
+
import { CanvasView } from "../../../../../view/elements/CanvasView.js";
|
|
52
|
+
import { computeCatmullRomSpline } from "../../../../navigation/ecs/components/computeCatmullRomSpline.js";
|
|
53
|
+
import { EntityPathStyle } from "../entity/EntityPathStyle.js";
|
|
54
|
+
import { EntityPathMarkerDefinition } from "../entity/EntityPathMarkerDefinition.js";
|
|
55
|
+
import { EntityBlueprint } from "../../../../ecs/EntityBlueprint.js";
|
|
56
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
57
|
+
import Mesh from "../../mesh/Mesh.js";
|
|
58
|
+
import { Animation } from "../../../../ecs/animation/Animation.js";
|
|
59
|
+
import Highlight from "../../highlight/Highlight.js";
|
|
60
|
+
import { TubePathStyle } from "./TubePathStyle.js";
|
|
61
|
+
import { TubeMaterialType } from "./TubeMaterialType.js";
|
|
62
|
+
import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
63
|
+
import Path from "../../../../navigation/ecs/components/Path.js";
|
|
64
|
+
import { InterpolationType } from "../../../../navigation/ecs/components/InterpolationType.js";
|
|
65
|
+
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
66
|
+
import { RibbonPathStyle } from "../ribbon/RibbonPathStyle.js";
|
|
67
|
+
import { PathDisplay } from "../PathDisplay.js";
|
|
68
|
+
import { PathDisplaySpec } from "../PathDisplaySpec.js";
|
|
69
|
+
import { PathDisplayType } from "../PathDisplayType.js";
|
|
70
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.js";
|
|
71
|
+
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
72
|
+
import { pingpong } from "../../../../../core/math/pingpong.js";
|
|
73
|
+
import { PathEvents } from "../../../../navigation/ecs/components/PathEvents.js";
|
|
74
|
+
|
|
75
|
+
const engineHarness = new EngineHarness();
|
|
76
|
+
|
|
77
|
+
function makeConfig(engine) {
|
|
78
|
+
|
|
79
|
+
const config = new EngineConfiguration();
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @type {SoundEngine}
|
|
84
|
+
*/
|
|
85
|
+
const sound = engine.sound;
|
|
86
|
+
const graphics = engine.graphics;
|
|
87
|
+
const assetManager = engine.assetManager;
|
|
88
|
+
const devices = engine.devices;
|
|
89
|
+
|
|
90
|
+
const guiSystem = new GUIElementSystem(engine.gui.view, engine);
|
|
91
|
+
const headsUpDisplaySystem = new HeadsUpDisplaySystem(graphics);
|
|
92
|
+
|
|
93
|
+
config.systems.push(
|
|
94
|
+
new ScriptSystem(),
|
|
95
|
+
new FacingDirectionSystem(),
|
|
96
|
+
new PathFollowingSystem(),
|
|
97
|
+
new SteeringSystem(),
|
|
98
|
+
new MotionSystem(),
|
|
99
|
+
new TagSystem(),
|
|
100
|
+
new AttachmentSystem(),
|
|
101
|
+
new SoundEmitterSystem(assetManager, sound.destination, sound.context),
|
|
102
|
+
new SoundControllerSystem(),
|
|
103
|
+
new SoundListenerSystem(sound.context),
|
|
104
|
+
new TimerSystem(),
|
|
105
|
+
guiSystem,
|
|
106
|
+
new AnimationSystem(graphics.viewport.size),
|
|
107
|
+
new TopDownCameraControllerSystem(graphics),
|
|
108
|
+
new TopDownCameraLanderSystem(),
|
|
109
|
+
new CameraSystem(graphics.scene, graphics),
|
|
110
|
+
new MeshSystem(engine),
|
|
111
|
+
new ClingToTerrainSystem(),
|
|
112
|
+
new TerrainSystem(graphics, assetManager),
|
|
113
|
+
new WaterSystem(graphics),
|
|
114
|
+
new Trail2DSystem(engine),
|
|
115
|
+
new Foliage2System(assetManager, graphics),
|
|
116
|
+
new ViewportPositionSystem(graphics.viewport.size),
|
|
117
|
+
new GridPosition2TransformSystem(),
|
|
118
|
+
new Transform2GridPositionSystem(),
|
|
119
|
+
new SynchronizePositionSystem(),
|
|
120
|
+
new GridObstacleSystem(),
|
|
121
|
+
new GridPositionSystem(),
|
|
122
|
+
new InputControllerSystem(devices),
|
|
123
|
+
new InputSystem(devices),
|
|
124
|
+
new MeshHighlightSystem(engine),
|
|
125
|
+
new LightSystem(engine, {
|
|
126
|
+
shadowResolution: 1024
|
|
127
|
+
}),
|
|
128
|
+
new AnimationControllerSystem(),
|
|
129
|
+
new AnimationGraphSystem(graphics.viewport.size),
|
|
130
|
+
headsUpDisplaySystem,
|
|
131
|
+
new BehaviorSystem(engine),
|
|
132
|
+
new SerializationMetadataSystem(),
|
|
133
|
+
new InverseKinematicsSystem(),
|
|
134
|
+
new PathDisplaySystem(engine),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Plugins
|
|
138
|
+
|
|
139
|
+
config.addPlugin(AmbientOcclusionPostProcessEffect)
|
|
140
|
+
|
|
141
|
+
// Knowledge
|
|
142
|
+
|
|
143
|
+
// Assets
|
|
144
|
+
|
|
145
|
+
config.addLoader(GameAssetType.ModelGLTF, new GLTFAssetLoader());
|
|
146
|
+
config.addLoader(GameAssetType.ModelGLTF_JSON, new GLTFAssetLoader());
|
|
147
|
+
config.addLoader(GameAssetType.JSON, new JsonAssetLoader());
|
|
148
|
+
config.addLoader(GameAssetType.Texture, new TextureAssetLoader());
|
|
149
|
+
config.addLoader(GameAssetType.Image, new ImageRGBADataLoader());
|
|
150
|
+
|
|
151
|
+
return config;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
*
|
|
156
|
+
* @param {EngineHarness} harness
|
|
157
|
+
* @return {Promise<void>}
|
|
158
|
+
*/
|
|
159
|
+
async function init(harness) {
|
|
160
|
+
const engine = harness.engine;
|
|
161
|
+
|
|
162
|
+
// engine.entityManager.addSystem(new RenderSystem(engine.graphics));
|
|
163
|
+
engine.entityManager.addSystem(new ShadedGeometrySystem(engine));
|
|
164
|
+
|
|
165
|
+
makeEngineOptionsModel(engine.options, engine);
|
|
166
|
+
|
|
167
|
+
await makeConfig(engine).apply(engine);
|
|
168
|
+
|
|
169
|
+
enableEditor(engine);
|
|
170
|
+
|
|
171
|
+
await harness.initialize();
|
|
172
|
+
|
|
173
|
+
main(engine);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function catmullRom(points) {
|
|
177
|
+
const cv = new CanvasView();
|
|
178
|
+
|
|
179
|
+
cv.size.set(500, 500);
|
|
180
|
+
|
|
181
|
+
cv.link();
|
|
182
|
+
|
|
183
|
+
cv.css({
|
|
184
|
+
position: "absolute",
|
|
185
|
+
left: 0,
|
|
186
|
+
right: 0,
|
|
187
|
+
zIndex: 99999
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const sample = [];
|
|
191
|
+
|
|
192
|
+
const ctx = cv.context2d;
|
|
193
|
+
ctx.strokeStyle = "rgba(255,255,255,1)";
|
|
194
|
+
ctx.lineWidth = 2;
|
|
195
|
+
ctx.beginPath();
|
|
196
|
+
|
|
197
|
+
const draw_scale = 50;
|
|
198
|
+
|
|
199
|
+
const result = [];
|
|
200
|
+
const sampleCount = 50;
|
|
201
|
+
|
|
202
|
+
computeCatmullRomSpline(result, points, points.length / 3, 3, sampleCount, 0.5);
|
|
203
|
+
|
|
204
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
205
|
+
const x = result[i * 3];
|
|
206
|
+
const y = result[i * 3 + 1];
|
|
207
|
+
const z = result[i * 3 + 2];
|
|
208
|
+
|
|
209
|
+
ctx.lineTo(x * draw_scale, z * draw_scale);
|
|
210
|
+
|
|
211
|
+
}
|
|
212
|
+
ctx.stroke();
|
|
213
|
+
|
|
214
|
+
document.body.appendChild(cv.el);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function sample_style_entity() {
|
|
218
|
+
const style = new EntityPathStyle();
|
|
219
|
+
style.spacing = 0.6;
|
|
220
|
+
style.marker_start = EntityPathMarkerDefinition.from({
|
|
221
|
+
blueprint: EntityBlueprint.from([
|
|
222
|
+
Transform.fromJSON({}),
|
|
223
|
+
Mesh.fromJSON({
|
|
224
|
+
url: "data/models/arrow-symbols/arrow4/model-green.gltf",
|
|
225
|
+
castShadow: true,
|
|
226
|
+
receiveShadow: true
|
|
227
|
+
})
|
|
228
|
+
]),
|
|
229
|
+
transform: Transform.fromJSON({
|
|
230
|
+
scale: {
|
|
231
|
+
x: 0.3,
|
|
232
|
+
y: 0.3,
|
|
233
|
+
z: 0.3
|
|
234
|
+
},
|
|
235
|
+
rotation: {
|
|
236
|
+
x: 0.5,
|
|
237
|
+
y: -0.5,
|
|
238
|
+
z: 0.5,
|
|
239
|
+
w: 0.5
|
|
240
|
+
},
|
|
241
|
+
position: {
|
|
242
|
+
x: 0,
|
|
243
|
+
y: 1,
|
|
244
|
+
z: 0
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
});
|
|
248
|
+
style.marker_end = EntityPathMarkerDefinition.from({
|
|
249
|
+
blueprint: EntityBlueprint.from([
|
|
250
|
+
Transform.fromJSON({}),
|
|
251
|
+
Mesh.fromJSON({
|
|
252
|
+
url: "data/models/arrow-symbols/arrow4/model-red.gltf",
|
|
253
|
+
castShadow: true,
|
|
254
|
+
receiveShadow: true
|
|
255
|
+
})
|
|
256
|
+
]),
|
|
257
|
+
transform: Transform.fromJSON({
|
|
258
|
+
scale: {
|
|
259
|
+
x: 0.3,
|
|
260
|
+
y: 0.3,
|
|
261
|
+
z: 0.3
|
|
262
|
+
},
|
|
263
|
+
rotation: {
|
|
264
|
+
x: 0.5,
|
|
265
|
+
y: -0.5,
|
|
266
|
+
z: 0.5,
|
|
267
|
+
w: 0.5
|
|
268
|
+
},
|
|
269
|
+
position: {
|
|
270
|
+
x: 0,
|
|
271
|
+
y: 1,
|
|
272
|
+
z: 0
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
});
|
|
276
|
+
style.marker_main = EntityPathMarkerDefinition.from({
|
|
277
|
+
blueprint: EntityBlueprint.from([
|
|
278
|
+
Transform.fromJSON({}),
|
|
279
|
+
Mesh.fromJSON({
|
|
280
|
+
url: "data/models/Barel-Roll Droid/handpainted.gltf",
|
|
281
|
+
castShadow: true,
|
|
282
|
+
receiveShadow: true
|
|
283
|
+
}),
|
|
284
|
+
Animation.fromJSON({
|
|
285
|
+
clips: [
|
|
286
|
+
{
|
|
287
|
+
name: "fly",
|
|
288
|
+
repeatCount: Infinity
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
}),
|
|
292
|
+
Highlight.fromOne(1, 0, 0, 1)
|
|
293
|
+
]),
|
|
294
|
+
transform: Transform.fromJSON({
|
|
295
|
+
scale: {
|
|
296
|
+
x: 0.2,
|
|
297
|
+
y: 0.2,
|
|
298
|
+
z: 0.2
|
|
299
|
+
},
|
|
300
|
+
position: {
|
|
301
|
+
x: 0,
|
|
302
|
+
y: 1,
|
|
303
|
+
z: 0
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
return style;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function sample_style_tube() {
|
|
312
|
+
const style = new TubePathStyle();
|
|
313
|
+
|
|
314
|
+
style.color.setRGB(1, 1, 1);
|
|
315
|
+
style.material_type = TubeMaterialType.Matcap;
|
|
316
|
+
style.material = new MatcapMaterialDefinition();
|
|
317
|
+
// style.material.texture = 'data/textures/matcap/matcap-porcelain-white.jpg';
|
|
318
|
+
style.material.texture = "data/textures/matcap/nidorx/3E2335_D36A1B_8E4A2E_2842A5.jpg";
|
|
319
|
+
|
|
320
|
+
style.width = 0.1;
|
|
321
|
+
|
|
322
|
+
style.path_mask = [
|
|
323
|
+
0, 1,
|
|
324
|
+
];
|
|
325
|
+
|
|
326
|
+
return style;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
function main(engine) {
|
|
331
|
+
EngineHarness.buildBasics({ engine });
|
|
332
|
+
|
|
333
|
+
const _p = new Path();
|
|
334
|
+
_p.interpolation = InterpolationType.CatmullRom;
|
|
335
|
+
// _p.interpolation = InterpolationType.Linear;
|
|
336
|
+
|
|
337
|
+
// _p.setPositionsFromVectorArray(Path.smoothPath([
|
|
338
|
+
// new Vector3(3, 1, 1),
|
|
339
|
+
// new Vector3(3, 1, 3),
|
|
340
|
+
// new Vector3(7, 1, 3),
|
|
341
|
+
// new Vector3(7, 1, 7),
|
|
342
|
+
// new Vector3(3, 1, 7),
|
|
343
|
+
// new Vector3(3, 1, 8),
|
|
344
|
+
// ], 50));
|
|
345
|
+
|
|
346
|
+
_p.setPositionsFromVectorArray([
|
|
347
|
+
new Vector3(3, 1, 1),
|
|
348
|
+
new Vector3(3, 1, 3),
|
|
349
|
+
new Vector3(7, 1, 3),
|
|
350
|
+
new Vector3(7, 1, 7),
|
|
351
|
+
new Vector3(3, 1, 7),
|
|
352
|
+
new Vector3(3, 1, 8),
|
|
353
|
+
]);
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
const trailPathStyle = new RibbonPathStyle();
|
|
357
|
+
trailPathStyle.material.diffuse = "data/textures/trail/Circle_04.png";
|
|
358
|
+
trailPathStyle.resolution = 10;
|
|
359
|
+
trailPathStyle.thickness = 0.1;
|
|
360
|
+
|
|
361
|
+
const pathDisplay = new PathDisplay();
|
|
362
|
+
const tube_style = sample_style_tube();
|
|
363
|
+
pathDisplay.specs.push(
|
|
364
|
+
PathDisplaySpec.from(
|
|
365
|
+
PathDisplayType.Tube,
|
|
366
|
+
tube_style
|
|
367
|
+
)
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
const path_entity = new EntityBuilder();
|
|
372
|
+
|
|
373
|
+
const ecd = engine.entityManager.dataset;
|
|
374
|
+
path_entity
|
|
375
|
+
.add(_p)
|
|
376
|
+
.add(pathDisplay)
|
|
377
|
+
.build(ecd);
|
|
378
|
+
|
|
379
|
+
let time = 0;
|
|
380
|
+
new EntityBuilder()
|
|
381
|
+
.add(BehaviorComponent.looping_function((delta) => {
|
|
382
|
+
time += delta*0.01;
|
|
383
|
+
tube_style.path_mask[1] = pingpong(time, 1);
|
|
384
|
+
|
|
385
|
+
path_entity.sendEvent(PathEvents.Changed);
|
|
386
|
+
}))
|
|
387
|
+
.build(ecd)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
init(engineHarness);
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.35.
|
|
8
|
+
"version": "2.35.17",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|