@woosh/meep-engine 2.110.7 → 2.110.9

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.
Files changed (189) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/build/meep.cjs +115 -119
  3. package/build/meep.min.js +1 -1
  4. package/build/meep.module.js +115 -119
  5. package/editor/tools/v2/TransformControls.js +11 -6
  6. package/package.json +2 -1
  7. package/src/core/UUID.d.ts +3 -0
  8. package/src/core/UUID.d.ts.map +1 -1
  9. package/src/core/UUID.js +9 -7
  10. package/src/core/collection/array/arraySetDiff.d.ts.map +1 -1
  11. package/src/core/collection/array/arraySetDiff.js +0 -1
  12. package/src/core/collection/array/binarySearchHighIndex.d.ts.map +1 -1
  13. package/src/core/collection/array/binarySearchHighIndex.js +7 -1
  14. package/src/core/collection/array/computeHashArray.d.ts.map +1 -1
  15. package/src/core/collection/array/computeHashArray.js +3 -2
  16. package/src/core/collection/array/fastArrayEquals.d.ts +1 -0
  17. package/src/core/collection/array/fastArrayEquals.d.ts.map +1 -1
  18. package/src/core/collection/array/fastArrayEquals.js +1 -0
  19. package/src/core/collection/array/isArrayEqual.d.ts.map +1 -1
  20. package/src/core/collection/array/isArrayEqual.js +9 -12
  21. package/src/core/collection/array/isArrayEqual.spec.d.ts +2 -0
  22. package/src/core/collection/array/isArrayEqual.spec.d.ts.map +1 -0
  23. package/src/core/collection/array/isArrayEqual.spec.js +25 -0
  24. package/src/core/collection/array/typed/is_typed_array_equals.d.ts.map +1 -1
  25. package/src/core/collection/array/typed/is_typed_array_equals.js +1 -0
  26. package/src/core/function/makeSequenceLoop.d.ts.map +1 -0
  27. package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
  28. package/src/core/geom/3d/shape/AbstractShape3D.js +14 -0
  29. package/src/core/geom/3d/shape/PointShape3D.d.ts +9 -0
  30. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -0
  31. package/src/core/geom/3d/shape/PointShape3D.js +14 -0
  32. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  33. package/src/core/geom/3d/shape/TransformedShape3D.js +26 -8
  34. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  35. package/src/core/geom/3d/shape/UnionShape3D.js +33 -4
  36. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  37. package/src/core/geom/3d/shape/UnitCubeShape3D.js +13 -6
  38. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  39. package/src/core/geom/3d/shape/UnitSphereShape3D.js +10 -0
  40. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.d.ts +15 -8
  41. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.d.ts.map +1 -1
  42. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.js +33 -9
  43. package/src/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.d.ts +1 -1
  44. package/src/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.d.ts.map +1 -1
  45. package/src/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +7 -7
  46. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.spec.d.ts +2 -0
  47. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.spec.d.ts.map +1 -0
  48. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.spec.js +38 -0
  49. package/src/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +42 -39
  50. package/src/core/geom/3d/v3_compute_triangle_normal.js +1 -1
  51. package/src/core/geom/3d/v3_negate_array.d.ts +9 -0
  52. package/src/core/geom/3d/v3_negate_array.d.ts.map +1 -0
  53. package/src/core/geom/3d/v3_negate_array.js +16 -0
  54. package/src/core/geom/Quaternion.d.ts.map +1 -1
  55. package/src/core/geom/Quaternion.js +30 -77
  56. package/src/core/geom/Vector3.d.ts +4 -0
  57. package/src/core/geom/Vector3.js +4 -4
  58. package/src/core/geom/vec3/v3_cross_array.d.ts +11 -0
  59. package/src/core/geom/vec3/v3_cross_array.d.ts.map +1 -0
  60. package/src/core/geom/vec3/v3_cross_array.js +31 -0
  61. package/src/core/geom/vec3/v3_displace_in_direction.js +3 -2
  62. package/src/core/geom/vec3/v3_displace_in_direction_array.d.ts +12 -0
  63. package/src/core/geom/vec3/v3_displace_in_direction_array.d.ts.map +1 -0
  64. package/src/core/geom/vec3/v3_displace_in_direction_array.js +22 -0
  65. package/src/core/geom/vec3/v3_dot_array_array.d.ts.map +1 -1
  66. package/src/core/geom/vec3/v3_dot_array_array.js +4 -1
  67. package/src/core/geom/vec3/v3_normalize_array.d.ts +3 -3
  68. package/src/core/geom/vec3/v3_normalize_array.d.ts.map +1 -1
  69. package/src/core/geom/vec3/v3_normalize_array.js +3 -3
  70. package/src/core/math/copysign.d.ts +1 -1
  71. package/src/core/math/copysign.js +1 -1
  72. package/src/core/math/epsilonEquals.d.ts.map +1 -1
  73. package/src/core/math/epsilonEquals.js +3 -2
  74. package/src/core/math/linalg/README.md +1 -1
  75. package/src/core/math/random/randomGaussian.spec.js +1 -1
  76. package/src/core/math/spline/spline_hermite3.d.ts +1 -1
  77. package/src/core/math/spline/spline_hermite3.js +1 -1
  78. package/src/core/process/delay.d.ts +6 -1
  79. package/src/core/process/delay.d.ts.map +1 -1
  80. package/src/core/process/delay.js +6 -1
  81. package/src/core/process/undo/Mark.d.ts +5 -5
  82. package/src/core/process/undo/Mark.d.ts.map +1 -1
  83. package/src/core/process/undo/Mark.js +6 -5
  84. package/src/core/process/worker/WorkerBuilder.d.ts +13 -2
  85. package/src/core/process/worker/WorkerBuilder.d.ts.map +1 -1
  86. package/src/core/process/worker/WorkerBuilder.js +9 -1
  87. package/src/core/process/worker/WorkerProxy.d.ts +16 -6
  88. package/src/core/process/worker/WorkerProxy.d.ts.map +1 -1
  89. package/src/core/process/worker/WorkerProxy.js +24 -5
  90. package/src/core/process/worker/extractTransferables.d.ts.map +1 -1
  91. package/src/core/process/worker/extractTransferables.js +3 -1
  92. package/src/engine/EngineHarness.d.ts +7 -1
  93. package/src/engine/EngineHarness.d.ts.map +1 -1
  94. package/src/engine/EngineHarness.js +12 -1
  95. package/src/engine/animation/clip/AnimationTrack.d.ts.map +1 -1
  96. package/src/engine/animation/clip/AnimationTrack.js +3 -0
  97. package/src/engine/animation/clip/bind_property_writer.d.ts +2 -2
  98. package/src/engine/animation/clip/bind_property_writer.d.ts.map +1 -1
  99. package/src/engine/animation/clip/bind_property_writer.js +22 -13
  100. package/src/engine/animation/clip/curve_from_track_data.d.ts.map +1 -1
  101. package/src/engine/animation/clip/curve_from_track_data.js +9 -1
  102. package/src/engine/animation/clip/ecd_bind_animation_curve.d.ts.map +1 -1
  103. package/src/engine/animation/clip/ecd_bind_animation_curve.js +6 -5
  104. package/src/engine/animation/curve/AnimationCurve.d.ts +21 -0
  105. package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
  106. package/src/engine/animation/curve/AnimationCurve.js +43 -15
  107. package/src/engine/animation/curve/AnimationCurve.spec.js +67 -0
  108. package/src/engine/animation/curve/Keyframe.d.ts +24 -3
  109. package/src/engine/animation/curve/Keyframe.d.ts.map +1 -1
  110. package/src/engine/animation/curve/Keyframe.js +49 -3
  111. package/src/engine/animation/curve/Keyframe.spec.js +11 -0
  112. package/src/engine/animation/curve/animation_curve_compute_aabb.d.ts +7 -0
  113. package/src/engine/animation/curve/animation_curve_compute_aabb.d.ts.map +1 -0
  114. package/src/engine/animation/curve/{compute_curve_aabb.js → animation_curve_compute_aabb.js} +1 -1
  115. package/src/engine/animation/curve/animation_curve_optimize.d.ts +8 -0
  116. package/src/engine/animation/curve/animation_curve_optimize.d.ts.map +1 -0
  117. package/src/engine/animation/curve/animation_curve_optimize.js +89 -0
  118. package/src/engine/animation/curve/animation_curve_optimize.spec.d.ts +2 -0
  119. package/src/engine/animation/curve/animation_curve_optimize.spec.d.ts.map +1 -0
  120. package/src/engine/animation/curve/animation_curve_optimize.spec.js +50 -0
  121. package/src/engine/animation/curve/draw/build_curve_editor.js +2 -2
  122. package/src/engine/animation/curve/evaluate_two_key_curve.d.ts +9 -0
  123. package/src/engine/animation/curve/evaluate_two_key_curve.d.ts.map +1 -0
  124. package/src/engine/animation/curve/evaluate_two_key_curve.js +23 -0
  125. package/src/engine/animation/curve/prototypeGLTF.js +14 -14
  126. package/src/engine/asset/loaders/material/computeTextureEquality.d.ts.map +1 -1
  127. package/src/engine/asset/loaders/material/computeTextureEquality.js +4 -6
  128. package/src/engine/asset/loaders/material/computeTextureHash.d.ts.map +1 -1
  129. package/src/engine/asset/loaders/material/computeTextureHash.js +6 -6
  130. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescription.d.ts +6 -1
  131. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescription.d.ts.map +1 -1
  132. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescription.js +11 -6
  133. package/src/engine/ecs/guid/GUIDSerializationAdapter.spec.js +5 -5
  134. package/src/engine/ecs/guid/{GUID.d.ts → UUID.d.ts} +17 -12
  135. package/src/engine/ecs/guid/UUID.d.ts.map +1 -0
  136. package/src/engine/ecs/guid/{GUID.js → UUID.js} +35 -12
  137. package/src/engine/ecs/guid/UUID.spec.d.ts +2 -0
  138. package/src/engine/ecs/guid/UUID.spec.d.ts.map +1 -0
  139. package/src/engine/ecs/guid/{GUID.spec.js → UUID.spec.js} +18 -12
  140. package/src/engine/ecs/guid/UUIDSerializationAdapter.d.ts +18 -0
  141. package/src/engine/ecs/guid/UUIDSerializationAdapter.d.ts.map +1 -0
  142. package/src/engine/ecs/guid/{GUIDSerializationAdapter.js → UUIDSerializationAdapter.js} +5 -5
  143. package/src/engine/ecs/ik/InverseKinematics.js +3 -3
  144. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts.map +1 -1
  145. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +1 -140
  146. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +1 -1
  147. package/src/engine/graphics/material/manager/MaterialManager.d.ts.map +1 -1
  148. package/src/engine/graphics/texture/isImageBitmap.d.ts +7 -0
  149. package/src/engine/graphics/texture/isImageBitmap.d.ts.map +1 -0
  150. package/src/engine/graphics/texture/isImageBitmap.js +12 -0
  151. package/src/engine/graphics/trail/x/RibbonXPlugin.d.ts.map +1 -1
  152. package/src/engine/graphics/trail/x/RibbonXPlugin.js +9 -1
  153. package/src/engine/input/ecs/systems/InputControllerSystem.js +1 -1
  154. package/src/engine/intelligence/blackboard/BlackboardDynamicStorageAdapter.d.ts +1 -1
  155. package/src/engine/intelligence/blackboard/BlackboardDynamicStorageAdapter.js +4 -4
  156. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +13 -0
  157. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -0
  158. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +395 -0
  159. package/src/engine/physics/gjk/expanding_polytope_algorithm.spec.d.ts +2 -0
  160. package/src/engine/physics/gjk/expanding_polytope_algorithm.spec.d.ts.map +1 -0
  161. package/src/engine/physics/gjk/expanding_polytope_algorithm.spec.js +46 -0
  162. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.d.ts +18 -0
  163. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.d.ts.map +1 -0
  164. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.js +277 -0
  165. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.spec.d.ts +2 -0
  166. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.spec.d.ts.map +1 -0
  167. package/src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.spec.js +43 -0
  168. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.d.ts +12 -0
  169. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.d.ts.map +1 -0
  170. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.js +100 -0
  171. package/src/engine/physics/inverse_kinematics/fabrik/prototype.d.ts +2 -0
  172. package/src/engine/physics/inverse_kinematics/fabrik/prototype.d.ts.map +1 -0
  173. package/src/engine/physics/inverse_kinematics/fabrik/prototype.js +112 -0
  174. package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts +16 -0
  175. package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts.map +1 -0
  176. package/src/engine/physics/inverse_kinematics/two_joint_ik.js +127 -0
  177. package/src/view/elements/DropDownSelectionView.js +2 -2
  178. package/src/view/elements/tiles2d/Tile.d.ts.map +1 -1
  179. package/src/view/elements/tiles2d/Tile.js +2 -3
  180. package/src/core/math/makeSequenceLoop.d.ts.map +0 -1
  181. package/src/engine/animation/curve/compute_curve_aabb.d.ts +0 -7
  182. package/src/engine/animation/curve/compute_curve_aabb.d.ts.map +0 -1
  183. package/src/engine/ecs/guid/GUID.d.ts.map +0 -1
  184. package/src/engine/ecs/guid/GUID.spec.d.ts +0 -2
  185. package/src/engine/ecs/guid/GUID.spec.d.ts.map +0 -1
  186. package/src/engine/ecs/guid/GUIDSerializationAdapter.d.ts +0 -18
  187. package/src/engine/ecs/guid/GUIDSerializationAdapter.d.ts.map +0 -1
  188. /package/src/core/{math → function}/makeSequenceLoop.d.ts +0 -0
  189. /package/src/core/{math → function}/makeSequenceLoop.js +0 -0
