@zephyr3d/scene 0.8.1 → 0.9.0

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 (241) hide show
  1. package/dist/animation/animationset.js +563 -128
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/cloth/gpu_cloth_system.js +2516 -0
  4. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -0
  5. package/dist/animation/fixed_geometry_cache_track.js +138 -0
  6. package/dist/animation/fixed_geometry_cache_track.js.map +1 -0
  7. package/dist/animation/geometry_cache_utils.js +120 -0
  8. package/dist/animation/geometry_cache_utils.js.map +1 -0
  9. package/dist/animation/ik_modifier.js +9 -1
  10. package/dist/animation/ik_modifier.js.map +1 -1
  11. package/dist/animation/joint_dynamics/collision.js +469 -0
  12. package/dist/animation/joint_dynamics/collision.js.map +1 -0
  13. package/dist/animation/joint_dynamics/constraints.js +329 -0
  14. package/dist/animation/joint_dynamics/constraints.js.map +1 -0
  15. package/dist/animation/joint_dynamics/controller.js +699 -0
  16. package/dist/animation/joint_dynamics/controller.js.map +1 -0
  17. package/dist/animation/joint_dynamics/joint_dynamics_system.js +393 -0
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -0
  19. package/dist/animation/joint_dynamics/solver.js +794 -0
  20. package/dist/animation/joint_dynamics/solver.js.map +1 -0
  21. package/dist/animation/joint_dynamics/types.js +19 -0
  22. package/dist/animation/joint_dynamics/types.js.map +1 -0
  23. package/dist/animation/joint_dynamics/vrm_spring_bone.js +46 -0
  24. package/dist/animation/joint_dynamics/vrm_spring_bone.js.map +1 -0
  25. package/dist/animation/joint_dynamics_modifier.js +51 -0
  26. package/dist/animation/joint_dynamics_modifier.js.map +1 -0
  27. package/dist/animation/pca_geometry_cache_track.js +222 -0
  28. package/dist/animation/pca_geometry_cache_track.js.map +1 -0
  29. package/dist/animation/skeleton.js +1907 -3
  30. package/dist/animation/skeleton.js.map +1 -1
  31. package/dist/animation/skeleton_modifier.js +3 -5
  32. package/dist/animation/skeleton_modifier.js.map +1 -1
  33. package/dist/animation/spring/multi_chain_spring_system.js +2 -0
  34. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  35. package/dist/animation/spring/spring_chain.js +3 -2
  36. package/dist/animation/spring/spring_chain.js.map +1 -1
  37. package/dist/animation/spring/spring_collider.js +35 -5
  38. package/dist/animation/spring/spring_collider.js.map +1 -1
  39. package/dist/animation/spring/spring_particle.js +1 -0
  40. package/dist/animation/spring/spring_particle.js.map +1 -1
  41. package/dist/animation/spring/spring_system.js +325 -28
  42. package/dist/animation/spring/spring_system.js.map +1 -1
  43. package/dist/animation/spring2/collision.js +469 -0
  44. package/dist/animation/spring2/collision.js.map +1 -0
  45. package/dist/animation/spring2/constraints.js +329 -0
  46. package/dist/animation/spring2/constraints.js.map +1 -0
  47. package/dist/animation/spring2/controller.js +434 -0
  48. package/dist/animation/spring2/controller.js.map +1 -0
  49. package/dist/animation/spring2/math.js +16 -0
  50. package/dist/animation/spring2/math.js.map +1 -0
  51. package/dist/animation/spring2/solver.js +624 -0
  52. package/dist/animation/spring2/solver.js.map +1 -0
  53. package/dist/animation/spring2/spring_system.js +118 -0
  54. package/dist/animation/spring2/spring_system.js.map +1 -0
  55. package/dist/animation/spring2/types.js +19 -0
  56. package/dist/animation/spring2/types.js.map +1 -0
  57. package/dist/animation/spring_modifier.js +17 -1
  58. package/dist/animation/spring_modifier.js.map +1 -1
  59. package/dist/app/engine.js +42 -15
  60. package/dist/app/engine.js.map +1 -1
  61. package/dist/app/runtimescript.js +132 -1
  62. package/dist/app/runtimescript.js.map +1 -1
  63. package/dist/app/screen.js +3 -3
  64. package/dist/app/screen.js.map +1 -1
  65. package/dist/app/scriptingsystem.js +69 -37
  66. package/dist/app/scriptingsystem.js.map +1 -1
  67. package/dist/app/scriptregistry.js +157 -146
  68. package/dist/app/scriptregistry.js.map +1 -1
  69. package/dist/asset/assetmanager.js +2 -1
  70. package/dist/asset/assetmanager.js.map +1 -1
  71. package/dist/asset/loaders/zabc/zabc_loader.js +570 -0
  72. package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -0
  73. package/dist/asset/model.js +192 -0
  74. package/dist/asset/model.js.map +1 -1
  75. package/dist/camera/base.js +26 -7
  76. package/dist/camera/base.js.map +1 -1
  77. package/dist/camera/camera.js +146 -24
  78. package/dist/camera/camera.js.map +1 -1
  79. package/dist/camera/fps.js +2 -2
  80. package/dist/camera/fps.js.map +1 -1
  81. package/dist/camera/orbit.js +2 -2
  82. package/dist/camera/orbit.js.map +1 -1
  83. package/dist/index.d.ts +11701 -8506
  84. package/dist/index.js +29 -8
  85. package/dist/index.js.map +1 -1
  86. package/dist/material/lambert.js +1 -1
  87. package/dist/material/lambert.js.map +1 -1
  88. package/dist/material/material.js +9 -3
  89. package/dist/material/material.js.map +1 -1
  90. package/dist/material/meshmaterial.js +54 -7
  91. package/dist/material/meshmaterial.js.map +1 -1
  92. package/dist/material/mixins/lightmodel/blinnphong.js +17 -7
  93. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  94. package/dist/material/mixins/lightmodel/lambert.js +7 -2
  95. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  96. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +108 -16
  97. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  98. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +222 -14
  99. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  100. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +24 -12
  101. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  102. package/dist/material/mixins/lit.js +11 -8
  103. package/dist/material/mixins/lit.js.map +1 -1
  104. package/dist/material/mixins/pbr/common.js +72 -5
  105. package/dist/material/mixins/pbr/common.js.map +1 -1
  106. package/dist/material/pbrblueprint.js +148 -1
  107. package/dist/material/pbrblueprint.js.map +1 -1
  108. package/dist/material/pbrmr.js +125 -2
  109. package/dist/material/pbrmr.js.map +1 -1
  110. package/dist/material/shader/helper.js +10 -4
  111. package/dist/material/shader/helper.js.map +1 -1
  112. package/dist/material/water.js +2 -2
  113. package/dist/material/water.js.map +1 -1
  114. package/dist/posteffect/coloradjust.js +145 -0
  115. package/dist/posteffect/coloradjust.js.map +1 -0
  116. package/dist/posteffect/taa.js +68 -32
  117. package/dist/posteffect/taa.js.map +1 -1
  118. package/dist/render/cluster_light.js +17 -12
  119. package/dist/render/cluster_light.js.map +1 -1
  120. package/dist/render/deferredlightpass.js +510 -0
  121. package/dist/render/deferredlightpass.js.map +1 -0
  122. package/dist/render/deferredshadowlightpass.js +428 -0
  123. package/dist/render/deferredshadowlightpass.js.map +1 -0
  124. package/dist/render/drawable.js.map +1 -1
  125. package/dist/render/drawable_mixin.js +21 -12
  126. package/dist/render/drawable_mixin.js.map +1 -1
  127. package/dist/render/envlight.js +20 -22
  128. package/dist/render/envlight.js.map +1 -1
  129. package/dist/render/gbufferpass.js +50 -0
  130. package/dist/render/gbufferpass.js.map +1 -0
  131. package/dist/render/lightpass.js +1 -2
  132. package/dist/render/lightpass.js.map +1 -1
  133. package/dist/render/primitive.js +1 -1
  134. package/dist/render/primitive.js.map +1 -1
  135. package/dist/render/render_queue.js +3 -2
  136. package/dist/render/render_queue.js.map +1 -1
  137. package/dist/render/renderer.js +5 -358
  138. package/dist/render/renderer.js.map +1 -1
  139. package/dist/render/rendergraph/executor.js +15 -12
  140. package/dist/render/rendergraph/executor.js.map +1 -1
  141. package/dist/render/rendergraph/forward_plus_builder.js +144 -88
  142. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  143. package/dist/render/rendergraph/history_resource_manager.js +178 -0
  144. package/dist/render/rendergraph/history_resource_manager.js.map +1 -0
  145. package/dist/render/rendergraph/rendergraph.js +12 -1
  146. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  147. package/dist/render/rendergraph/types.js +2 -2
  148. package/dist/render/rendergraph/types.js.map +1 -1
  149. package/dist/render/sky.js +26 -9
  150. package/dist/render/sky.js.map +1 -1
  151. package/dist/scene/basesprite.js +4 -3
  152. package/dist/scene/basesprite.js.map +1 -1
  153. package/dist/scene/batchgroup.js +4 -4
  154. package/dist/scene/environment.js +7 -4
  155. package/dist/scene/environment.js.map +1 -1
  156. package/dist/scene/light.js +184 -18
  157. package/dist/scene/light.js.map +1 -1
  158. package/dist/scene/mesh.js +30 -0
  159. package/dist/scene/mesh.js.map +1 -1
  160. package/dist/scene/particlesys.js +3 -2
  161. package/dist/scene/particlesys.js.map +1 -1
  162. package/dist/scene/raycast_visitor.js +29 -3
  163. package/dist/scene/raycast_visitor.js.map +1 -1
  164. package/dist/scene/scene.js +86 -19
  165. package/dist/scene/scene.js.map +1 -1
  166. package/dist/scene/scene_node.js +87 -31
  167. package/dist/scene/scene_node.js.map +1 -1
  168. package/dist/scene/script_attachment.js +59 -0
  169. package/dist/scene/script_attachment.js.map +1 -0
  170. package/dist/scene/terrain-cm/grass.js +3 -2
  171. package/dist/scene/terrain-cm/grass.js.map +1 -1
  172. package/dist/scene/terrain-cm/terrain-cm.js +4 -3
  173. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  174. package/dist/scene/water.js +3 -2
  175. package/dist/scene/water.js.map +1 -1
  176. package/dist/shaders/shadow.js +2 -2
  177. package/dist/shaders/shadow.js.map +1 -1
  178. package/dist/shadow/shadowmapper.js +74 -4
  179. package/dist/shadow/shadowmapper.js.map +1 -1
  180. package/dist/shapes/box.js +163 -0
  181. package/dist/shapes/box.js.map +1 -1
  182. package/dist/shapes/capsule.js +216 -0
  183. package/dist/shapes/capsule.js.map +1 -0
  184. package/dist/shapes/cylinder.js +91 -0
  185. package/dist/shapes/cylinder.js.map +1 -1
  186. package/dist/shapes/plane.js +32 -0
  187. package/dist/shapes/plane.js.map +1 -1
  188. package/dist/shapes/tetrahedron.js +211 -0
  189. package/dist/shapes/tetrahedron.js.map +1 -1
  190. package/dist/shapes/torus.js +173 -0
  191. package/dist/shapes/torus.js.map +1 -1
  192. package/dist/utility/blueprint/common/math.js +111 -1
  193. package/dist/utility/blueprint/common/math.js.map +1 -1
  194. package/dist/utility/blueprint/material/inputs.js +235 -1
  195. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  196. package/dist/utility/blueprint/material/ir.js +154 -10
  197. package/dist/utility/blueprint/material/ir.js.map +1 -1
  198. package/dist/utility/blueprint/material/texture.js +273 -19
  199. package/dist/utility/blueprint/material/texture.js.map +1 -1
  200. package/dist/utility/serialization/json.js +12 -2
  201. package/dist/utility/serialization/json.js.map +1 -1
  202. package/dist/utility/serialization/manager.js +30 -11
  203. package/dist/utility/serialization/manager.js.map +1 -1
  204. package/dist/utility/serialization/scene/animation.js +250 -7
  205. package/dist/utility/serialization/scene/animation.js.map +1 -1
  206. package/dist/utility/serialization/scene/batch.js +4 -2
  207. package/dist/utility/serialization/scene/batch.js.map +1 -1
  208. package/dist/utility/serialization/scene/camera.js +154 -2
  209. package/dist/utility/serialization/scene/camera.js.map +1 -1
  210. package/dist/utility/serialization/scene/cloth_script.js +834 -0
  211. package/dist/utility/serialization/scene/cloth_script.js.map +1 -0
  212. package/dist/utility/serialization/scene/common.js +7 -0
  213. package/dist/utility/serialization/scene/common.js.map +1 -1
  214. package/dist/utility/serialization/scene/light.js +120 -4
  215. package/dist/utility/serialization/scene/light.js.map +1 -1
  216. package/dist/utility/serialization/scene/material.js +453 -1
  217. package/dist/utility/serialization/scene/material.js.map +1 -1
  218. package/dist/utility/serialization/scene/mesh.js +4 -2
  219. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  220. package/dist/utility/serialization/scene/node.js +298 -10
  221. package/dist/utility/serialization/scene/node.js.map +1 -1
  222. package/dist/utility/serialization/scene/particle.js +4 -2
  223. package/dist/utility/serialization/scene/particle.js.map +1 -1
  224. package/dist/utility/serialization/scene/primitive.js +100 -3
  225. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  226. package/dist/utility/serialization/scene/scene.js +130 -3
  227. package/dist/utility/serialization/scene/scene.js.map +1 -1
  228. package/dist/utility/serialization/scene/script.js +66 -0
  229. package/dist/utility/serialization/scene/script.js.map +1 -0
  230. package/dist/utility/serialization/scene/spring_script.js +596 -0
  231. package/dist/utility/serialization/scene/spring_script.js.map +1 -0
  232. package/dist/utility/serialization/scene/sprite.js +5 -3
  233. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  234. package/dist/utility/serialization/scene/terrain.js +4 -2
  235. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  236. package/dist/utility/serialization/scene/water.js +4 -2
  237. package/dist/utility/serialization/scene/water.js.map +1 -1
  238. package/dist/utility/serialization/types.js.map +1 -1
  239. package/dist/values.js +5 -1
  240. package/dist/values.js.map +1 -1
  241. package/package.json +3 -3
