@woosh/meep-engine 2.35.16 → 2.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/binary/BinaryBuffer.js +42 -17
- package/core/bvh2/BinaryNode.js +1 -1
- package/core/bvh2/aabb3/AABB3.js +2 -2
- package/core/bvh2/aabb3/aabb3_array_combine.js +20 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_frustum_array.js +20 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_ray.js +1 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_ray_array.js +14 -0
- package/core/bvh2/{aabb3_combined_surface_area.js → aabb3/aabb3_combined_surface_area.js} +3 -3
- package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +1 -19
- package/core/bvh2/bvh3/BVHNodeProxy.js +53 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +848 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.spec.js +142 -0
- package/core/bvh2/bvh3/bvh_query_leaves_generic.js +79 -0
- package/core/bvh2/bvh3/bvh_query_leaves_ray.js +95 -0
- package/core/bvh2/bvh3/query/BVHQuery.js +11 -0
- package/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +36 -0
- package/core/bvh2/bvh3/query/BVHQueryIntersectsRay.js +36 -0
- package/core/collection/array/copyArray.js +2 -2
- package/core/collection/table/RowFirstTable.js +25 -7
- package/core/collection/table/RowFirstTableSpec.js +4 -4
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +1 -1
- package/{engine/graphics/util → core/geom/3d/aabb}/computeBoundingBoxFromVertexData.js +1 -1
- package/core/geom/3d/compose_matrix4_array.js +53 -0
- package/{engine/graphics/util → core/geom/3d}/decompose_matrix_4_array.js +0 -0
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/Vector1.js +2 -3
- package/core/geom/Vector3.js +5 -1
- package/core/process/undo/ActionProcessor.js +31 -3
- package/core/process/undo/ActionProcessor.spec.js +1 -1
- package/engine/animation/curve/AnimationCurve.js +40 -1
- package/engine/animation/curve/Keyframe.js +19 -0
- package/engine/animation/curve/compression/animation_curve_to_float_array.js +35 -0
- package/engine/animation/curve/compression/downsample_float_array.js +50 -0
- package/engine/animation/curve/compression/downsample_float_array_curve_by_error.js +147 -0
- package/engine/animation/curve/compression/downsample_float_array_curve_by_error.spec.js +47 -0
- package/engine/animation/curve/compression/prototypeCurveCompression.js +154 -0
- package/engine/animation/curve/draw/build_curve_editor.js +316 -0
- package/engine/animation/curve/draw/build_plot_entity_from_array.js +47 -0
- package/engine/animation/curve/draw/build_tangent_editor.js +115 -0
- package/engine/animation/curve/draw/draw_grid.js +27 -0
- package/engine/animation/curve/draw/draw_label.js +17 -0
- package/engine/animation/curve/draw/plot_array.js +76 -0
- package/engine/animation/curve/draw/plot_data.js +49 -0
- package/engine/asset/loaders/GLTFAssetLoader.js +3 -0
- package/engine/asset/loaders/gltf/GLTFAssetTransformMikkTSpaceTangents.js +27 -0
- package/engine/ecs/EntityComponentDataset.js +7 -4
- package/engine/ecs/foliage/InstancedFoliage.js +1 -1
- package/engine/ecs/foliage/ViewState.js +1 -1
- package/engine/ecs/parent/EntityNode.d.ts +7 -3
- package/engine/ecs/parent/EntityNode.js +21 -0
- package/engine/ecs/parent/entity_node_compute_bounding_box.js +41 -0
- package/engine/ecs/transform/Transform.js +2 -2
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +5 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +46 -12
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +81 -95
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +16 -5
- package/engine/graphics/ecs/mesh-v2/render/adapters/InstancedRendererAdapter.js +2 -0
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +1 -0
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +3 -4
- 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/computeFrenetFrames.js +1 -2
- 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/MikkT/MikkTSpace.js +2210 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.spec.js +22 -0
- package/engine/graphics/geometry/MikkT/buffer_geometry_ensure_tangents.js +34 -0
- package/engine/graphics/geometry/MikkT/buffer_geometry_generate_tangents.js +28 -0
- package/engine/graphics/{compute_geometry_polycount.js → geometry/compute_geometry_polycount.js} +0 -0
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -3
- package/engine/graphics/geometry/skining/computeSkinnedMeshBoundingVolumes.js +1 -1
- package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.js +83 -0
- package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.spec.js +24 -0
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +42 -19
- package/engine/graphics/micron/plugin/GLTF_MICRON_ID_FIELD.js +5 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -4
- package/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +10 -0
- package/engine/graphics/micron/prototypeVirtualGeometry.js +5 -3
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +2 -2
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +2 -2
- package/engine/graphics/micron/render/v1/MicronRenderContext.js +0 -6
- package/engine/graphics/render/forward_plus/LightManager.js +3 -1
- package/engine/graphics/util/composeMatrix4.js +1 -53
- package/engine/graphics/util/composeMatrix4RotationScale.js +1 -1
- package/engine/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
- package/engine/intelligence/blackboard/AbstractBlackboard.js +9 -0
- package/engine/notify/Notification.js +1 -1
- package/engine/ui/DraggableAspect.js +4 -1
- package/engine/ui/notification/ViewEmitter.js +7 -1
- package/engine/ui/notification/notificationGenerator.js +1 -1
- package/engine/ui/scene/SceneGUIContext.js +11 -130
- package/engine/ui/scene/initializeNotifications.js +141 -0
- package/package.json +1 -1
- package/view/elements/notify/NotificationView.js +1 -2
|
@@ -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
|
}
|