@@ -0,0 +1,277 @@
1
+ import { v3_displace_in_direction_array } from "../../../../core/geom/vec3/v3_displace_in_direction_array.js";
2
+ import { v3_distance } from "../../../../core/geom/vec3/v3_distance.js";
3
+ import { v3_distance_sqr } from "../../../../core/geom/vec3/v3_distance_sqr.js";
4
+ import { v3_length_sqr } from "../../../../core/geom/vec3/v3_length_sqr.js";
5
+ import { v3_normalize_array } from "../../../../core/geom/vec3/v3_normalize_array.js";
6
+
7
+ const scratch_direction = new Float32Array(3);
8
+
9
+ /**
10
+ * 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
12
+ * see "FABRIK: a fast, iterative solver for inverse kinematics"
13
+ * @param {number} size number of points in the chain
14
+ * @param {Float32Array|number[]} positions
15
+ * @param {Float32Array|number[]} lengths
16
+ * @param {number} origin_x
17
+ * @param {number} origin_y
18
+ * @param {number} origin_z
19
+ * @param {number} target_x
20
+ * @param {number} target_y
21
+ * @param {number} target_z
22
+ * @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
23
+ * @param {number} [distance_tolerance] Minimum squared distance to be achieved to the target, used to terminate earlier before maximum number of iterations is reached
24
+ */
25
+ export function fabrik3d_solve_primitive(
26
+ size,
27
+ positions,
28
+ lengths,
29
+ origin_x, origin_y, origin_z,
30
+ target_x, target_y, target_z,
31
+ max_iterations = 4,
32
+ distance_tolerance = 1e-7
33
+ ) {
34
+
35
+ if (size === 0) {
36
+ // nothing to solve, chain has insufficient number of joints
37
+ return;
38
+ }
39
+
40
+ if (
41
+ !is_reachable(
42
+ size, lengths,
43
+ origin_x, origin_y, origin_z,
44
+ target_x, target_y, target_z)
45
+ ) {
46
+ // target is not reachable, so stretch out the chain towards it instead
47
+ reach_out(
48
+ size,
49
+ positions,
50
+ lengths,
51
+ origin_x, origin_y, origin_z,
52
+ target_x, target_y, target_z
53
+ );
54
+
55
+ return;
56
+ }
57
+
58
+
59
+ for (let i = 0; i < max_iterations; i++) {
60
+
61
+ solve_backward(size, positions, lengths, target_x, target_y, target_z);
62
+ solve_forward(size, positions, lengths, origin_x, origin_y, origin_z);
63
+
64
+ const last_join_address = (size - 1) * 3;
65
+
66
+ const last_joint_x = positions[last_join_address];
67
+ const last_joint_y = positions[last_join_address + 1];
68
+ const last_joint_z = positions[last_join_address + 2];
69
+
70
+ if (v3_distance_sqr(last_joint_x, last_joint_y, last_joint_z, target_x, target_y, target_z) <= distance_tolerance) {
71
+ // close enough
72
+ break;
73
+ }
74
+
75
+ }
76
+
77
+ }
78
+
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_normalize_array(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
+ }
125
+
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;
182
+
183
+ const length_sqr = v3_length_sqr(dx, dy, dz);
184
+
185
+ if (length_sqr === 0) {
186
+ // TODO use random point on a sphere to prevent pathology
187
+
188
+ // points are on top of each other, set arbitrary direction
189
+ result[result_offset + 0] = 0;
190
+ result[result_offset + 1] = 0;
191
+ result[result_offset + 2] = 1;
192
+
193
+ return;
194
+ }
195
+
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
+ }
202
+
203
+
204
+ /**
205
+ *
206
+ * @param {number} size
207
+ * @param {Float32Array} positions
208
+ * @param {Float32Array|number[]} lengths
209
+ * @param {number} origin_x
210
+ * @param {number} origin_y
211
+ * @param {number} origin_z
212
+ */
213
+ function solve_forward(size, positions, lengths, origin_x, origin_y, origin_z) {
214
+
215
+ // move first point to origin
216
+ positions[0] = origin_x;
217
+ positions[1] = origin_y;
218
+ positions[2] = origin_z;
219
+
220
+ for (let i = 1; i < size; i++) {
221
+ const current_address = i * 3;
222
+ const previous_address = current_address - 3;
223
+
224
+ compute_direction(
225
+ scratch_direction, 0,
226
+ positions, previous_address, current_address
227
+ );
228
+
229
+ const length = lengths[i - 1];
230
+
231
+ v3_displace_in_direction_array(
232
+ positions, current_address,
233
+ positions, previous_address,
234
+ scratch_direction, 0,
235
+ length
236
+ );
237
+ }
238
+
239
+ }
240
+
241
+ /**
242
+ *
243
+ * @param {number} size
244
+ * @param {Float32Array} positions
245
+ * @param {Float32Array|number[]} lengths
246
+ * @param {number} target_x
247
+ * @param {number} target_y
248
+ * @param {number} target_z
249
+ */
250
+ function solve_backward(size, positions, lengths, target_x, target_y, target_z) {
251
+
252
+ const last_index = size - 1;
253
+
254
+ // move last point to target
255
+ const last_address = last_index * 3;
256
+
257
+ positions[last_address] = target_x;
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
+ );
269
+
270
+ v3_displace_in_direction_array(
271
+ positions, current_address,
272
+ positions, next_address,
273
+ scratch_direction, 0,
274
+ lengths[i]
275
+ )
276
+ }
277
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fabrik3d_solve_primitive.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fabrik3d_solve_primitive.spec.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/inverse_kinematics/fabrik/fabrik3d_solve_primitive.spec.js"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ import { fabrik3d_solve_primitive } from "./fabrik3d_solve_primitive.js";
2
+
3
+ test("0 size chain solve should succeed", () => {
4
+
5
+ fabrik3d_solve_primitive(
6
+ 0, [], [],
7
+ 0, 0, 0,
8
+ 0, 0, 1
9
+ );
10
+
11
+ });
12
+
13
+ test("1 joint chain", () => {
14
+
15
+ const positions = [-1, -1, -1];
16
+
17
+ fabrik3d_solve_primitive(
18
+ 1, positions, [1],
19
+ 1, 2, 3,
20
+ 0, 0, 1
21
+ );
22
+
23
+ expect(positions).toEqual([1, 2, 3]);
24
+ });
25
+
26
+ test("2 joint chain", () => {
27
+ const positions = [
28
+ -1, -1, -1,
29
+ -1, -1, -1,
30
+ ];
31
+
32
+ fabrik3d_solve_primitive(
33
+ 2, positions, [1, 1],
34
+ 1, 2, 3,
35
+ 2, 2, 3
36
+ );
37
+
38
+ expect(positions).toEqual([
39
+ 1, 2, 3,
40
+ 2, 2, 3
41
+ ]);
42
+
43
+ });
@@ -0,0 +1,12 @@
1
+ /**
2
+ *
3
+ * @param {Transform[]} joints
4
+ * @param {number[]} lengths distance to next bone
5
+ * @param {Vector3} origin where should the first joint be placed at
6
+ * @param {Vector3} target where should the last joint be placed at
7
+ * @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
8
+ * @param {number} [distance_tolerance] Minimum squared distance to be achieved to the target, used to terminate earlier before maximum number of iterations is reached
9
+ */
10
+ export function fabrik_solve(joints: Transform[], lengths: number[], origin: Vector3, target: Vector3, max_iterations?: number, distance_tolerance?: number): void;
11
+ import Vector3 from "../../../../core/geom/Vector3.js";
12
+ //# sourceMappingURL=fabrik_solve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fabrik_solve.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.js"],"names":[],"mappings":"AAWA;;;;;;;;GAQG;AACH,qCAPW,WAAW,WACX,MAAM,EAAE,UACR,OAAO,UACP,OAAO,mBACP,MAAM,uBACN,MAAM,QAgFhB;oBAjGmB,kCAAkC"}
@@ -0,0 +1,100 @@
1
+ import Quaternion from "../../../../core/geom/Quaternion.js";
2
+ import Vector3 from "../../../../core/geom/Vector3.js";
3
+ import { fabrik3d_solve_primitive } from "./fabrik3d_solve_primitive.js";
4
+
5
+ const scratch_positions_count = 64;
6
+ const scratch_positions = new Float32Array(scratch_positions_count * 3);
7
+
8
+ const scratch_v3_0 = new Vector3();
9
+ const scratch_v3_1 = new Vector3();
10
+ const scratch_quat = new Quaternion();
11
+
12
+ /**
13
+ *
14
+ * @param {Transform[]} joints
15
+ * @param {number[]} lengths distance to next bone
16
+ * @param {Vector3} origin where should the first joint be placed at
17
+ * @param {Vector3} target where should the last joint be placed at
18
+ * @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
19
+ * @param {number} [distance_tolerance] Minimum squared distance to be achieved to the target, used to terminate earlier before maximum number of iterations is reached
20
+ */
21
+ export function fabrik_solve(
22
+ joints,
23
+ lengths,
24
+ origin,
25
+ target,
26
+ max_iterations = 4,
27
+ distance_tolerance = 1e-7
28
+ ) {
29
+
30
+ const joint_count = joints.length;
31
+
32
+ let positions;
33
+ if (joint_count <= scratch_positions_count) {
34
+ positions = scratch_positions;
35
+ } else {
36
+ positions = new Float32Array(joint_count * 3);
37
+ }
38
+
39
+ for (let i = 0; i < joint_count; i++) {
40
+ const offset = i * 3;
41
+ const joint = joints[i];
42
+
43
+ joint.position.toArray(positions, offset);
44
+ }
45
+
46
+ fabrik3d_solve_primitive(
47
+ joint_count,
48
+ positions,
49
+ lengths,
50
+ origin.x, origin.y, origin.z,
51
+ target.x, target.y, target.z,
52
+ max_iterations, distance_tolerance
53
+ );
54
+
55
+ // apply rotation
56
+ for (let i = 1; i < joint_count; i++) {
57
+ const current_joint = joints[i];
58
+ const previous_joint = joints[i - 1];
59
+
60
+ const i3 = i * 3;
61
+
62
+ const previous_x = positions[i3 - 3];
63
+ const previous_y = positions[i3 - 2];
64
+ const previous_z = positions[i3 - 1];
65
+
66
+ const current_x = positions[i3];
67
+ const current_y = positions[i3 + 1];
68
+ const current_z = positions[i3 + 2];
69
+
70
+ scratch_v3_0.copy(current_joint.position);
71
+ scratch_v3_0.sub(previous_joint.position);
72
+
73
+ if (scratch_v3_0.lengthSqr() === 0) {
74
+ continue;
75
+ }
76
+
77
+ scratch_v3_1.set(
78
+ current_x - previous_x,
79
+ current_y - previous_y,
80
+ current_z - previous_z,
81
+ );
82
+
83
+ if (scratch_v3_1.lengthSqr() === 0) {
84
+ continue;
85
+ }
86
+
87
+ scratch_v3_0.normalize();
88
+ scratch_v3_1.normalize();
89
+
90
+ scratch_quat.fromUnitVectors(scratch_v3_0, scratch_v3_1);
91
+
92
+ previous_joint.rotation.multiplyQuaternions(scratch_quat, previous_joint.rotation);
93
+ }
94
+
95
+ // apply positions
96
+ for (let i = 0; i < joint_count; i++) {
97
+ joints[i].position.fromArray(positions, i * 3);
98
+ }
99
+ }
100
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prototype.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prototype.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/inverse_kinematics/fabrik/prototype.js"],"names":[],"mappings":""}
@@ -0,0 +1,112 @@
1
+ import { CylinderBufferGeometry, MeshStandardMaterial } from "three";
2
+ import { TransformControls } from "../../../../../editor/tools/v2/TransformControls.js";
3
+ import Vector3 from "../../../../core/geom/Vector3.js";
4
+ import { DEG_TO_RAD } from "../../../../core/math/DEG_TO_RAD.js";
5
+ import Entity from "../../../ecs/Entity.js";
6
+ import { TransformAttachmentSystem } from "../../../ecs/transform-attachment/TransformAttachmentSystem.js";
7
+ import { Transform } from "../../../ecs/transform/Transform.js";
8
+ import { EngineHarness } from "../../../EngineHarness.js";
9
+ import { ShadedGeometry } from "../../../graphics/ecs/mesh-v2/ShadedGeometry.js";
10
+ import { ShadedGeometrySystem } from "../../../graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
11
+ import InputController from "../../../input/ecs/components/InputController.js";
12
+ import InputControllerSystem from "../../../input/ecs/systems/InputControllerSystem.js";
13
+ import { BehaviorComponent } from "../../../intelligence/behavior/ecs/BehaviorComponent.js";
14
+ import { BehaviorSystem } from "../../../intelligence/behavior/ecs/BehaviorSystem.js";
15
+ import { fabrik_solve } from "./fabrik_solve.js";
16
+
17
+ EngineHarness.bootstrap({
18
+ configuration(config, engine) {
19
+ config.addSystem(new ShadedGeometrySystem(engine));
20
+ config.addSystem(new InputControllerSystem(engine.devices));
21
+ config.addSystem(new TransformAttachmentSystem());
22
+ config.addSystem(new BehaviorSystem(engine));
23
+ }
24
+ })
25
+ .then(async engine => {
26
+
27
+ const ecd = engine.entityManager.dataset;
28
+
29
+ await EngineHarness.buildBasics({
30
+ engine,
31
+ cameraController: false
32
+ });
33
+
34
+
35
+ const controls = new TransformControls(engine.graphics.camera, engine.viewStack.el);
36
+
37
+ /**
38
+ *
39
+ * @type {Entity[]}
40
+ */
41
+ const chain = [];
42
+
43
+
44
+ const link_geometry = new CylinderBufferGeometry(1, 1, 2);
45
+ link_geometry.rotateX(90 * DEG_TO_RAD);
46
+
47
+ for (let i = 0; i < 50; i++) {
48
+
49
+ const entity = new Entity()
50
+ .add(Transform.fromJSON({
51
+ position: {
52
+ x: 10,
53
+ y: 0,
54
+ z: 10
55
+ },
56
+ scale: 0.1
57
+ }));
58
+
59
+ entity.add(ShadedGeometry.from(link_geometry, new MeshStandardMaterial()));
60
+
61
+ chain.push(entity);
62
+
63
+ entity.build(ecd);
64
+ }
65
+
66
+ controls.build(ecd);
67
+ controls.attach(chain[chain.length - 1].id);
68
+
69
+ const joints = chain.map(e => e.getComponent(Transform));
70
+ const lengths = chain.map(x => 0.1);
71
+
72
+ new Entity()
73
+ .add(BehaviorComponent.looping_function(timeDelta => {
74
+ const last = joints[joints.length - 1];
75
+ const target = last.position.clone();
76
+
77
+ for (let i = 0; i < joints.length; i++) {
78
+ // gravity
79
+ joints[i].position._add(0, -9 * timeDelta, 0);
80
+ }
81
+
82
+
83
+ fabrik_solve(
84
+ joints,
85
+ lengths,
86
+ new Vector3(10, 2, 10),
87
+ target
88
+ );
89
+
90
+ last.position.copy(target);
91
+ }))
92
+ .build(ecd);
93
+
94
+ new Entity()
95
+ .add(new InputController([{
96
+ path: 'keyboard/keys/w/down',
97
+ listener() {
98
+ controls.mode = "translate"
99
+ }
100
+ }, {
101
+ path: 'keyboard/keys/e/down',
102
+ listener() {
103
+ controls.mode = "scale"
104
+ }
105
+ }, {
106
+ path: 'keyboard/keys/r/down',
107
+ listener() {
108
+ controls.mode = "rotate"
109
+ }
110
+ }]))
111
+ .build(ecd);
112
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Based on http://theorangeduck.com/page/simple-two-joint
3
+ * @param {Vector3} a Root bone position
4
+ * @param {Vector3} b Second bone position
5
+ * @param {Vector3} c Effector position
6
+ * @param {Vector3} t Target position
7
+ * @param {number} eps EPSILON value, small value for rounding error compensation
8
+ * @param {Quaternion} a_gr Global rotation of root bone
9
+ * @param {Quaternion} b_gr Global rotation of second bone
10
+ * @param {Quaternion} a_lr local rotation for root bone, this will be updated as a result
11
+ * @param {Quaternion} b_lr local rotation for second bone, this will be updated as a result
12
+ */
13
+ export function two_joint_ik(a: Vector3, b: Vector3, c: Vector3, t: Vector3, eps: number, a_gr: Quaternion, b_gr: Quaternion, a_lr: Quaternion, b_lr: Quaternion): void;
14
+ import Vector3 from "../../../core/geom/Vector3.js";
15
+ import Quaternion from "../../../core/geom/Quaternion.js";
16
+ //# sourceMappingURL=two_joint_ik.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"two_joint_ik.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/inverse_kinematics/two_joint_ik.js"],"names":[],"mappings":"AAgDA;;;;;;;;;;;GAWG;AACH,gCAVW,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,OACP,MAAM,QACN,UAAU,QACV,UAAU,QACV,UAAU,QACV,UAAU,QAoEpB;oBA5HmB,+BAA+B;uBAF5B,kCAAkC"}