@@ -1,11 +1,94 @@
1
- import { Vector3, Disposable, randomUUID, DRef, DWeakRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
1
+ import { Vector3, Disposable, randomUUID, DRef, Quaternion, DWeakRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
2
2
  import { BoundingBox } from '../utility/bounding_volume.js';
3
3
  import { getDevice } from '../app/api.js';
4
4
 
5
+ /**
6
+ * Standardized humanoid joint names for consistent skeleton mapping across models and animations.
7
+ *
8
+ * These names align with common conventions used in 3D modeling and animation tools, facilitating interoperability and reuse of assets.
9
+ *
10
+ * @public
11
+ */ var HumanoidBodyRig = /*#__PURE__*/ function(HumanoidBodyRig) {
12
+ HumanoidBodyRig["Hips"] = "Hips";
13
+ HumanoidBodyRig["Spine"] = "Spine";
14
+ HumanoidBodyRig["Chest"] = "Chest";
15
+ HumanoidBodyRig["UpperChest"] = "UpperChest";
16
+ HumanoidBodyRig["Neck"] = "Neck";
17
+ HumanoidBodyRig["Head"] = "Head";
18
+ HumanoidBodyRig["LeftShoulder"] = "LeftShoulder";
19
+ HumanoidBodyRig["LeftUpperArm"] = "LeftUpperArm";
20
+ HumanoidBodyRig["LeftLowerArm"] = "LeftLowerArm";
21
+ HumanoidBodyRig["LeftHand"] = "LeftHand";
22
+ HumanoidBodyRig["RightShoulder"] = "RightShoulder";
23
+ HumanoidBodyRig["RightUpperArm"] = "RightUpperArm";
24
+ HumanoidBodyRig["RightLowerArm"] = "RightLowerArm";
25
+ HumanoidBodyRig["RightHand"] = "RightHand";
26
+ HumanoidBodyRig["LeftUpperLeg"] = "LeftUpperLeg";
27
+ HumanoidBodyRig["LeftLowerLeg"] = "LeftLowerLeg";
28
+ HumanoidBodyRig["LeftFoot"] = "LeftFoot";
29
+ HumanoidBodyRig["LeftToes"] = "LeftToes";
30
+ HumanoidBodyRig["RightUpperLeg"] = "RightUpperLeg";
31
+ HumanoidBodyRig["RightLowerLeg"] = "RightLowerLeg";
32
+ HumanoidBodyRig["RightFoot"] = "RightFoot";
33
+ HumanoidBodyRig["RightToes"] = "RightToes";
34
+ return HumanoidBodyRig;
35
+ }({});
36
+ /**
37
+ * Standardized humanoid hand joint names for consistent skeleton mapping across models and animations.
38
+ *
39
+ * These names align with common conventions used in 3D modeling and animation tools, facilitating interoperability and reuse of assets.
40
+ *
41
+ * @public
42
+ */ var HumanoidHandRig = /*#__PURE__*/ function(HumanoidHandRig) {
43
+ HumanoidHandRig["ThumbProximal"] = "ThumbProximal";
44
+ HumanoidHandRig["ThumbIntermediate"] = "ThumbIntermediate";
45
+ HumanoidHandRig["ThumbDistal"] = "ThumbDistal";
46
+ HumanoidHandRig["IndexProximal"] = "IndexProximal";
47
+ HumanoidHandRig["IndexIntermediate"] = "IndexIntermediate";
48
+ HumanoidHandRig["IndexDistal"] = "IndexDistal";
49
+ HumanoidHandRig["MiddleProximal"] = "MiddleProximal";
50
+ HumanoidHandRig["MiddleIntermediate"] = "MiddleIntermediate";
51
+ HumanoidHandRig["MiddleDistal"] = "MiddleDistal";
52
+ HumanoidHandRig["RingProximal"] = "RingProximal";
53
+ HumanoidHandRig["RingIntermediate"] = "RingIntermediate";
54
+ HumanoidHandRig["RingDistal"] = "RingDistal";
55
+ HumanoidHandRig["PinkyProximal"] = "PinkyProximal";
56
+ HumanoidHandRig["PinkyIntermediate"] = "PinkyIntermediate";
57
+ HumanoidHandRig["PinkyDistal"] = "PinkyDistal";
58
+ return HumanoidHandRig;
59
+ }({});
5
60
  const tmpV0 = new Vector3();
6
61
  const tmpV1 = new Vector3();
7
62
  const tmpV2 = new Vector3();
8
63
  const tmpV3 = new Vector3();
64
+ function jointPattern(all, none, any) {
65
+ return {
66
+ all,
67
+ any: any?.length ? any : undefined,
68
+ none: none?.length ? none : undefined
69
+ };
70
+ }
71
+ function sideJointPatterns(side, patterns) {
72
+ const sideTokens = side === 'left' ? [
73
+ 'left',
74
+ 'l'
75
+ ] : [
76
+ 'right',
77
+ 'r'
78
+ ];
79
+ return sideTokens.flatMap((sideToken)=>patterns.map((pattern)=>({
80
+ all: [
81
+ sideToken,
82
+ ...pattern.all
83
+ ],
84
+ any: pattern.any?.length ? [
85
+ ...pattern.any
86
+ ] : undefined,
87
+ none: pattern.none?.length ? [
88
+ ...pattern.none
89
+ ] : undefined
90
+ })));
91
+ }
9
92
  /**
10
93
  * Skeleton for skinned animation.
11
94
  *
@@ -40,6 +123,8 @@ const tmpV3 = new Vector3();
40
123
  /** @internal */ _playing;
41
124
  /** @internal */ _modifiers;
42
125
  /** @internal */ _lastUpdateTime;
126
+ /** @internal */ _humanoidJointMapping;
127
+ /** @internal */ _humanoidRootRotation;
43
128
  /**
44
129
  * Create a skeleton instance.
45
130
  *
@@ -58,6 +143,19 @@ const tmpV3 = new Vector3();
58
143
  this._lastUpdateTime = 0;
59
144
  this.computeBindPose();
60
145
  this.updateJointMatrices(0);
146
+ let skeletonRoot = this.findRootJoint(this._joints);
147
+ if (!skeletonRoot || !this._joints.includes(skeletonRoot)) {
148
+ throw new Error('Skeleton root must be included in the joint list');
149
+ }
150
+ this._humanoidJointMapping = Skeleton.tryExtractHumanoidJoints(skeletonRoot);
151
+ this._humanoidRootRotation = Quaternion.identity();
152
+ if (this._humanoidJointMapping) {
153
+ let p = this._humanoidJointMapping.body["Hips"];
154
+ while(this._joints.includes(p.parent)){
155
+ Quaternion.multiply(p.parent.rotation, this._humanoidRootRotation, this._humanoidRootRotation);
156
+ p = p.parent;
157
+ }
158
+ }
61
159
  Skeleton._registry.set(this._id, new DWeakRef(this));
62
160
  }
63
161
  /**
@@ -74,9 +172,15 @@ const tmpV3 = new Vector3();
74
172
  }
75
173
  return m ? m.get() : null;
76
174
  }
77
- /** @internal */ get joints() {
175
+ /** Gets joint nodes */ get joints() {
78
176
  return this._joints;
79
177
  }
178
+ /** Gets the humanoid joint mapping */ get humanoidJointMapping() {
179
+ return this._humanoidJointMapping;
180
+ }
181
+ /** Root rotation of humanoid hips bone */ get humanoidRootRotation() {
182
+ return this._humanoidRootRotation;
183
+ }
80
184
  /** @internal */ get inverseBindMatrices() {
81
185
  return this._inverseBindMatrices;
82
186
  }
@@ -165,6 +269,7 @@ const tmpV3 = new Vector3();
165
269
  const bindpose = this._bindPose[i];
166
270
  joint.position.set(bindpose.position);
167
271
  joint.rotation.set(bindpose.rotation);
272
+ //joint.rotation.identity();
168
273
  joint.scale.set(bindpose.scale);
169
274
  }
170
275
  }
@@ -353,7 +458,1806 @@ const tmpV3 = new Vector3();
353
458
  };
