@woosh/meep-engine 2.131.28 → 2.131.30
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/package.json +1 -1
- package/src/core/bvh2/bvh3/BVH.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/BVH.js +16 -0
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +1 -4
- package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.d.ts +1 -1
- package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.d.ts.map +1 -1
- package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.js +145 -211
- package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.d.ts +1 -1
- package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.js +1 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "Pure JavaScript game engine. Fully featured and production ready.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.131.
|
|
8
|
+
"version": "2.131.30",
|
|
9
9
|
"main": "build/meep.module.js",
|
|
10
10
|
"module": "build/meep.module.js",
|
|
11
11
|
"exports": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BVH.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/BVH.js"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BVH.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/BVH.js"],"names":[],"mappings":"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"}
|
|
@@ -254,6 +254,22 @@ export class BVH {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Allocates specified number of nodes linearly.
|
|
259
|
+
* Can only be used when the tree is explicitly empty, call {@link release_all} to achieve that.
|
|
260
|
+
* Nodes from 0 through to count - 1 will be allocated, and you can use them immediately.
|
|
261
|
+
*
|
|
262
|
+
* This method is intended for static builds mainly, where we know ahead of time how many nodes we will need, and we want to avoid per-node allocation overhead.
|
|
263
|
+
* @param {number} node_count
|
|
264
|
+
*/
|
|
265
|
+
allocate_linear(node_count) {
|
|
266
|
+
assert.isNonNegativeInteger(node_count, 'node_count');
|
|
267
|
+
assert.equal(this.__size, 0, 'Tree is not empty');
|
|
268
|
+
|
|
269
|
+
this.node_capacity = node_count;
|
|
270
|
+
this.__size = node_count;
|
|
271
|
+
}
|
|
272
|
+
|
|
257
273
|
/**
|
|
258
274
|
*
|
|
259
275
|
* @returns {number}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ebvh_build_for_geometry_morton.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js"],"names":[],"mappings":"AAWA;;;;;;;;;;GAUG;AACH,sEAPW,MAAM,EAAE,GAAC,WAAW,GAAC,WAAW,kBAChC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,WAAW,WACX,KAAK,YACL,MAAM,GACJ,IAAI,
|
|
1
|
+
{"version":3,"file":"ebvh_build_for_geometry_morton.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js"],"names":[],"mappings":"AAWA;;;;;;;;;;GAUG;AACH,sEAPW,MAAM,EAAE,GAAC,WAAW,GAAC,WAAW,kBAChC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,WAAW,WACX,KAAK,YACL,MAAM,GACJ,IAAI,CAmHhB;sBApIqB,6BAA6B"}
|
|
@@ -53,11 +53,8 @@ export function ebvh_build_for_geometry_morton(
|
|
|
53
53
|
|
|
54
54
|
const node_total_count = node_leaf_count + node_bin_count;
|
|
55
55
|
|
|
56
|
-
|
|
57
56
|
// skip allocation calls, allocate exactly as many nodes as we need
|
|
58
|
-
bvh.
|
|
59
|
-
bvh.__size = node_total_count;
|
|
60
|
-
|
|
57
|
+
bvh.allocate_linear(node_total_count);
|
|
61
58
|
|
|
62
59
|
// indices of triangles, but sorted by morton codes
|
|
63
60
|
const sorted_triangle_order = new Uint32Array(tri_count);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Implementation of FABRIK algorithm, "Forward And Backward Reaching Inverse Kinematics"
|
|
3
|
-
* This implementation deals with single chain at a time, without support for multiple effectors
|
|
3
|
+
* This implementation deals with a single chain at a time, without support for multiple effectors
|
|
4
4
|
* see "FABRIK: a fast, iterative solver for inverse kinematics"
|
|
5
5
|
* @param {number} size number of points in the chain
|
|
6
6
|
* @param {Float32Array|number[]} positions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fabrik3d_solve_primitive.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fabrik3d_solve_primitive.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,+CAZW,MAAM,aACN,YAAY,GAAC,MAAM,EAAE,WACrB,YAAY,GAAC,MAAM,EAAE,YACrB,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,mBACN,MAAM,uBACN,MAAM,QA8FhB"}
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
import { v3_array_normalize } from "../../../../core/geom/vec3/v3_array_normalize.js";
|
|
2
|
-
import { v3_displace_in_direction_array } from "../../../../core/geom/vec3/v3_displace_in_direction_array.js";
|
|
3
|
-
import { v3_distance } from "../../../../core/geom/vec3/v3_distance.js";
|
|
4
|
-
import { v3_distance_sqr } from "../../../../core/geom/vec3/v3_distance_sqr.js";
|
|
5
|
-
import { v3_length_sqr } from "../../../../core/geom/vec3/v3_length_sqr.js";
|
|
6
|
-
|
|
7
|
-
const scratch_direction = new Float32Array(3);
|
|
8
|
-
|
|
9
1
|
/**
|
|
10
2
|
* Implementation of FABRIK algorithm, "Forward And Backward Reaching Inverse Kinematics"
|
|
11
|
-
* This implementation deals with single chain at a time, without support for multiple effectors
|
|
3
|
+
* This implementation deals with a single chain at a time, without support for multiple effectors
|
|
12
4
|
* see "FABRIK: a fast, iterative solver for inverse kinematics"
|
|
13
5
|
* @param {number} size number of points in the chain
|
|
14
6
|
* @param {Float32Array|number[]} positions
|
|
@@ -37,241 +29,183 @@ export function fabrik3d_solve_primitive(
|
|
|
37
29
|
return;
|
|
38
30
|
}
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
target_x, target_y, target_z
|
|
53
|
-
);
|
|
32
|
+
// 1. Check Reachability
|
|
33
|
+
// Calculate distance to target squared first to avoid sqrt if not needed
|
|
34
|
+
const dx = target_x - origin_x;
|
|
35
|
+
const dy = target_y - origin_y;
|
|
36
|
+
const dz = target_z - origin_z;
|
|
37
|
+
const dist_sq = dx * dx + dy * dy + dz * dz;
|
|
38
|
+
|
|
39
|
+
// Calculate total length if not provided (fallback)
|
|
40
|
+
let total_chain_length = 0;
|
|
41
|
+
for (let i = 0; i < size - 1; i++) {
|
|
42
|
+
total_chain_length += lengths[i];
|
|
43
|
+
}
|
|
54
44
|
|
|
45
|
+
// Unreachable: The target is further than the total length
|
|
46
|
+
// (Compare squares to save a SQRT on the distance check)
|
|
47
|
+
if (dist_sq > total_chain_length * total_chain_length) {
|
|
48
|
+
stretch_chain(size, positions, lengths, origin_x, origin_y, origin_z, dx, dy, dz, Math.sqrt(dist_sq));
|
|
55
49
|
return;
|
|
56
50
|
}
|
|
57
51
|
|
|
52
|
+
// 2. Iteration Loop
|
|
53
|
+
const last_index = size - 1;
|
|
54
|
+
const last_offset = last_index * 3;
|
|
58
55
|
|
|
59
56
|
for (let i = 0; i < max_iterations; i++) {
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
// --- Backward Pass (Target -> Origin) ---
|
|
59
|
+
// Snap the last point to target
|
|
60
|
+
positions[last_offset] = target_x;
|
|
61
|
+
positions[last_offset + 1] = target_y;
|
|
62
|
+
positions[last_offset + 2] = target_z;
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
for (let j = last_index - 1; j >= 0; j--) {
|
|
65
|
+
const curr = j * 3;
|
|
66
|
+
const next = (j + 1) * 3;
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
// Vector from Next (fixed) to Current (to be moved)
|
|
69
|
+
// We want to move Current towards Next until distance is lengths[j]
|
|
70
|
+
const bone_len = lengths[j];
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
// close enough
|
|
72
|
-
break;
|
|
72
|
+
solve_joint(positions, curr, next, bone_len);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
// --- Forward Pass (Origin -> Target) ---
|
|
76
|
+
// Snap first point to origin
|
|
77
|
+
positions[0] = origin_x;
|
|
78
|
+
positions[1] = origin_y;
|
|
79
|
+
positions[2] = origin_z;
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
for (let j = 0; j < last_index; j++) {
|
|
82
|
+
const curr = (j + 1) * 3; // The point we are moving
|
|
83
|
+
const prev = j * 3; // The fixed point
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
* @param {number} size number of points in the chain
|
|
81
|
-
* @param {Float32Array|number[]} positions
|
|
82
|
-
* @param {Float32Array|number[]} lengths
|
|
83
|
-
* @param {number} origin_x
|
|
84
|
-
* @param {number} origin_y
|
|
85
|
-
* @param {number} origin_z
|
|
86
|
-
* @param {number} target_x
|
|
87
|
-
* @param {number} target_y
|
|
88
|
-
* @param {number} target_z
|
|
89
|
-
*/
|
|
90
|
-
function reach_out(
|
|
91
|
-
size,
|
|
92
|
-
positions,
|
|
93
|
-
lengths,
|
|
94
|
-
origin_x, origin_y, origin_z,
|
|
95
|
-
target_x, target_y, target_z,
|
|
96
|
-
) {
|
|
97
|
-
|
|
98
|
-
positions[0] = origin_x;
|
|
99
|
-
positions[1] = origin_y;
|
|
100
|
-
positions[2] = origin_z;
|
|
101
|
-
|
|
102
|
-
scratch_direction[0] = target_x - origin_x;
|
|
103
|
-
scratch_direction[1] = target_y - origin_y;
|
|
104
|
-
scratch_direction[2] = target_z - origin_z;
|
|
105
|
-
|
|
106
|
-
v3_array_normalize(scratch_direction, 0, scratch_direction, 0);
|
|
107
|
-
|
|
108
|
-
for (let i = 1; i < size; i++) {
|
|
109
|
-
const current_offset = i * 3;
|
|
110
|
-
|
|
111
|
-
const previous_offset = current_offset - 3;
|
|
112
|
-
|
|
113
|
-
const previous_x = positions[previous_offset];
|
|
114
|
-
const previous_y = positions[previous_offset + 1];
|
|
115
|
-
const previous_z = positions[previous_offset + 2];
|
|
116
|
-
|
|
117
|
-
const length = lengths[i - 1];
|
|
118
|
-
|
|
119
|
-
positions[current_offset] = previous_x + scratch_direction[0] * length;
|
|
120
|
-
positions[current_offset + 1] = previous_y + scratch_direction[1] * length;
|
|
121
|
-
positions[current_offset + 2] = previous_z + scratch_direction[2] * length;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
}
|
|
85
|
+
const bone_len = lengths[j];
|
|
125
86
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
* @param {number} size
|
|
129
|
-
* @param {number[]} lengths
|
|
130
|
-
* @param {number} origin_x
|
|
131
|
-
* @param {number} origin_y
|
|
132
|
-
* @param {number} origin_z
|
|
133
|
-
* @param {number} target_x
|
|
134
|
-
* @param {number} target_y
|
|
135
|
-
* @param {number} target_z
|
|
136
|
-
*/
|
|
137
|
-
function is_reachable(
|
|
138
|
-
size, lengths,
|
|
139
|
-
origin_x, origin_y, origin_z,
|
|
140
|
-
target_x, target_y, target_z
|
|
141
|
-
) {
|
|
142
|
-
|
|
143
|
-
let total_length = 0;
|
|
144
|
-
|
|
145
|
-
const limit = size - 1;
|
|
146
|
-
|
|
147
|
-
for (let i = 0; i < limit; i++) {
|
|
148
|
-
const x = lengths[i];
|
|
149
|
-
|
|
150
|
-
total_length += x;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const distance_to_target = v3_distance(origin_x, origin_y, origin_z, target_x, target_y, target_z);
|
|
154
|
-
|
|
155
|
-
return distance_to_target <= total_length;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Produced vector normalize(B-A)
|
|
160
|
-
* @param result
|
|
161
|
-
* @param result_offset
|
|
162
|
-
* @param positions
|
|
163
|
-
* @param offsetA
|
|
164
|
-
* @param offsetB
|
|
165
|
-
*/
|
|
166
|
-
function compute_direction(
|
|
167
|
-
result, result_offset,
|
|
168
|
-
positions, offsetA, offsetB
|
|
169
|
-
) {
|
|
170
|
-
|
|
171
|
-
const ax = positions[offsetA];
|
|
172
|
-
const ay = positions[offsetA + 1];
|
|
173
|
-
const az = positions[offsetA + 2];
|
|
174
|
-
|
|
175
|
-
const bx = positions[offsetB];
|
|
176
|
-
const by = positions[offsetB + 1];
|
|
177
|
-
const bz = positions[offsetB + 2];
|
|
178
|
-
|
|
179
|
-
const dx = bx - ax;
|
|
180
|
-
const dy = by - ay;
|
|
181
|
-
const dz = bz - az;
|
|
87
|
+
solve_joint(positions, curr, prev, bone_len);
|
|
88
|
+
}
|
|
182
89
|
|
|
183
|
-
|
|
90
|
+
// --- Check Tolerance ---
|
|
91
|
+
const tip_x = positions[last_offset];
|
|
92
|
+
const tip_y = positions[last_offset + 1];
|
|
93
|
+
const tip_z = positions[last_offset + 2];
|
|
184
94
|
|
|
185
|
-
|
|
186
|
-
|
|
95
|
+
const delta_x = tip_x - target_x;
|
|
96
|
+
const delta_y = tip_y - target_y;
|
|
97
|
+
const delta_z = tip_z - target_z;
|
|
187
98
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
99
|
+
const dist_to_target_sq =
|
|
100
|
+
delta_x * delta_x
|
|
101
|
+
+ delta_y * delta_y
|
|
102
|
+
+ delta_z * delta_z;
|
|
192
103
|
|
|
193
|
-
|
|
104
|
+
if (dist_to_target_sq <= distance_tolerance) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
194
107
|
}
|
|
195
108
|
|
|
196
|
-
const m = 1 / Math.sqrt(length_sqr);
|
|
197
|
-
|
|
198
|
-
result[result_offset + 0] = dx * m;
|
|
199
|
-
result[result_offset + 1] = dy * m;
|
|
200
|
-
result[result_offset + 2] = dz * m;
|
|
201
109
|
}
|
|
202
110
|
|
|
203
|
-
|
|
204
111
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
112
|
+
* Inline-friendly helper to project point 'curr' onto the line starting at 'anchor'
|
|
113
|
+
* such that the distance between them becomes 'length'.
|
|
207
114
|
* @param {Float32Array} positions
|
|
208
|
-
* @param {
|
|
209
|
-
* @param {number}
|
|
210
|
-
* @param {number}
|
|
211
|
-
* @param {number} origin_z
|
|
115
|
+
* @param {number} curr_ptr
|
|
116
|
+
* @param {number} anchor_ptr
|
|
117
|
+
* @param {number} length
|
|
212
118
|
*/
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
119
|
+
function solve_joint(
|
|
120
|
+
positions,
|
|
121
|
+
curr_ptr,
|
|
122
|
+
anchor_ptr,
|
|
123
|
+
length
|
|
124
|
+
) {
|
|
125
|
+
const ax = positions[anchor_ptr];
|
|
126
|
+
const ay = positions[anchor_ptr + 1];
|
|
127
|
+
const az = positions[anchor_ptr + 2];
|
|
128
|
+
|
|
129
|
+
const cx = positions[curr_ptr];
|
|
130
|
+
const cy = positions[curr_ptr + 1];
|
|
131
|
+
const cz = positions[curr_ptr + 2];
|
|
132
|
+
|
|
133
|
+
// Vector from Anchor -> Current
|
|
134
|
+
const dx = cx - ax;
|
|
135
|
+
const dy = cy - ay;
|
|
136
|
+
const dz = cz - az;
|
|
137
|
+
|
|
138
|
+
const len_sq = dx * dx + dy * dy + dz * dz;
|
|
139
|
+
|
|
140
|
+
if (len_sq < 1e-15) {
|
|
141
|
+
// Prevent division by zero / singularity
|
|
142
|
+
// If points overlap perfectly, pick arbitrary direction (Z-axis)
|
|
143
|
+
positions[curr_ptr] = ax;
|
|
144
|
+
positions[curr_ptr + 1] = ay;
|
|
145
|
+
positions[curr_ptr + 2] = az + length;
|
|
146
|
+
}else {
|
|
147
|
+
|
|
148
|
+
// Math: NewPos = Anchor + (Direction * Length)
|
|
149
|
+
// Direction = Vector / CurrentLength
|
|
150
|
+
// NewPos = Anchor + Vector * (Length / CurrentLength)
|
|
151
|
+
// We use inverse sqrt for speed if available, or just standard math
|
|
152
|
+
|
|
153
|
+
const scale = length / Math.sqrt(len_sq);
|
|
154
|
+
|
|
155
|
+
positions[curr_ptr] = ax + dx * scale;
|
|
156
|
+
positions[curr_ptr + 1] = ay + dy * scale;
|
|
157
|
+
positions[curr_ptr + 2] = az + dz * scale;
|
|
237
158
|
}
|
|
238
|
-
|
|
239
159
|
}
|
|
240
160
|
|
|
241
161
|
/**
|
|
242
|
-
*
|
|
162
|
+
* Handle unreachable target by stretching chain in a straight line
|
|
243
163
|
* @param {number} size
|
|
244
164
|
* @param {Float32Array} positions
|
|
245
|
-
* @param {Float32Array
|
|
246
|
-
* @param {number}
|
|
247
|
-
* @param {number}
|
|
248
|
-
* @param {number}
|
|
165
|
+
* @param {Float32Array} lengths
|
|
166
|
+
* @param {number} ox
|
|
167
|
+
* @param {number} oy
|
|
168
|
+
* @param {number} oz
|
|
169
|
+
* @param {number} dx
|
|
170
|
+
* @param {number} dy
|
|
171
|
+
* @param {number} dz
|
|
172
|
+
* @param {number} current_dist
|
|
249
173
|
*/
|
|
250
|
-
function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
positions[last_address + 1] = target_y;
|
|
259
|
-
positions[last_address + 2] = target_z;
|
|
260
|
-
|
|
261
|
-
for (let i = last_index - 1; i >= 0; i--) {
|
|
262
|
-
const current_address = i * 3;
|
|
263
|
-
const next_address = current_address + 3;
|
|
264
|
-
|
|
265
|
-
compute_direction(
|
|
266
|
-
scratch_direction, 0,
|
|
267
|
-
positions, next_address, current_address
|
|
268
|
-
);
|
|
174
|
+
function stretch_chain(
|
|
175
|
+
size,
|
|
176
|
+
positions,
|
|
177
|
+
lengths,
|
|
178
|
+
ox, oy, oz,
|
|
179
|
+
dx, dy, dz,
|
|
180
|
+
current_dist
|
|
181
|
+
) {
|
|
269
182
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
183
|
+
// Normalize direction
|
|
184
|
+
const inv_dist = 1.0 / current_dist;
|
|
185
|
+
const nx = dx * inv_dist;
|
|
186
|
+
const ny = dy * inv_dist;
|
|
187
|
+
const nz = dz * inv_dist;
|
|
188
|
+
|
|
189
|
+
// Reset origin
|
|
190
|
+
positions[0] = ox;
|
|
191
|
+
positions[1] = oy;
|
|
192
|
+
positions[2] = oz;
|
|
193
|
+
|
|
194
|
+
let prev_x = ox;
|
|
195
|
+
let prev_y = oy;
|
|
196
|
+
let prev_z = oz;
|
|
197
|
+
|
|
198
|
+
for (let i = 0; i < size - 1; i++) {
|
|
199
|
+
const len = lengths[i];
|
|
200
|
+
const next_offset = (i + 1) * 3;
|
|
201
|
+
|
|
202
|
+
// Move point along the line
|
|
203
|
+
prev_x += nx * len;
|
|
204
|
+
prev_y += ny * len;
|
|
205
|
+
prev_z += nz * len;
|
|
206
|
+
|
|
207
|
+
positions[next_offset] = prev_x;
|
|
208
|
+
positions[next_offset + 1] = prev_y;
|
|
209
|
+
positions[next_offset + 2] = prev_z;
|
|
276
210
|
}
|
|
277
211
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Note that bones are defined as a combination of Joint ({@link Transform}) and bone length. Joint defines the origin of the bone.
|
|
3
3
|
* Last joint's position is expected to be bone_length distance from the target if target is reachable and be oriented towards that target ({@link Transform.lookAt})
|
|
4
4
|
* @param {Transform[]} joints Will be updated as a result of the solve
|
|
5
|
-
* @param {number[]} lengths distance to next bone
|
|
5
|
+
* @param {number[]} lengths distance to next bone, bone lengths.
|
|
6
6
|
* @param {Vector3} origin where should the first joint be placed at
|
|
7
7
|
* @param {Vector3} target where should the last joint be placed at
|
|
8
8
|
* @param {number} [max_iterations] More steps will lead to higher accuracy, but at the cost of computation. Generally solution will be reached in just a few iteration so this is just a ceiling
|
|
@@ -13,7 +13,7 @@ const scratch_quat = new Quaternion();
|
|
|
13
13
|
* Note that bones are defined as a combination of Joint ({@link Transform}) and bone length. Joint defines the origin of the bone.
|
|
14
14
|
* Last joint's position is expected to be bone_length distance from the target if target is reachable and be oriented towards that target ({@link Transform.lookAt})
|
|
15
15
|
* @param {Transform[]} joints Will be updated as a result of the solve
|
|
16
|
-
* @param {number[]} lengths distance to next bone
|
|
16
|
+
* @param {number[]} lengths distance to next bone, bone lengths.
|
|
17
17
|
* @param {Vector3} origin where should the first joint be placed at
|
|
18
18
|
* @param {Vector3} target where should the last joint be placed at
|
|
19
19
|
* @param {number} [max_iterations] More steps will lead to higher accuracy, but at the cost of computation. Generally solution will be reached in just a few iteration so this is just a ceiling
|