@woosh/meep-engine 2.35.12 → 2.35.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +30 -1
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +6 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +1 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +29 -2
- package/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +43 -21
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +41 -12
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +43 -3
- package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +28 -16
- package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +11 -6
- package/engine/navigation/ecs/components/Path.js +5 -6
- package/package.json +1 -1
|
@@ -74,6 +74,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
74
74
|
* @private
|
|
75
75
|
*/
|
|
76
76
|
this.__adapter_suppliers = new Map();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Keeps count of usage for each geometry by ID
|
|
80
|
+
* @type {Map<number, number>}
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
this.__geometry_usage_counters = new Map();
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/**
|
|
@@ -166,7 +173,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
166
173
|
this.__render_layer.buildVisibleSet = ((destination, destination_offset, view) => {
|
|
167
174
|
const ctx = this.__view_contexts.get(view);
|
|
168
175
|
|
|
169
|
-
return ctx.collect(destination, destination_offset,graphics.renderer, view, this.__bvh);
|
|
176
|
+
return ctx.collect(destination, destination_offset, graphics.renderer, view, this.__bvh);
|
|
170
177
|
});
|
|
171
178
|
|
|
172
179
|
readyCallback();
|
|
@@ -210,6 +217,13 @@ export class ShadedGeometrySystem extends System {
|
|
|
210
217
|
sg.__entity = entity;
|
|
211
218
|
|
|
212
219
|
this.__bvh.insertNode(leaf_node);
|
|
220
|
+
|
|
221
|
+
// update usage count
|
|
222
|
+
const geometry_id = sg.geometry.id;
|
|
223
|
+
const count_existing = this.__geometry_usage_counters.get(geometry_id);
|
|
224
|
+
const count_new = count_existing !== undefined ? count_existing + 1 : 1;
|
|
225
|
+
|
|
226
|
+
this.__geometry_usage_counters.set(geometry_id, count_new);
|
|
213
227
|
}
|
|
214
228
|
|
|
215
229
|
/**
|
|
@@ -224,6 +238,21 @@ export class ShadedGeometrySystem extends System {
|
|
|
224
238
|
t.scale.onChanged.remove(sg.updateTransform, sg);
|
|
225
239
|
|
|
226
240
|
sg.bvh.disconnect();
|
|
241
|
+
|
|
242
|
+
const geometry_id = sg.geometry.id;
|
|
243
|
+
const count_existing = this.__geometry_usage_counters.get(geometry_id);
|
|
244
|
+
|
|
245
|
+
if (count_existing === 1) {
|
|
246
|
+
|
|
247
|
+
// last instance
|
|
248
|
+
this.__geometry_usage_counters.delete(geometry_id);
|
|
249
|
+
|
|
250
|
+
// release GPU memory
|
|
251
|
+
sg.geometry.dispose();
|
|
252
|
+
|
|
253
|
+
} else {
|
|
254
|
+
this.__geometry_usage_counters.set(geometry_id, count_existing - 1);
|
|
255
|
+
}
|
|
227
256
|
}
|
|
228
257
|
|
|
229
258
|
/**
|
|
@@ -3,6 +3,8 @@ import { TubeMaterialType } from "./TubeMaterialType.js";
|
|
|
3
3
|
import { assert } from "../../../../../core/assert.js";
|
|
4
4
|
import { MatcapMaterialDefinition } from "./MatcapMaterialDefinition.js";
|
|
5
5
|
|
|
6
|
+
const DEFAULT_COLOR = Object.freeze({ r: 1, g: 1, b: 1 });
|
|
7
|
+
|
|
6
8
|
export class TubePathStyle {
|
|
7
9
|
constructor() {
|
|
8
10
|
/**
|
|
@@ -59,6 +61,16 @@ export class TubePathStyle {
|
|
|
59
61
|
* @type {boolean}
|
|
60
62
|
*/
|
|
61
63
|
this.receive_shadow = false;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Which parts of the path to visualise, in normalized offsets
|
|
67
|
+
* @example [ 0, 1 ] = whole path
|
|
68
|
+
* @example [ 0, 0.5 ] = first half of the path
|
|
69
|
+
* @example [ 0.5, 0.6 ] = segment from 50% along the path, to 60% along the path
|
|
70
|
+
* @example [ 0, 0.1, 0.9, 1] = first 10% of the path, and last 10% of the path
|
|
71
|
+
* @type {number[]}
|
|
72
|
+
*/
|
|
73
|
+
this.path_mask = [0, 1];
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
static fromJSON(j) {
|
|
@@ -70,7 +82,7 @@ export class TubePathStyle {
|
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
fromJSON({
|
|
73
|
-
color,
|
|
85
|
+
color = DEFAULT_COLOR,
|
|
74
86
|
material_type,
|
|
75
87
|
material,
|
|
76
88
|
opacity = 1,
|
|
@@ -78,9 +90,22 @@ export class TubePathStyle {
|
|
|
78
90
|
resolution = 10,
|
|
79
91
|
radial_resolution = 16,
|
|
80
92
|
cast_shadow = false,
|
|
81
|
-
receive_shadow = false
|
|
93
|
+
receive_shadow = false,
|
|
94
|
+
path_mask = [0, 1]
|
|
82
95
|
}) {
|
|
83
96
|
assert.enum(material_type, TubeMaterialType, 'material_type');
|
|
97
|
+
assert.isNumber(opacity, 'opacity');
|
|
98
|
+
assert.isNumber(width, 'width');
|
|
99
|
+
assert.isNumber(resolution, 'resolution');
|
|
100
|
+
assert.isNumber(radial_resolution, 'radial_resolution');
|
|
101
|
+
assert.isBoolean(cast_shadow, 'cast_shadow');
|
|
102
|
+
assert.isBoolean(receive_shadow, 'receive_shadow');
|
|
103
|
+
|
|
104
|
+
assert.defined(path_mask, 'path_mask');
|
|
105
|
+
assert.notNull(path_mask, 'path_mask');
|
|
106
|
+
|
|
107
|
+
assert.greaterThanOrEqual(path_mask.length, 2, 'path_mask length bust be at least 2');
|
|
108
|
+
assert.ok(path_mask.length % 2 === 0, 'path_mask length bust be multiple of 2');
|
|
84
109
|
|
|
85
110
|
if (typeof color === 'string') {
|
|
86
111
|
this.color.parse(color);
|
|
@@ -97,6 +122,8 @@ export class TubePathStyle {
|
|
|
97
122
|
this.cast_shadow = cast_shadow;
|
|
98
123
|
this.receive_shadow = receive_shadow;
|
|
99
124
|
|
|
125
|
+
this.path_mask = path_mask;
|
|
126
|
+
|
|
100
127
|
switch (material_type) {
|
|
101
128
|
case TubeMaterialType.Matcap:
|
|
102
129
|
this.material = new MatcapMaterialDefinition();
|
|
@@ -9,6 +9,28 @@ import { build_geometry_catmullrom } from "./build_geometry_catmullrom.js";
|
|
|
9
9
|
import { ShadedGeometry } from "../../../mesh-v2/ShadedGeometry.js";
|
|
10
10
|
import { ShadedGeometryFlags } from "../../../mesh-v2/ShadedGeometryFlags.js";
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param {number} segment_start
|
|
15
|
+
* @param {number} segment_end
|
|
16
|
+
* @returns {BufferGeometry}
|
|
17
|
+
* @param {Path} path_component
|
|
18
|
+
* @param {TubePathStyle} style
|
|
19
|
+
*/
|
|
20
|
+
function make_geometry_segment(path_component, style, segment_start, segment_end) {
|
|
21
|
+
|
|
22
|
+
const interpolation = path_component.interpolation;
|
|
23
|
+
|
|
24
|
+
if (interpolation === InterpolationType.Linear) {
|
|
25
|
+
return build_geometry_linear(path_component, style, segment_start, segment_end);
|
|
26
|
+
} else if (interpolation === InterpolationType.CatmullRom) {
|
|
27
|
+
return build_geometry_catmullrom(path_component, style, segment_start, segment_end);
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error(`Unsupported interpolation type '${interpolation}'`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
12
34
|
export class TubePathBuilder {
|
|
13
35
|
constructor() {
|
|
14
36
|
/**
|
|
@@ -80,20 +102,6 @@ export class TubePathBuilder {
|
|
|
80
102
|
}
|
|
81
103
|
|
|
82
104
|
|
|
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
105
|
let material_def;
|
|
98
106
|
|
|
99
107
|
if (style.material_type === TubeMaterialType.Standard) {
|
|
@@ -116,23 +124,37 @@ export class TubePathBuilder {
|
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
material_def.color.set(style.color.toUint());
|
|
127
|
+
material_def.wireframe = true;
|
|
119
128
|
|
|
120
129
|
if (style.opacity < 1) {
|
|
121
130
|
material_def.transparent = true;
|
|
122
131
|
material_def.opacity = style.opacity;
|
|
123
132
|
}
|
|
124
133
|
|
|
125
|
-
const
|
|
134
|
+
const segment_count = style.path_mask.length / 2;
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < segment_count; i++) {
|
|
137
|
+
const i2 = i * 2;
|
|
138
|
+
|
|
139
|
+
const segment_start = style.path_mask[i2];
|
|
140
|
+
const segment_end = style.path_mask[i2 + 1];
|
|
141
|
+
|
|
142
|
+
const geometry = make_geometry_segment(path_component, style, segment_start, segment_end);
|
|
126
143
|
|
|
127
|
-
|
|
144
|
+
const entityBuilder = new EntityBuilder();
|
|
128
145
|
|
|
129
|
-
|
|
146
|
+
entityBuilder.add(new Transform());
|
|
130
147
|
|
|
131
|
-
|
|
132
|
-
shaded_geometry.writeFlag(ShadedGeometryFlags.ReceiveShadow, style.receive_shadow);
|
|
148
|
+
const shaded_geometry = ShadedGeometry.from(geometry, material_def);
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
shaded_geometry.writeFlag(ShadedGeometryFlags.CastShadow, style.cast_shadow);
|
|
151
|
+
shaded_geometry.writeFlag(ShadedGeometryFlags.ReceiveShadow, style.receive_shadow);
|
|
152
|
+
|
|
153
|
+
entityBuilder.add(shaded_geometry);
|
|
154
|
+
|
|
155
|
+
destination.push(entityBuilder);
|
|
156
|
+
|
|
157
|
+
}
|
|
135
158
|
|
|
136
|
-
destination.push(entityBuilder);
|
|
137
159
|
}
|
|
138
160
|
}
|
|
@@ -1,32 +1,61 @@
|
|
|
1
|
-
import { CatmullRomCurve3 } from "three";
|
|
2
1
|
import { computeFrenetFrames } from "./computeFrenetFrames.js";
|
|
3
2
|
import { makeTubeGeometry } from "./makeTubeGeometry.js";
|
|
3
|
+
import Vector3 from "../../../../../../core/geom/Vector3.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
7
|
-
* @param {
|
|
8
|
-
* @param {number} point_count
|
|
7
|
+
* @param {Path} path
|
|
9
8
|
* @param {TubePathStyle} style
|
|
9
|
+
* @param {number} segment_start
|
|
10
|
+
* @param {number} segment_end
|
|
10
11
|
* @return {THREE.BufferGeometry}
|
|
11
12
|
*/
|
|
12
|
-
export function build_geometry_catmullrom(
|
|
13
|
+
export function build_geometry_catmullrom(path, style, segment_start, segment_end) {
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const sample_points = [];
|
|
15
|
+
const point_count = path.getPointCount();
|
|
17
16
|
|
|
18
17
|
// resample curve
|
|
19
18
|
const total_points = Math.ceil(point_count * style.resolution);
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
const path_length = path.length;
|
|
21
|
+
|
|
22
|
+
const point = new Vector3();
|
|
23
|
+
|
|
24
|
+
const points_f32 = [];
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
let added_points = 0;
|
|
28
|
+
let i;
|
|
29
|
+
|
|
30
|
+
// initial segment
|
|
31
|
+
path.sample_catmull_rom(point, segment_start * path_length);
|
|
32
|
+
|
|
33
|
+
point.writeToArray(points_f32, added_points * 3);
|
|
34
|
+
|
|
35
|
+
added_points++;
|
|
36
|
+
|
|
37
|
+
const max_i = segment_end * (total_points - 1);
|
|
38
|
+
for (i = Math.ceil(segment_start * total_points + 0.0001); i < max_i; i++) {
|
|
22
39
|
const t = i / (total_points - 1);
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
path.sample_catmull_rom(point, path_length * t);
|
|
42
|
+
|
|
43
|
+
point.writeToArray(points_f32, added_points * 3);
|
|
44
|
+
|
|
45
|
+
added_points++
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (((i - 1) / (total_points - 1)) - segment_end > 0.0001) {
|
|
49
|
+
// end
|
|
50
|
+
|
|
51
|
+
path.sample_catmull_rom(point, segment_end * path_length);
|
|
52
|
+
|
|
53
|
+
point.writeToArray(points_f32, added_points * 3);
|
|
25
54
|
|
|
26
|
-
|
|
55
|
+
added_points++;
|
|
27
56
|
}
|
|
28
57
|
|
|
29
|
-
const frames = computeFrenetFrames(
|
|
58
|
+
const frames = computeFrenetFrames(points_f32, false);
|
|
30
59
|
|
|
31
|
-
return makeTubeGeometry(
|
|
60
|
+
return makeTubeGeometry(points_f32, frames.normals, frames.binormals, style.width, style.radial_resolution, false);
|
|
32
61
|
}
|
|
@@ -1,14 +1,54 @@
|
|
|
1
1
|
import { computeFrenetFrames } from "./computeFrenetFrames.js";
|
|
2
2
|
import { makeTubeGeometry } from "./makeTubeGeometry.js";
|
|
3
|
+
import Vector3 from "../../../../../../core/geom/Vector3.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const scratch_array_0 = [];
|
|
7
|
+
const scratch_array_1 = [];
|
|
8
|
+
|
|
9
|
+
const scratch_v3 = new Vector3();
|
|
3
10
|
|
|
4
11
|
/**
|
|
5
12
|
*
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {number} point_count
|
|
13
|
+
* @param {Path} path
|
|
8
14
|
* @param {TubePathStyle} style
|
|
15
|
+
* @param {number} segment_start
|
|
16
|
+
* @param {number} segment_end
|
|
9
17
|
* @return {THREE.BufferGeometry}
|
|
10
18
|
*/
|
|
11
|
-
export function build_geometry_linear(
|
|
19
|
+
export function build_geometry_linear(path, style, segment_start, segment_end) {
|
|
20
|
+
const points = [];
|
|
21
|
+
|
|
22
|
+
const path_length = path.length;
|
|
23
|
+
|
|
24
|
+
path.find_index_and_normalized_distance(scratch_array_0, segment_start * path_length);
|
|
25
|
+
path.find_index_and_normalized_distance(scratch_array_1, segment_end * path_length);
|
|
26
|
+
|
|
27
|
+
let points_added = 0;
|
|
28
|
+
|
|
29
|
+
if (scratch_array_0[1] !== 0) {
|
|
30
|
+
path.sample_linear(scratch_v3, segment_start * path_length);
|
|
31
|
+
|
|
32
|
+
scratch_v3.writeToArray(points, points_added * 3);
|
|
33
|
+
points_added++;
|
|
34
|
+
|
|
35
|
+
// offset first sampled point, we're already past it
|
|
36
|
+
scratch_array_0[0]++;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const max_i = scratch_array_1[0];
|
|
40
|
+
for (let i = scratch_array_0[0]; i <= max_i; i++) {
|
|
41
|
+
path.readPositionToArray(i, points, points_added * 3);
|
|
42
|
+
points_added++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (scratch_array_1[1] !== 0) {
|
|
46
|
+
//add end
|
|
47
|
+
path.sample_linear(scratch_v3, segment_end * path_length);
|
|
48
|
+
|
|
49
|
+
scratch_v3.writeToArray(points, points_added * 3);
|
|
50
|
+
points_added++;
|
|
51
|
+
}
|
|
12
52
|
|
|
13
53
|
const frames = computeFrenetFrames(points, false);
|
|
14
54
|
|
|
@@ -2,15 +2,17 @@ import { Vector3 } from "three";
|
|
|
2
2
|
import { Matrix4 } from "three/src/math/Matrix4.js";
|
|
3
3
|
import { max2 } from "../../../../../../core/math/max2.js";
|
|
4
4
|
import { min2 } from "../../../../../../core/math/min2.js";
|
|
5
|
-
import
|
|
5
|
+
import { clamp } from "../../../../../../core/math/clamp.js";
|
|
6
|
+
import { vec3 } from "gl-matrix";
|
|
7
|
+
import { array_copy } from "../../../../../../core/collection/array/copyArray.js";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* @see https://github.com/mrdoob/three.js/blob/c12c9a166a1369cdd58622fff2aff7e3a84305d7/src/extras/core/Curve.js#L260
|
|
9
|
-
* @param {
|
|
11
|
+
* @param {Float32Array|number[]} points
|
|
10
12
|
* @param {boolean} [closed]
|
|
11
13
|
*/
|
|
12
14
|
export function computeFrenetFrames(points, closed = false) {
|
|
13
|
-
// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
|
|
15
|
+
// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
|
|
14
16
|
|
|
15
17
|
const normal = new Vector3();
|
|
16
18
|
|
|
@@ -21,10 +23,15 @@ export function computeFrenetFrames(points, closed = false) {
|
|
|
21
23
|
const vec = new Vector3();
|
|
22
24
|
const mat = new Matrix4();
|
|
23
25
|
|
|
24
|
-
const
|
|
26
|
+
const point_count = points.length / 3;
|
|
27
|
+
const segments = point_count - 1;
|
|
25
28
|
|
|
26
|
-
const v3_0 =
|
|
27
|
-
const v3_1 =
|
|
29
|
+
const v3_0 = [];
|
|
30
|
+
const v3_1 = [];
|
|
31
|
+
|
|
32
|
+
const p0_a = [];
|
|
33
|
+
const pR_a = [];
|
|
34
|
+
const p1_a = [];
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
37
|
*
|
|
@@ -36,18 +43,23 @@ export function computeFrenetFrames(points, closed = false) {
|
|
|
36
43
|
const i0 = max2(i - 1, 0);
|
|
37
44
|
const i1 = min2(i + 1, segments);
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
array_copy(points, i0 * 3, p0_a, 0, 3);
|
|
47
|
+
array_copy(points, i * 3, pR_a, 0, 3);
|
|
48
|
+
array_copy(points, i1 * 3, p1_a, 0, 3);
|
|
42
49
|
|
|
43
50
|
// get points along the lines close to the reference
|
|
44
|
-
v3_0.subVectors(p0, pR);
|
|
45
|
-
v3_0.normalize();
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
vec3.sub(v3_0, p0_a, pR_a);
|
|
53
|
+
vec3.normalize(v3_0, v3_0);
|
|
54
|
+
|
|
55
|
+
vec3.sub(v3_1, p1_a, pR_a);
|
|
56
|
+
vec3.normalize(v3_1, v3_1);
|
|
49
57
|
|
|
50
|
-
destination.
|
|
58
|
+
destination.set(
|
|
59
|
+
v3_1[0] - v3_0[0],
|
|
60
|
+
v3_1[1] - v3_0[1],
|
|
61
|
+
v3_1[2] - v3_0[2],
|
|
62
|
+
);
|
|
51
63
|
destination.normalize();
|
|
52
64
|
}
|
|
53
65
|
|
|
@@ -112,7 +124,7 @@ export function computeFrenetFrames(points, closed = false) {
|
|
|
112
124
|
|
|
113
125
|
vec.normalize();
|
|
114
126
|
|
|
115
|
-
const theta = Math.acos(
|
|
127
|
+
const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), -1, 1)); // clamp for floating pt errors
|
|
116
128
|
|
|
117
129
|
normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
|
|
118
130
|
|
|
@@ -126,7 +138,7 @@ export function computeFrenetFrames(points, closed = false) {
|
|
|
126
138
|
|
|
127
139
|
if (closed === true) {
|
|
128
140
|
|
|
129
|
-
let theta = Math.acos(
|
|
141
|
+
let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1));
|
|
130
142
|
theta /= segments;
|
|
131
143
|
|
|
132
144
|
if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
|
|
@@ -2,7 +2,7 @@ import { BufferGeometry, Float32BufferAttribute, Vector3 } from "three";
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
|
|
5
|
-
* @param {
|
|
5
|
+
* @param {Float32Array|number[]} points
|
|
6
6
|
* @param {Vector3[]} _normals
|
|
7
7
|
* @param {Vector3[]} binormals
|
|
8
8
|
* @param {number} radius
|
|
@@ -24,7 +24,8 @@ export function makeTubeGeometry(points, _normals, binormals, radius, radialSegm
|
|
|
24
24
|
const uvs = [];
|
|
25
25
|
const indices = [];
|
|
26
26
|
|
|
27
|
-
const
|
|
27
|
+
const point_count = points.length / 3;
|
|
28
|
+
const tubularSegments = point_count - 1;
|
|
28
29
|
|
|
29
30
|
// create buffer data
|
|
30
31
|
|
|
@@ -69,7 +70,11 @@ export function makeTubeGeometry(points, _normals, binormals, radius, radialSegm
|
|
|
69
70
|
|
|
70
71
|
// we use getPointAt to sample evenly distributed points from the given path
|
|
71
72
|
|
|
72
|
-
const
|
|
73
|
+
const i3 = i * 3;
|
|
74
|
+
|
|
75
|
+
const Px = points[i3];
|
|
76
|
+
const Py = points[i3 + 1];
|
|
77
|
+
const Pz = points[i3 + 2];
|
|
73
78
|
|
|
74
79
|
// retrieve corresponding normal and binormal
|
|
75
80
|
|
|
@@ -97,9 +102,9 @@ export function makeTubeGeometry(points, _normals, binormals, radius, radialSegm
|
|
|
97
102
|
|
|
98
103
|
// vertex
|
|
99
104
|
|
|
100
|
-
vertex.x =
|
|
101
|
-
vertex.y =
|
|
102
|
-
vertex.z =
|
|
105
|
+
vertex.x = Px + radius * normal.x;
|
|
106
|
+
vertex.y = Py + radius * normal.y;
|
|
107
|
+
vertex.z = Pz + radius * normal.z;
|
|
103
108
|
|
|
104
109
|
vertices.push(vertex.x, vertex.y, vertex.z);
|
|
105
110
|
|
|
@@ -436,7 +436,7 @@ class Path {
|
|
|
436
436
|
*/
|
|
437
437
|
sample_linear(result, offset) {
|
|
438
438
|
|
|
439
|
-
const found = this.
|
|
439
|
+
const found = this.find_index_and_normalized_distance(scratch_array_0, offset);
|
|
440
440
|
|
|
441
441
|
if (!found) {
|
|
442
442
|
return false;
|
|
@@ -466,9 +466,8 @@ class Path {
|
|
|
466
466
|
* @param {number[]} result
|
|
467
467
|
* @param {number} absolute_distance absolute distance along the path
|
|
468
468
|
* @returns {boolean}
|
|
469
|
-
* @private
|
|
470
469
|
*/
|
|
471
|
-
|
|
470
|
+
find_index_and_normalized_distance(result, absolute_distance) {
|
|
472
471
|
const pointCount = this.getPointCount();
|
|
473
472
|
|
|
474
473
|
if (pointCount === 0) {
|
|
@@ -495,10 +494,10 @@ class Path {
|
|
|
495
494
|
// we found v1
|
|
496
495
|
const local_offset = absolute_distance - cursor;
|
|
497
496
|
|
|
498
|
-
const
|
|
497
|
+
const local_normalized_offset = local_offset / distance;
|
|
499
498
|
|
|
500
499
|
result[0] = i - 1;
|
|
501
|
-
result[1] =
|
|
500
|
+
result[1] = local_normalized_offset;
|
|
502
501
|
return true;
|
|
503
502
|
}
|
|
504
503
|
|
|
@@ -525,7 +524,7 @@ class Path {
|
|
|
525
524
|
* @returns {boolean}
|
|
526
525
|
*/
|
|
527
526
|
sample_catmull_rom(result, offset) {
|
|
528
|
-
const found = this.
|
|
527
|
+
const found = this.find_index_and_normalized_distance(scratch_array_0, offset);
|
|
529
528
|
|
|
530
529
|
if (!found) {
|
|
531
530
|
return false;
|
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.13",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|