354
459
  return info;
355
460
  }
461
+ /**
462
+ * Skin all vertices into mesh-local space for the current skeleton pose.
463
+ *
464
+ * This is used by systems like cloth that need the animated mesh pose on CPU,
465
+ * but render with GPU skinning disabled to avoid double deformation.
466
+ *
467
+ * @param positions - Bind-pose/object-space input positions, xyz packed.
468
+ * @param blendIndices - 4 joint indices per vertex.
469
+ * @param weights - 4 joint weights per vertex.
470
+ * @param invWorldMatrix - Mesh inverse world matrix to convert skinned world positions back to mesh-local space.
471
+ * @param out - Optional output array to reuse.
472
+ * @returns The skinned mesh-local positions.
473
+ * @internal
474
+ */ skinPositionsToLocal(positions, blendIndices, weights, invWorldMatrix, out) {
475
+ const result = out && out.length === positions.length ? out : new Float32Array(positions.length);
476
+ const matrixOffset = this._jointOffsets[0] - 1;
477
+ for(let i = 0; i + 2 < positions.length; i += 3){
478
+ const vertexIndex = i / 3 >> 0;
479
+ const x = positions[i];
480
+ const y = positions[i + 1];
481
+ const z = positions[i + 2];
482
+ let skinnedX = 0;
483
+ let skinnedY = 0;
484
+ let skinnedZ = 0;
485
+ let weightSum = 0;
486
+ for(let j = 0; j < 4; j++){
487
+ const weight = Number(weights[vertexIndex * 4 + j]) || 0;
488
+ if (weight <= 0) {
489
+ continue;
490
+ }
491
+ const jointIndex = (Number(blendIndices[vertexIndex * 4 + j]) || 0) + matrixOffset;
492
+ const matrix = this._jointMatrices[jointIndex];
493
+ if (!matrix) {
494
+ continue;
495
+ }
496
+ skinnedX += (matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12]) * weight;
497
+ skinnedY += (matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13]) * weight;
498
+ skinnedZ += (matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14]) * weight;
499
+ weightSum += weight;
500
+ }
501
+ if (weightSum <= 1e-6) {
502
+ skinnedX = x;
503
+ skinnedY = y;
504
+ skinnedZ = z;
505
+ }
506
+ result[i] = invWorldMatrix[0] * skinnedX + invWorldMatrix[4] * skinnedY + invWorldMatrix[8] * skinnedZ + invWorldMatrix[12];
507
+ result[i + 1] = invWorldMatrix[1] * skinnedX + invWorldMatrix[5] * skinnedY + invWorldMatrix[9] * skinnedZ + invWorldMatrix[13];
508
+ result[i + 2] = invWorldMatrix[2] * skinnedX + invWorldMatrix[6] * skinnedY + invWorldMatrix[10] * skinnedZ + invWorldMatrix[14];
509
+ }
510
+ return result;
511
+ }
512
+ findRootJoint(joints) {
513
+ let root = null;
514
+ for (const joint of joints){
515
+ if (!root) {
516
+ root = joint;
517
+ }
518
+ while(!root.isParentOf(joint)){
519
+ root = root.parent;
520
+ }
521
+ if (!root) {
522
+ break;
523
+ }
524
+ }
525
+ return root;
526
+ }
527
+ static normalizeHumanoidJointName(name) {
528
+ return name.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/([a-zA-Z])(\d+)/g, '$1 $2').replace(/(\d+)([a-zA-Z])/g, '$1 $2').replace(/[_:\/\\.-]+/g, ' ').replace(/[^a-zA-Z0-9]+/g, ' ').toLowerCase().replace(/\bforearm\b/g, 'fore arm').replace(/\bupperarm\b/g, 'upper arm').replace(/\blowerarm\b/g, 'lower arm').replace(/\bupleg\b/g, 'up leg').replace(/\bupperleg\b/g, 'upper leg').replace(/\blowerleg\b/g, 'lower leg').replace(/\btoebase\b/g, 'toe base').replace(/\bupperchest\b/g, 'upper chest').replace(/\btoes\b/g, 'toe').replace(/\blittle\b/g, 'pinky').replace(/\bcollar\b/g, 'clavicle').replace(/\s+/g, ' ').trim();
529
+ }
530
+ static getHumanoidJointNodeDepth(root, node) {
531
+ let depth = 0;
532
+ let current = node;
533
+ while(current && current !== root){
534
+ depth++;
535
+ current = current.parent;
536
+ }
537
+ return depth;
538
+ }
539
+ static collectHumanoidJointNodeInfos(root) {
540
+ const nodes = [];
541
+ this.iterateNode(root, (node)=>{
542
+ const normalizedName = this.normalizeHumanoidJointName(node.name || '');
543
+ if (!normalizedName) {
544
+ return false;
545
+ }
546
+ const tokens = normalizedName.split(' ').filter(Boolean);
547
+ if (!tokens.length) {
548
+ return false;
549
+ }
550
+ nodes.push({
551
+ node,
552
+ depth: this.getHumanoidJointNodeDepth(root, node),
553
+ tokens,
554
+ tokenSet: new Set(tokens)
555
+ });
556
+ return false;
557
+ });
558
+ return nodes;
559
+ }
560
+ static matchesHumanoidJointPattern(info, pattern) {
561
+ if (pattern.all?.some((token)=>!info.tokenSet.has(token))) {
562
+ return false;
563
+ }
564
+ if (pattern.any?.length && !pattern.any.some((token)=>info.tokenSet.has(token))) {
565
+ return false;
566
+ }
567
+ if (pattern.none?.some((token)=>info.tokenSet.has(token))) {
568
+ return false;
569
+ }
570
+ return true;
571
+ }
572
+ static scoreHumanoidJointPattern(info, pattern, priority) {
573
+ const matchedTokens = new Set(pattern.all ?? []);
574
+ for (const token of pattern.any ?? []){
575
+ if (info.tokenSet.has(token)) {
576
+ matchedTokens.add(token);
577
+ }
578
+ }
579
+ let extraTokenCount = 0;
580
+ for (const token of info.tokens){
581
+ if (!matchedTokens.has(token)) {
582
+ extraTokenCount++;
583
+ }
584
+ }
585
+ return priority * 100000 + matchedTokens.size * 100 - extraTokenCount * 5 - info.depth;
586
+ }
587
+ static collectHumanoidJointCandidates(nodes, patterns, used) {
588
+ const candidates = new Map();
589
+ for(let index = 0; index < patterns.length; index++){
590
+ const pattern = patterns[index];
591
+ const priority = patterns.length - index;
592
+ for (const info of nodes){
593
+ if (used.has(info.node) || !this.matchesHumanoidJointPattern(info, pattern)) {
594
+ continue;
595
+ }
596
+ const score = this.scoreHumanoidJointPattern(info, pattern, priority);
597
+ const current = candidates.get(info.node);
598
+ if (current === undefined || score > current) {
599
+ candidates.set(info.node, score);
600
+ }
601
+ }
602
+ }
603
+ return Array.from(candidates, ([node, score])=>({
604
+ node,
605
+ score
606
+ })).sort((a, b)=>b.score - a.score);
607
+ }
608
+ static findBestHumanoidJoint(nodes, patterns, used) {
609
+ return this.collectHumanoidJointCandidates(nodes, patterns, used)[0]?.node ?? null;
610
+ }
611
+ static matchHumanoidJointProfile(nodes, profile, used, optional) {
612
+ const result = {};
613
+ const reserved = new Set();
614
+ for (const joint of Object.keys(profile)){
615
+ const node = this.findBestHumanoidJoint(nodes, profile[joint], new Set([
616
+ ...used,
617
+ ...reserved
618
+ ]));
619
+ if (!node) {
620
+ if (optional?.has(joint)) {
621
+ continue;
622
+ }
623
+ return null;
624
+ }
625
+ result[joint] = node;
626
+ reserved.add(node);
627
+ }
628
+ for (const node of reserved){
629
+ used.add(node);
630
+ }
631
+ return result;
632
+ }
633
+ static validateHumanoidBodyPartial(body) {
634
+ const validateAncestor = (ancestor, descendant)=>!body[ancestor] || !body[descendant] || this.isSameOrAncestor(body[ancestor], body[descendant]);
635
+ return validateAncestor("Hips", "Spine") && validateAncestor("Hips", "Neck") && validateAncestor("Hips", "LeftUpperLeg") && validateAncestor("Hips", "RightUpperLeg") && validateAncestor("Spine", "Chest") && validateAncestor("Spine", "UpperChest") && validateAncestor("Spine", "Neck") && validateAncestor("Spine", "Head") && validateAncestor("Spine", "LeftShoulder") && validateAncestor("Spine", "RightShoulder") && validateAncestor("Chest", "UpperChest") && validateAncestor("Chest", "Neck") && validateAncestor("Chest", "Head") && validateAncestor("Chest", "LeftShoulder") && validateAncestor("Chest", "RightShoulder") && validateAncestor("UpperChest", "Neck") && validateAncestor("UpperChest", "Head") && validateAncestor("UpperChest", "LeftShoulder") && validateAncestor("UpperChest", "RightShoulder") && validateAncestor("Neck", "Head") && validateAncestor("LeftShoulder", "LeftUpperArm") && validateAncestor("LeftUpperArm", "LeftLowerArm") && validateAncestor("LeftLowerArm", "LeftHand") && validateAncestor("RightShoulder", "RightUpperArm") && validateAncestor("RightUpperArm", "RightLowerArm") && validateAncestor("RightLowerArm", "RightHand") && validateAncestor("LeftUpperLeg", "LeftLowerLeg") && validateAncestor("LeftLowerLeg", "LeftFoot") && validateAncestor("LeftFoot", "LeftToes") && validateAncestor("RightUpperLeg", "RightLowerLeg") && validateAncestor("RightLowerLeg", "RightFoot") && validateAncestor("RightFoot", "RightToes");
636
+ }
637
+ static matchHumanoidBodyProfile(nodes, profile, used, optional) {
638
+ const joints = Object.keys(profile);
639
+ const candidates = new Map();
640
+ for (const joint of joints){
641
+ candidates.set(joint, this.collectHumanoidJointCandidates(nodes, profile[joint], used));
642
+ }
643
+ const current = {};
644
+ const reserved = new Set();
645
+ let bestScore = Number.NEGATIVE_INFINITY;
646
+ let bestResult = null;
647
+ const search = (index, score)=>{
648
+ if (index >= joints.length) {
649
+ if (score > bestScore) {
650
+ bestScore = score;
651
+ bestResult = {
652
+ ...current
653
+ };
654
+ }
655
+ return;
656
+ }
657
+ const joint = joints[index];
658
+ let matched = false;
659
+ for (const candidate of candidates.get(joint) ?? []){
660
+ if (reserved.has(candidate.node)) {
661
+ continue;
662
+ }
663
+ current[joint] = candidate.node;
664
+ reserved.add(candidate.node);
665
+ if (this.validateHumanoidBodyPartial(current)) {
666
+ matched = true;
667
+ search(index + 1, score + candidate.score);
668
+ }
669
+ reserved.delete(candidate.node);
670
+ delete current[joint];
671
+ }
672
+ if (optional?.has(joint)) {
673
+ search(index + 1, score);
674
+ } else if (!matched) {
675
+ return;
676
+ }
677
+ };
678
+ search(0, 0);
679
+ if (!bestResult) {
680
+ return null;
681
+ }
682
+ for (const node of Object.values(bestResult)){
683
+ used.add(node);
684
+ }
685
+ return bestResult;
686
+ }
687
+ static getHumanoidIntermediateChain(ancestor, descendant) {
688
+ if (!this.isSameOrAncestor(ancestor, descendant)) {
689
+ return null;
690
+ }
691
+ const chain = [];
692
+ let current = descendant.parent;
693
+ while(current && current !== ancestor){
694
+ chain.unshift(current);
695
+ current = current.parent;
696
+ }
697
+ return chain;
698
+ }
699
+ static completeHumanoidBody(body) {
700
+ const requiredJoints = [
701
+ "Hips",
702
+ "Spine",
703
+ "Neck",
704
+ "Head",
705
+ "LeftShoulder",
706
+ "LeftUpperArm",
707
+ "LeftLowerArm",
708
+ "LeftHand",
709
+ "RightShoulder",
710
+ "RightUpperArm",
711
+ "RightLowerArm",
712
+ "RightHand",
713
+ "LeftUpperLeg",
714
+ "LeftLowerLeg",
715
+ "LeftFoot",
716
+ "LeftToes",
717
+ "RightUpperLeg",
718
+ "RightLowerLeg",
719
+ "RightFoot",
720
+ "RightToes"
721
+ ];
722
+ for (const joint of requiredJoints){
723
+ if (!body[joint]) {
724
+ return null;
725
+ }
726
+ }
727
+ const spine = body["Spine"];
728
+ const neck = body["Neck"];
729
+ let chest = body["Chest"];
730
+ let upperChest = body["UpperChest"];
731
+ if (!chest || !upperChest) {
732
+ const spineChain = this.getHumanoidIntermediateChain(spine, neck);
733
+ if (!spineChain || spineChain.length === 0) {
734
+ chest ||= spine;
735
+ upperChest ||= chest;
736
+ } else if (spineChain.length === 1) {
737
+ chest ||= spineChain[0];
738
+ upperChest ||= chest;
739
+ } else {
740
+ chest ||= spineChain[0];
741
+ upperChest ||= spineChain[spineChain.length - 1];
742
+ }
743
+ }
744
+ if (!chest || !upperChest) {
745
+ return null;
746
+ }
747
+ return {
748
+ ["Hips"]: body["Hips"],
749
+ ["Spine"]: spine,
750
+ ["Chest"]: chest,
751
+ ["UpperChest"]: upperChest,
752
+ ["Neck"]: neck,
753
+ ["Head"]: body["Head"],
754
+ ["LeftShoulder"]: body["LeftShoulder"],
755
+ ["LeftUpperArm"]: body["LeftUpperArm"],
756
+ ["LeftLowerArm"]: body["LeftLowerArm"],
757
+ ["LeftHand"]: body["LeftHand"],
758
+ ["RightShoulder"]: body["RightShoulder"],
759
+ ["RightUpperArm"]: body["RightUpperArm"],
760
+ ["RightLowerArm"]: body["RightLowerArm"],
761
+ ["RightHand"]: body["RightHand"],
762
+ ["LeftUpperLeg"]: body["LeftUpperLeg"],
763
+ ["LeftLowerLeg"]: body["LeftLowerLeg"],
764
+ ["LeftFoot"]: body["LeftFoot"],
765
+ ["LeftToes"]: body["LeftToes"],
766
+ ["RightUpperLeg"]: body["RightUpperLeg"],
767
+ ["RightLowerLeg"]: body["RightLowerLeg"],
768
+ ["RightFoot"]: body["RightFoot"],
769
+ ["RightToes"]: body["RightToes"]
770
+ };
771
+ }
772
+ static completeHumanoidHand(hand) {
773
+ for (const joint of Object.values(HumanoidHandRig)){
774
+ if (!hand[joint]) {
775
+ return null;
776
+ }
777
+ }
778
+ return {
779
+ ["ThumbProximal"]: hand["ThumbProximal"],
780
+ ["ThumbIntermediate"]: hand["ThumbIntermediate"],
781
+ ["ThumbDistal"]: hand["ThumbDistal"],
782
+ ["IndexProximal"]: hand["IndexProximal"],
783
+ ["IndexIntermediate"]: hand["IndexIntermediate"],
784
+ ["IndexDistal"]: hand["IndexDistal"],
785
+ ["MiddleProximal"]: hand["MiddleProximal"],
786
+ ["MiddleIntermediate"]: hand["MiddleIntermediate"],
787
+ ["MiddleDistal"]: hand["MiddleDistal"],
788
+ ["RingProximal"]: hand["RingProximal"],
789
+ ["RingIntermediate"]: hand["RingIntermediate"],
790
+ ["RingDistal"]: hand["RingDistal"],
791
+ ["PinkyProximal"]: hand["PinkyProximal"],
792
+ ["PinkyIntermediate"]: hand["PinkyIntermediate"],
793
+ ["PinkyDistal"]: hand["PinkyDistal"]
794
+ };
795
+ }
796
+ static tryExtractOptionalHumanoidHand(nodes, side, used) {
797
+ const handCandidates = this.matchHumanoidJointProfile(nodes, this.createCommonHumanoidHandProfile(side), used);
798
+ if (!handCandidates) {
799
+ return undefined;
800
+ }
801
+ return this.completeHumanoidHand(handCandidates) ?? undefined;
802
+ }
803
+ static isSameOrAncestor(parent, child) {
804
+ return parent === child || this.isParentOf(parent, child);
805
+ }
806
+ static validateHumanoidHandHierarchy(hand, joints) {
807
+ const chains = [
808
+ [
809
+ "ThumbProximal",
810
+ "ThumbIntermediate",
811
+ "ThumbDistal"
812
+ ],
813
+ [
814
+ "IndexProximal",
815
+ "IndexIntermediate",
816
+ "IndexDistal"
817
+ ],
818
+ [
819
+ "MiddleProximal",
820
+ "MiddleIntermediate",
821
+ "MiddleDistal"
822
+ ],
823
+ [
824
+ "RingProximal",
825
+ "RingIntermediate",
826
+ "RingDistal"
827
+ ],
828
+ [
829
+ "PinkyProximal",
830
+ "PinkyIntermediate",
831
+ "PinkyDistal"
832
+ ]
833
+ ];
834
+ return chains.every(([proximal, intermediate, distal])=>this.isSameOrAncestor(hand, joints[proximal]) && this.isSameOrAncestor(joints[proximal], joints[intermediate]) && this.isSameOrAncestor(joints[intermediate], joints[distal]));
835
+ }
836
+ static validateHumanoidJointExtraction(result) {
837
+ const body = result.body;
838
+ return this.isSameOrAncestor(body["Hips"], body["Spine"]) && this.isSameOrAncestor(body["Spine"], body["Chest"]) && this.isSameOrAncestor(body["Chest"], body["UpperChest"]) && this.isSameOrAncestor(body["UpperChest"], body["Neck"]) && this.isSameOrAncestor(body["Neck"], body["Head"]) && this.isSameOrAncestor(body["UpperChest"], body["LeftShoulder"]) && this.isSameOrAncestor(body["LeftShoulder"], body["LeftUpperArm"]) && this.isSameOrAncestor(body["LeftUpperArm"], body["LeftLowerArm"]) && this.isSameOrAncestor(body["LeftLowerArm"], body["LeftHand"]) && this.isSameOrAncestor(body["UpperChest"], body["RightShoulder"]) && this.isSameOrAncestor(body["RightShoulder"], body["RightUpperArm"]) && this.isSameOrAncestor(body["RightUpperArm"], body["RightLowerArm"]) && this.isSameOrAncestor(body["RightLowerArm"], body["RightHand"]) && this.isSameOrAncestor(body["Hips"], body["LeftUpperLeg"]) && this.isSameOrAncestor(body["LeftUpperLeg"], body["LeftLowerLeg"]) && this.isSameOrAncestor(body["LeftLowerLeg"], body["LeftFoot"]) && this.isSameOrAncestor(body["LeftFoot"], body["LeftToes"]) && this.isSameOrAncestor(body["Hips"], body["RightUpperLeg"]) && this.isSameOrAncestor(body["RightUpperLeg"], body["RightLowerLeg"]) && this.isSameOrAncestor(body["RightLowerLeg"], body["RightFoot"]) && this.isSameOrAncestor(body["RightFoot"], body["RightToes"]) && (!result.leftHand || this.validateHumanoidHandHierarchy(body["LeftHand"], result.leftHand)) && (!result.rightHand || this.validateHumanoidHandHierarchy(body["RightHand"], result.rightHand));
839
+ }
840
+ static createCommonHumanoidHandProfile(side) {
841
+ return {
842
+ ["ThumbProximal"]: sideJointPatterns(side, [
843
+ {
844
+ all: [
845
+ 'thumb',
846
+ 'proximal'
847
+ ]
848
+ },
849
+ {
850
+ all: [
851
+ 'thumb',
852
+ '1'
853
+ ]
854
+ },
855
+ {
856
+ all: [
857
+ 'finger',
858
+ '0'
859
+ ]
860
+ }
861
+ ]),
862
+ ["ThumbIntermediate"]: sideJointPatterns(side, [
863
+ {
864
+ all: [
865
+ 'thumb',
866
+ 'intermediate'
867
+ ]
868
+ },
869
+ {
870
+ all: [
871
+ 'thumb',
872
+ '2'
873
+ ]
874
+ },
875
+ {
876
+ all: [
877
+ 'finger',
878
+ '01'
879
+ ]
880
+ }
881
+ ]),
882
+ ["ThumbDistal"]: sideJointPatterns(side, [
883
+ {
884
+ all: [
885
+ 'thumb',
886
+ 'distal'
887
+ ]
888
+ },
889
+ {
890
+ all: [
891
+ 'thumb',
892
+ '3'
893
+ ]
894
+ },
895
+ {
896
+ all: [
897
+ 'finger',
898
+ '02'
899
+ ]
900
+ }
901
+ ]),
902
+ ["IndexProximal"]: sideJointPatterns(side, [
903
+ {
904
+ all: [
905
+ 'index',
906
+ 'proximal'
907
+ ]
908
+ },
909
+ {
910
+ all: [
911
+ 'index',
912
+ '1'
913
+ ]
914
+ },
915
+ {
916
+ all: [
917
+ 'finger',
918
+ '1'
919
+ ]
920
+ }
921
+ ]),
922
+ ["IndexIntermediate"]: sideJointPatterns(side, [
923
+ {
924
+ all: [
925
+ 'index',
926
+ 'intermediate'
927
+ ]
928
+ },
929
+ {
930
+ all: [
931
+ 'index',
932
+ '2'
933
+ ]
934
+ },
935
+ {
936
+ all: [
937
+ 'finger',
938
+ '11'
939
+ ]
940
+ }
941
+ ]),
942
+ ["IndexDistal"]: sideJointPatterns(side, [
943
+ {
944
+ all: [
945
+ 'index',
946
+ 'distal'
947
+ ]
948
+ },
949
+ {
950
+ all: [
951
+ 'index',
952
+ '3'
953
+ ]
954
+ },
955
+ {
956
+ all: [
957
+ 'finger',
958
+ '12'
959
+ ]
960
+ }
961
+ ]),
962
+ ["MiddleProximal"]: sideJointPatterns(side, [
963
+ {
964
+ all: [
965
+ 'middle',
966
+ 'proximal'
967
+ ]
968
+ },
969
+ {
970
+ all: [
971
+ 'middle',
972
+ '1'
973
+ ]
974
+ },
975
+ {
976
+ all: [
977
+ 'finger',
978
+ '2'
979
+ ]
980
+ }
981
+ ]),
982
+ ["MiddleIntermediate"]: sideJointPatterns(side, [
983
+ {
984
+ all: [
985
+ 'middle',
986
+ 'intermediate'
987
+ ]
988
+ },
989
+ {
990
+ all: [
991
+ 'middle',
992
+ '2'
993
+ ]
994
+ },
995
+ {
996
+ all: [
997
+ 'finger',
998
+ '21'
999
+ ]
1000
+ }
1001
+ ]),
1002
+ ["MiddleDistal"]: sideJointPatterns(side, [
1003
+ {
1004
+ all: [
1005
+ 'middle',
1006
+ 'distal'
1007
+ ]
1008
+ },
1009
+ {
1010
+ all: [
1011
+ 'middle',
1012
+ '3'
1013
+ ]
1014
+ },
1015
+ {
1016
+ all: [
1017
+ 'finger',
1018
+ '22'
1019
+ ]
1020
+ }
1021
+ ]),
1022
+ ["RingProximal"]: sideJointPatterns(side, [
1023
+ {
1024
+ all: [
1025
+ 'ring',
1026
+ 'proximal'
1027
+ ]
1028
+ },
1029
+ {
1030
+ all: [
1031
+ 'ring',
1032
+ '1'
1033
+ ]
1034
+ },
1035
+ {
1036
+ all: [
1037
+ 'finger',
1038
+ '3'
1039
+ ]
1040
+ }
1041
+ ]),
1042
+ ["RingIntermediate"]: sideJointPatterns(side, [
1043
+ {
1044
+ all: [
1045
+ 'ring',
1046
+ 'intermediate'
1047
+ ]
1048
+ },
1049
+ {
1050
+ all: [
1051
+ 'ring',
1052
+ '2'
1053
+ ]
1054
+ },
1055
+ {
1056
+ all: [
1057
+ 'finger',
1058
+ '31'
1059
+ ]
1060
+ }
1061
+ ]),
1062
+ ["RingDistal"]: sideJointPatterns(side, [
1063
+ {
1064
+ all: [
1065
+ 'ring',
1066
+ 'distal'
1067
+ ]
1068
+ },
1069
+ {
1070
+ all: [
1071
+ 'ring',
1072
+ '3'
1073
+ ]
1074
+ },
1075
+ {
1076
+ all: [
1077
+ 'finger',
1078
+ '32'
1079
+ ]
1080
+ }
1081
+ ]),
1082
+ ["PinkyProximal"]: sideJointPatterns(side, [
1083
+ {
1084
+ all: [
1085
+ 'pinky',
1086
+ 'proximal'
1087
+ ]
1088
+ },
1089
+ {
1090
+ all: [
1091
+ 'pinky',
1092
+ '1'
1093
+ ]
1094
+ },
1095
+ {
1096
+ all: [
1097
+ 'finger',
1098
+ '4'
1099
+ ]
1100
+ }
1101
+ ]),
1102
+ ["PinkyIntermediate"]: sideJointPatterns(side, [
1103
+ {
1104
+ all: [
1105
+ 'pinky',
1106
+ 'intermediate'
1107
+ ]
1108
+ },
1109
+ {
1110
+ all: [
1111
+ 'pinky',
1112
+ '2'
1113
+ ]
1114
+ },
1115
+ {
1116
+ all: [
1117
+ 'finger',
1118
+ '41'
1119
+ ]
1120
+ }
1121
+ ]),
1122
+ ["PinkyDistal"]: sideJointPatterns(side, [
1123
+ {
1124
+ all: [
1125
+ 'pinky',
1126
+ 'distal'
1127
+ ]
1128
+ },
1129
+ {
1130
+ all: [
1131
+ 'pinky',
1132
+ '3'
1133
+ ]
1134
+ },
1135
+ {
1136
+ all: [
1137
+ 'finger',
1138
+ '42'
1139
+ ]
1140
+ }
1141
+ ])
1142
+ };
1143
+ }
1144
+ static createStandardHumanoidBodyProfile() {
1145
+ return {
1146
+ ["Hips"]: [
1147
+ jointPattern([
1148
+ 'hips'
1149
+ ]),
1150
+ jointPattern([
1151
+ 'pelvis'
1152
+ ])
1153
+ ],
1154
+ ["Spine"]: [
1155
+ jointPattern([
1156
+ 'spine'
1157
+ ], [
1158
+ '1',
1159
+ '2',
1160
+ '3',
1161
+ 'chest',
1162
+ 'upper'
1163
+ ])
1164
+ ],
1165
+ ["Chest"]: [
1166
+ jointPattern([
1167
+ 'chest'
1168
+ ], [
1169
+ 'upper'
1170
+ ]),
1171
+ jointPattern([
1172
+ 'spine',
1173
+ '1'
1174
+ ])
1175
+ ],
1176
+ ["UpperChest"]: [
1177
+ jointPattern([
1178
+ 'upper',
1179
+ 'chest'
1180
+ ]),
1181
+ jointPattern([
1182
+ 'spine',
1183
+ '2'
1184
+ ]),
1185
+ jointPattern([
1186
+ 'spine',
1187
+ '3'
1188
+ ])
1189
+ ],
1190
+ ["Neck"]: [
1191
+ jointPattern([
1192
+ 'neck'
1193
+ ], [
1194
+ '1',
1195
+ '2'
1196
+ ])
1197
+ ],
1198
+ ["Head"]: [
1199
+ jointPattern([
1200
+ 'head'
1201
+ ], [
1202
+ 'top',
1203
+ 'end',
1204
+ 'nub'
1205
+ ])
1206
+ ],
1207
+ ["LeftShoulder"]: sideJointPatterns('left', [
1208
+ {
1209
+ all: [
1210
+ 'shoulder'
1211
+ ]
1212
+ },
1213
+ {
1214
+ all: [
1215
+ 'clavicle'
1216
+ ]
1217
+ }
1218
+ ]),
1219
+ ["LeftUpperArm"]: sideJointPatterns('left', [
1220
+ {
1221
+ all: [
1222
+ 'upper',
1223
+ 'arm'
1224
+ ],
1225
+ none: [
1226
+ 'twist'
1227
+ ]
1228
+ },
1229
+ {
1230
+ all: [
1231
+ 'arm'
1232
+ ],
1233
+ none: [
1234
+ 'fore',
1235
+ 'lower',
1236
+ 'hand',
1237
+ 'twist',
1238
+ 'shoulder'
1239
+ ]
1240
+ }
1241
+ ]),
1242
+ ["LeftLowerArm"]: sideJointPatterns('left', [
1243
+ {
1244
+ all: [
1245
+ 'lower',
1246
+ 'arm'
1247
+ ],
1248
+ none: [
1249
+ 'twist'
1250
+ ]
1251
+ },
1252
+ {
1253
+ all: [
1254
+ 'fore',
1255
+ 'arm'
1256
+ ],
1257
+ none: [
1258
+ 'twist'
1259
+ ]
1260
+ }
1261
+ ]),
1262
+ ["LeftHand"]: sideJointPatterns('left', [
1263
+ {
1264
+ all: [
1265
+ 'hand'
1266
+ ],
1267
+ none: [
1268
+ 'thumb',
1269
+ 'index',
1270
+ 'middle',
1271
+ 'ring',
1272
+ 'pinky'
1273
+ ]
1274
+ }
1275
+ ]),
1276
+ ["RightShoulder"]: sideJointPatterns('right', [
1277
+ {
1278
+ all: [
1279
+ 'shoulder'
1280
+ ]
1281
+ },
1282
+ {
1283
+ all: [
1284
+ 'clavicle'
1285
+ ]
1286
+ }
1287
+ ]),
1288
+ ["RightUpperArm"]: sideJointPatterns('right', [
1289
+ {
1290
+ all: [
1291
+ 'upper',
1292
+ 'arm'
1293
+ ],
1294
+ none: [
1295
+ 'twist'
1296
+ ]
1297
+ },
1298
+ {
1299
+ all: [
1300
+ 'arm'
1301
+ ],
1302
+ none: [
1303
+ 'fore',
1304
+ 'lower',
1305
+ 'hand',
1306
+ 'twist',
1307
+ 'shoulder'
1308
+ ]
1309
+ }
1310
+ ]),
1311
+ ["RightLowerArm"]: sideJointPatterns('right', [
1312
+ {
1313
+ all: [
1314
+ 'lower',
1315
+ 'arm'
1316
+ ],
1317
+ none: [
1318
+ 'twist'
1319
+ ]
1320
+ },
1321
+ {
1322
+ all: [
1323
+ 'fore',
1324
+ 'arm'
1325
+ ],
1326
+ none: [
1327
+ 'twist'
1328
+ ]
1329
+ }
1330
+ ]),
1331
+ ["RightHand"]: sideJointPatterns('right', [
1332
+ {
1333
+ all: [
1334
+ 'hand'
1335
+ ],
1336
+ none: [
1337
+ 'thumb',
1338
+ 'index',
1339
+ 'middle',
1340
+ 'ring',
1341
+ 'pinky'
1342
+ ]
1343
+ }
1344
+ ]),
1345
+ ["LeftUpperLeg"]: sideJointPatterns('left', [
1346
+ {
1347
+ all: [
1348
+ 'upper',
1349
+ 'leg'
1350
+ ]
1351
+ },
1352
+ {
1353
+ all: [
1354
+ 'up',
1355
+ 'leg'
1356
+ ]
1357
+ },
1358
+ {
1359
+ all: [
1360
+ 'thigh'
1361
+ ]
1362
+ }
1363
+ ]),
1364
+ ["LeftLowerLeg"]: sideJointPatterns('left', [
1365
+ {
1366
+ all: [
1367
+ 'lower',
1368
+ 'leg'
1369
+ ]
1370
+ },
1371
+ {
1372
+ all: [
1373
+ 'leg'
1374
+ ],
1375
+ none: [
1376
+ 'upper',
1377
+ 'up',
1378
+ 'thigh',
1379
+ 'foot',
1380
+ 'toe'
1381
+ ]
1382
+ },
1383
+ {
1384
+ all: [
1385
+ 'calf'
1386
+ ]
1387
+ },
1388
+ {
1389
+ all: [
1390
+ 'shin'
1391
+ ]
1392
+ }
1393
+ ]),
1394
+ ["LeftFoot"]: sideJointPatterns('left', [
1395
+ {
1396
+ all: [
1397
+ 'foot'
1398
+ ],
1399
+ none: [
1400
+ 'toe'
1401
+ ]
1402
+ }
1403
+ ]),
1404
+ ["LeftToes"]: sideJointPatterns('left', [
1405
+ {
1406
+ all: [
1407
+ 'toe',
1408
+ 'base'
1409
+ ]
1410
+ },
1411
+ {
1412
+ all: [
1413
+ 'toe'
1414
+ ],
1415
+ none: [
1416
+ 'end'
1417
+ ]
1418
+ }
1419
+ ]),
1420
+ ["RightUpperLeg"]: sideJointPatterns('right', [
1421
+ {
1422
+ all: [
1423
+ 'upper',
1424
+ 'leg'
1425
+ ]
1426
+ },
1427
+ {
1428
+ all: [
1429
+ 'up',
1430
+ 'leg'
1431
+ ]
1432
+ },
1433
+ {
1434
+ all: [
1435
+ 'thigh'
1436
+ ]
1437
+ }
1438
+ ]),
1439
+ ["RightLowerLeg"]: sideJointPatterns('right', [
1440
+ {
1441
+ all: [
1442
+ 'lower',
1443
+ 'leg'
1444
+ ]
1445
+ },
1446
+ {
1447
+ all: [
1448
+ 'leg'
1449
+ ],
1450
+ none: [
1451
+ 'upper',
1452
+ 'up',
1453
+ 'thigh',
1454
+ 'foot',
1455
+ 'toe'
1456
+ ]
1457
+ },
1458
+ {
1459
+ all: [
1460
+ 'calf'
1461
+ ]
1462
+ },
1463
+ {
1464
+ all: [
1465
+ 'shin'
1466
+ ]
1467
+ }
1468
+ ]),
1469
+ ["RightFoot"]: sideJointPatterns('right', [
1470
+ {
1471
+ all: [
1472
+ 'foot'
1473
+ ],
1474
+ none: [
1475
+ 'toe'
1476
+ ]
1477
+ }
1478
+ ]),
1479
+ ["RightToes"]: sideJointPatterns('right', [
1480
+ {
1481
+ all: [
1482
+ 'toe',
1483
+ 'base'
1484
+ ]
1485
+ },
1486
+ {
1487
+ all: [
1488
+ 'toe'
1489
+ ],
1490
+ none: [
1491
+ 'end'
1492
+ ]
1493
+ }
1494
+ ])
1495
+ };
1496
+ }
1497
+ static createMixamoHumanoidBodyProfile() {
1498
+ return {
1499
+ ["Hips"]: [
1500
+ jointPattern([
1501
+ 'hips'
1502
+ ])
1503
+ ],
1504
+ ["Spine"]: [
1505
+ jointPattern([
1506
+ 'spine'
1507
+ ], [
1508
+ '1',
1509
+ '2',
1510
+ '3'
1511
+ ])
1512
+ ],
1513
+ ["Chest"]: [
1514
+ jointPattern([
1515
+ 'spine',
1516
+ '1'
1517
+ ]),
1518
+ jointPattern([
1519
+ 'chest'
1520
+ ], [
1521
+ 'upper'
1522
+ ])
1523
+ ],
1524
+ ["UpperChest"]: [
1525
+ jointPattern([
1526
+ 'spine',
1527
+ '2'
1528
+ ]),
1529
+ jointPattern([
1530
+ 'spine',
1531
+ '3'
1532
+ ]),
1533
+ jointPattern([
1534
+ 'upper',
1535
+ 'chest'
1536
+ ])
1537
+ ],
1538
+ ["Neck"]: [
1539
+ jointPattern([
1540
+ 'neck'
1541
+ ], [
1542
+ '1',
1543
+ '2'
1544
+ ])
1545
+ ],
1546
+ ["Head"]: [
1547
+ jointPattern([
1548
+ 'head'
1549
+ ], [
1550
+ 'top',
1551
+ 'end',
1552
+ 'nub'
1553
+ ])
1554
+ ],
1555
+ ["LeftShoulder"]: sideJointPatterns('left', [
1556
+ {
1557
+ all: [
1558
+ 'shoulder'
1559
+ ]
1560
+ },
1561
+ {
1562
+ all: [
1563
+ 'clavicle'
1564
+ ]
1565
+ }
1566
+ ]),
1567
+ ["LeftUpperArm"]: sideJointPatterns('left', [
1568
+ {
1569
+ all: [
1570
+ 'arm'
1571
+ ],
1572
+ none: [
1573
+ 'upper',
1574
+ 'fore',
1575
+ 'lower',
1576
+ 'hand',
1577
+ 'twist',
1578
+ 'shoulder'
1579
+ ]
1580
+ },
1581
+ {
1582
+ all: [
1583
+ 'upper',
1584
+ 'arm'
1585
+ ],
1586
+ none: [
1587
+ 'twist'
1588
+ ]
1589
+ }
1590
+ ]),
1591
+ ["LeftLowerArm"]: sideJointPatterns('left', [
1592
+ {
1593
+ all: [
1594
+ 'fore',
1595
+ 'arm'
1596
+ ],
1597
+ none: [
1598
+ 'twist'
1599
+ ]
1600
+ },
1601
+ {
1602
+ all: [
1603
+ 'lower',
1604
+ 'arm'
1605
+ ],
1606
+ none: [
1607
+ 'twist'
1608
+ ]
1609
+ }
1610
+ ]),
1611
+ ["LeftHand"]: sideJointPatterns('left', [
1612
+ {
1613
+ all: [
1614
+ 'hand'
1615
+ ],
1616
+ none: [
1617
+ 'thumb',
1618
+ 'index',
1619
+ 'middle',
1620
+ 'ring',
1621
+ 'pinky'
1622
+ ]
1623
+ }
1624
+ ]),
1625
+ ["RightShoulder"]: sideJointPatterns('right', [
1626
+ {
1627
+ all: [
1628
+ 'shoulder'
1629
+ ]
1630
+ },
1631
+ {
1632
+ all: [
1633
+ 'clavicle'
1634
+ ]
1635
+ }
1636
+ ]),
1637
+ ["RightUpperArm"]: sideJointPatterns('right', [
1638
+ {
1639
+ all: [
1640
+ 'arm'
1641
+ ],
1642
+ none: [
1643
+ 'upper',
1644
+ 'fore',
1645
+ 'lower',
1646
+ 'hand',
1647
+ 'twist',
1648
+ 'shoulder'
1649
+ ]
1650
+ },
1651
+ {
1652
+ all: [
1653
+ 'upper',
1654
+ 'arm'
1655
+ ],
1656
+ none: [
1657
+ 'twist'
1658
+ ]
1659
+ }
1660
+ ]),
1661
+ ["RightLowerArm"]: sideJointPatterns('right', [
1662
+ {
1663
+ all: [
1664
+ 'fore',
1665
+ 'arm'
1666
+ ],
1667
+ none: [
1668
+ 'twist'
1669
+ ]
1670
+ },
1671
+ {
1672
+ all: [
1673
+ 'lower',
1674
+ 'arm'
1675
+ ],
1676
+ none: [
1677
+ 'twist'
1678
+ ]
1679
+ }
1680
+ ]),
1681
+ ["RightHand"]: sideJointPatterns('right', [
1682
+ {
1683
+ all: [
1684
+ 'hand'
1685
+ ],
1686
+ none: [
1687
+ 'thumb',
1688
+ 'index',
1689
+ 'middle',
1690
+ 'ring',
1691
+ 'pinky'
1692
+ ]
1693
+ }
1694
+ ]),
1695
+ ["LeftUpperLeg"]: sideJointPatterns('left', [
1696
+ {
1697
+ all: [
1698
+ 'up',
1699
+ 'leg'
1700
+ ]
1701
+ },
1702
+ {
1703
+ all: [
1704
+ 'upper',
1705
+ 'leg'
1706
+ ]
1707
+ },
1708
+ {
1709
+ all: [
1710
+ 'thigh'
1711
+ ]
1712
+ }
1713
+ ]),
1714
+ ["LeftLowerLeg"]: sideJointPatterns('left', [
1715
+ {
1716
+ all: [
1717
+ 'leg'
1718
+ ],
1719
+ none: [
1720
+ 'upper',
1721
+ 'up',
1722
+ 'thigh',
1723
+ 'foot',
1724
+ 'toe'
1725
+ ]
1726
+ },
1727
+ {
1728
+ all: [
1729
+ 'lower',
1730
+ 'leg'
1731
+ ]
1732
+ },
1733
+ {
1734
+ all: [
1735
+ 'calf'
1736
+ ]
1737
+ },
1738
+ {
1739
+ all: [
1740
+ 'shin'
1741
+ ]
1742
+ }
1743
+ ]),
1744
+ ["LeftFoot"]: sideJointPatterns('left', [
1745
+ {
1746
+ all: [
1747
+ 'foot'
1748
+ ],
1749
+ none: [
1750
+ 'toe'
1751
+ ]
1752
+ }
1753
+ ]),
1754
+ ["LeftToes"]: sideJointPatterns('left', [
1755
+ {
1756
+ all: [
1757
+ 'toe',
1758
+ 'base'
1759
+ ]
1760
+ },
1761
+ {
1762
+ all: [
1763
+ 'toe'
1764
+ ],
1765
+ none: [
1766
+ 'end'
1767
+ ]
1768
+ }
1769
+ ]),
1770
+ ["RightUpperLeg"]: sideJointPatterns('right', [
1771
+ {
1772
+ all: [
1773
+ 'up',
1774
+ 'leg'
1775
+ ]
1776
+ },
1777
+ {
1778
+ all: [
1779
+ 'upper',
1780
+ 'leg'
1781
+ ]
1782
+ },
1783
+ {
1784
+ all: [
1785
+ 'thigh'
1786
+ ]
1787
+ }
1788
+ ]),
1789
+ ["RightLowerLeg"]: sideJointPatterns('right', [
1790
+ {
1791
+ all: [
1792
+ 'leg'
1793
+ ],
1794
+ none: [
1795
+ 'upper',
1796
+ 'up',
1797
+ 'thigh',
1798
+ 'foot',
1799
+ 'toe'
1800
+ ]
1801
+ },
1802
+ {
1803
+ all: [
1804
+ 'lower',
1805
+ 'leg'
1806
+ ]
1807
+ },
1808
+ {
1809
+ all: [
1810
+ 'calf'
1811
+ ]
1812
+ },
1813
+ {
1814
+ all: [
1815
+ 'shin'
1816
+ ]
1817
+ }
1818
+ ]),
1819
+ ["RightFoot"]: sideJointPatterns('right', [
1820
+ {
1821
+ all: [
1822
+ 'foot'
1823
+ ],
1824
+ none: [
1825
+ 'toe'
1826
+ ]
1827
+ }
1828
+ ]),
1829
+ ["RightToes"]: sideJointPatterns('right', [
1830
+ {
1831
+ all: [
1832
+ 'toe',
1833
+ 'base'
1834
+ ]
1835
+ },
1836
+ {
1837
+ all: [
1838
+ 'toe'
1839
+ ],
1840
+ none: [
1841
+ 'end'
1842
+ ]
1843
+ }
1844
+ ])
1845
+ };
1846
+ }
1847
+ static createBipedHumanoidBodyProfile() {
1848
+ return {
1849
+ ["Hips"]: [
1850
+ jointPattern([
1851
+ 'pelvis'
1852
+ ]),
1853
+ jointPattern([
1854
+ 'hips'
1855
+ ])
1856
+ ],
1857
+ ["Spine"]: [
1858
+ jointPattern([
1859
+ 'spine'
1860
+ ], [
1861
+ '1',
1862
+ '2',
1863
+ '3'
1864
+ ])
1865
+ ],
1866
+ ["Chest"]: [
1867
+ jointPattern([
1868
+ 'spine',
1869
+ '1'
1870
+ ]),
1871
+ jointPattern([
1872
+ 'chest'
1873
+ ], [
1874
+ 'upper'
1875
+ ])
1876
+ ],
1877
+ ["UpperChest"]: [
1878
+ jointPattern([
1879
+ 'spine',
1880
+ '2'
1881
+ ]),
1882
+ jointPattern([
1883
+ 'spine',
1884
+ '3'
1885
+ ]),
1886
+ jointPattern([
1887
+ 'upper',
1888
+ 'chest'
1889
+ ])
1890
+ ],
1891
+ ["Neck"]: [
1892
+ jointPattern([
1893
+ 'neck'
1894
+ ], [
1895
+ '1',
1896
+ '2'
1897
+ ])
1898
+ ],
1899
+ ["Head"]: [
1900
+ jointPattern([
1901
+ 'head'
1902
+ ], [
1903
+ 'top',
1904
+ 'end',
1905
+ 'nub'
1906
+ ])
1907
+ ],
1908
+ ["LeftShoulder"]: sideJointPatterns('left', [
1909
+ {
1910
+ all: [
1911
+ 'clavicle'
1912
+ ]
1913
+ },
1914
+ {
1915
+ all: [
1916
+ 'shoulder'
1917
+ ]
1918
+ }
1919
+ ]),
1920
+ ["LeftUpperArm"]: sideJointPatterns('left', [
1921
+ {
1922
+ all: [
1923
+ 'upper',
1924
+ 'arm'
1925
+ ],
1926
+ none: [
1927
+ 'twist'
1928
+ ]
1929
+ },
1930
+ {
1931
+ all: [
1932
+ 'arm'
1933
+ ],
1934
+ none: [
1935
+ 'fore',
1936
+ 'lower',
1937
+ 'hand',
1938
+ 'twist',
1939
+ 'shoulder',
1940
+ 'clavicle'
1941
+ ]
1942
+ }
1943
+ ]),
1944
+ ["LeftLowerArm"]: sideJointPatterns('left', [
1945
+ {
1946
+ all: [
1947
+ 'fore',
1948
+ 'arm'
1949
+ ],
1950
+ none: [
1951
+ 'twist'
1952
+ ]
1953
+ },
1954
+ {
1955
+ all: [
1956
+ 'lower',
1957
+ 'arm'
1958
+ ],
1959
+ none: [
1960
+ 'twist'
1961
+ ]
1962
+ }
1963
+ ]),
1964
+ ["LeftHand"]: sideJointPatterns('left', [
1965
+ {
1966
+ all: [
1967
+ 'hand'
1968
+ ],
1969
+ none: [
1970
+ 'finger',
1971
+ 'thumb',
1972
+ 'index',
1973
+ 'middle',
1974
+ 'ring',
1975
+ 'pinky'
1976
+ ]
1977
+ }
1978
+ ]),
1979
+ ["RightShoulder"]: sideJointPatterns('right', [
1980
+ {
1981
+ all: [
1982
+ 'clavicle'
1983
+ ]
1984
+ },
1985
+ {
1986
+ all: [
1987
+ 'shoulder'
1988
+ ]
1989
+ }
1990
+ ]),
1991
+ ["RightUpperArm"]: sideJointPatterns('right', [
1992
+ {
1993
+ all: [
1994
+ 'upper',
1995
+ 'arm'
1996
+ ],
1997
+ none: [
1998
+ 'twist'
1999
+ ]
2000
+ },
2001
+ {
2002
+ all: [
2003
+ 'arm'
2004
+ ],
2005
+ none: [
2006
+ 'fore',
2007
+ 'lower',
2008
+ 'hand',
2009
+ 'twist',
2010
+ 'shoulder',
2011
+ 'clavicle'
2012
+ ]
2013
+ }
2014
+ ]),
2015
+ ["RightLowerArm"]: sideJointPatterns('right', [
2016
+ {
2017
+ all: [
2018
+ 'fore',
2019
+ 'arm'
2020
+ ],
2021
+ none: [
2022
+ 'twist'
2023
+ ]
2024
+ },
2025
+ {
2026
+ all: [
2027
+ 'lower',
2028
+ 'arm'
2029
+ ],
2030
+ none: [
2031
+ 'twist'
2032
+ ]
2033
+ }
2034
+ ]),
2035
+ ["RightHand"]: sideJointPatterns('right', [
2036
+ {
2037
+ all: [
2038
+ 'hand'
2039
+ ],
2040
+ none: [
2041
+ 'finger',
2042
+ 'thumb',
2043
+ 'index',
2044
+ 'middle',
2045
+ 'ring',
2046
+ 'pinky'
2047
+ ]
2048
+ }
2049
+ ]),
2050
+ ["LeftUpperLeg"]: sideJointPatterns('left', [
2051
+ {
2052
+ all: [
2053
+ 'thigh'
2054
+ ]
2055
+ },
2056
+ {
2057
+ all: [
2058
+ 'upper',
2059
+ 'leg'
2060
+ ]
2061
+ },
2062
+ {
2063
+ all: [
2064
+ 'up',
2065
+ 'leg'
2066
+ ]
2067
+ }
2068
+ ]),
2069
+ ["LeftLowerLeg"]: sideJointPatterns('left', [
2070
+ {
2071
+ all: [
2072
+ 'calf'
2073
+ ]
2074
+ },
2075
+ {
2076
+ all: [
2077
+ 'lower',
2078
+ 'leg'
2079
+ ]
2080
+ },
2081
+ {
2082
+ all: [
2083
+ 'leg'
2084
+ ],
2085
+ none: [
2086
+ 'upper',
2087
+ 'up',
2088
+ 'thigh',
2089
+ 'foot',
2090
+ 'toe'
2091
+ ]
2092
+ }
2093
+ ]),
2094
+ ["LeftFoot"]: sideJointPatterns('left', [
2095
+ {
2096
+ all: [
2097
+ 'foot'
2098
+ ],
2099
+ none: [
2100
+ 'toe'
2101
+ ]
2102
+ }
2103
+ ]),
2104
+ ["LeftToes"]: sideJointPatterns('left', [
2105
+ {
2106
+ all: [
2107
+ 'toe',
2108
+ '0'
2109
+ ]
2110
+ },
2111
+ {
2112
+ all: [
2113
+ 'toe'
2114
+ ],
2115
+ none: [
2116
+ 'end'
2117
+ ]
2118
+ }
2119
+ ]),
2120
+ ["RightUpperLeg"]: sideJointPatterns('right', [
2121
+ {
2122
+ all: [
2123
+ 'thigh'
2124
+ ]
2125
+ },
2126
+ {
2127
+ all: [
2128
+ 'upper',
2129
+ 'leg'
2130
+ ]
2131
+ },
2132
+ {
2133
+ all: [
2134
+ 'up',
2135
+ 'leg'
2136
+ ]
2137
+ }
2138
+ ]),
2139
+ ["RightLowerLeg"]: sideJointPatterns('right', [
2140
+ {
2141
+ all: [
2142
+ 'calf'
2143
+ ]
2144
+ },
2145
+ {
2146
+ all: [
2147
+ 'lower',
2148
+ 'leg'
2149
+ ]
2150
+ },
2151
+ {
2152
+ all: [
2153
+ 'leg'
2154
+ ],
2155
+ none: [
2156
+ 'upper',
2157
+ 'up',
2158
+ 'thigh',
2159
+ 'foot',
2160
+ 'toe'
2161
+ ]
2162
+ }
2163
+ ]),
2164
+ ["RightFoot"]: sideJointPatterns('right', [
2165
+ {
2166
+ all: [
2167
+ 'foot'
2168
+ ],
2169
+ none: [
2170
+ 'toe'
2171
+ ]
2172
+ }
2173
+ ]),
2174
+ ["RightToes"]: sideJointPatterns('right', [
2175
+ {
2176
+ all: [
2177
+ 'toe',
2178
+ '0'
2179
+ ]
2180
+ },
2181
+ {
2182
+ all: [
2183
+ 'toe'
2184
+ ],
2185
+ none: [
2186
+ 'end'
2187
+ ]
2188
+ }
2189
+ ])
2190
+ };
2191
+ }
2192
+ static isParentOf(parent, child) {
2193
+ while(child && child !== parent){
2194
+ child = child.parent;
2195
+ }
2196
+ return child === parent;
2197
+ }
2198
+ static iterateNode(root, callback) {
2199
+ if (callback(root)) {
2200
+ return true;
2201
+ }
2202
+ for (const child of root.children){
2203
+ if (this.iterateNode(child, callback)) {
2204
+ return true;
2205
+ }
2206
+ }
2207
+ return false;
2208
+ }
2209
+ static tryExtractHumanoidJointsByBodyProfile(root, bodyProfile) {
2210
+ const nodes = this.collectHumanoidJointNodeInfos(root);
2211
+ const used = new Set();
2212
+ const bodyCandidates = this.matchHumanoidBodyProfile(nodes, bodyProfile, used, new Set([
2213
+ "Chest",
2214
+ "UpperChest"
2215
+ ]));
2216
+ if (!bodyCandidates) {
2217
+ return null;
2218
+ }
2219
+ const body = this.completeHumanoidBody(bodyCandidates);
2220
+ if (!body) {
2221
+ return null;
2222
+ }
2223
+ const leftHand = this.tryExtractOptionalHumanoidHand(nodes, 'left', used);
2224
+ const rightHand = this.tryExtractOptionalHumanoidHand(nodes, 'right', used);
2225
+ const result = {
2226
+ body,
2227
+ leftHand,
2228
+ rightHand
2229
+ };
2230
+ return this.validateHumanoidJointExtraction(result) ? result : null;
2231
+ }
2232
+ /**
2233
+ * Attempt to extract humanoid joint mappings from the skeleton's joints based on their names.
2234
+ *
2235
+ * This method looks for joints with names matching the standardized `HumanoidBodyRig` and `HumanoidHandRig` enums.
2236
+ * If a complete mapping is found, it returns an object containing the mapped joints for the body and hands.
2237
+ * If any required joint is missing, it returns `null`.
2238
+ *
2239
+ * This method tries to find the best match for humanoid rigs, designed to work with Mixamo, VRoid, Unity Humanoid,
2240
+ * Biped, and similar skeletons. It is not guaranteed to work with all models, and may require manual adjustments or
2241
+ * custom modifiers for non-standard rigs.
2242
+ *
2243
+ * @param root - The root scene node to search for humanoid joints.
2244
+ * @returns An object containing the mapped body and hand joints if a complete humanoid rig is detected, otherwise `null`.
2245
+ */ static tryExtractHumanoidJoints(root) {
2246
+ return this.tryExtractHumanoidJointsMixamo(root) ?? this.tryExtractHumanoidJointsVRM(root) ?? this.tryExtractHumanoidJointsUnityHumanoid(root) ?? this.tryExtractHumanoidJointsBiped(root);
2247
+ }
2248
+ static tryExtractHumanoidJointsMixamo(root) {
2249
+ return this.tryExtractHumanoidJointsByBodyProfile(root, this.createMixamoHumanoidBodyProfile());
2250
+ }
2251
+ static tryExtractHumanoidJointsVRM(root) {
2252
+ return this.tryExtractHumanoidJointsByBodyProfile(root, this.createStandardHumanoidBodyProfile());
2253
+ }
2254
+ static tryExtractHumanoidJointsUnityHumanoid(root) {
2255
+ return this.tryExtractHumanoidJointsByBodyProfile(root, this.createStandardHumanoidBodyProfile());
2256
+ }
2257
+ static tryExtractHumanoidJointsBiped(root) {
2258
+ return this.tryExtractHumanoidJointsByBodyProfile(root, this.createBipedHumanoidBodyProfile());
2259
+ }
356
2260
  }
357
2261
 
358
- export { Skeleton };
2262
+ export { HumanoidBodyRig, HumanoidHandRig, Skeleton };
359
2263
  //# sourceMappingURL=skeleton.js.map