@bitefoundry/retrieviewer 0.0.3 → 0.0.4

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 (254) hide show
  1. package/ASSET-PROVENANCE.md +6 -0
  2. package/ASSETS-LICENSE.md +2 -1
  3. package/ATTRIBUTION.md +6 -1
  4. package/COMFORT-ART.md +65 -0
  5. package/DESKTOP-PLATFORMS.md +6 -1
  6. package/PLUGIN.md +13 -10
  7. package/PREREQUISITES.md +95 -0
  8. package/PUPPY-MEMORY.md +102 -1
  9. package/README.ko.md +110 -0
  10. package/README.md +117 -59
  11. package/RELEASING.md +23 -12
  12. package/THIRD-PARTY-NOTICES.md +5 -3
  13. package/braille.mjs +35 -9
  14. package/examples/live.mjs +2 -2
  15. package/integrations/linux-overlay/overlay.py +2 -2
  16. package/integrations/macos-overlay/overlay.jxa +8 -6
  17. package/integrations/opencode/runtime.mjs +4 -4
  18. package/integrations/opencode/tui.tsx +1 -1
  19. package/integrations/windows-overlay/Overlay.cs +4 -4
  20. package/integrations/windows-overlay/protocol.mjs +11 -7
  21. package/package.json +34 -13
  22. package/puppy-comfort-sprites.mjs +25 -0
  23. package/puppy-companion-comfort-q5.bin.gz +0 -0
  24. package/puppy-companion-comfort.json +77 -0
  25. package/puppy-companion-life.mjs +49 -16
  26. package/puppy-companion-objects.mjs +12 -0
  27. package/puppy-frame-predictive.mjs +15 -9
  28. package/puppy-frame-store.mjs +2 -2
  29. package/puppy-paper-world.mjs +14 -0
  30. package/puppy-paper.mjs +65 -14
  31. package/retrieviewer-plugin.d.mts +1 -1
  32. package/retrieviewer-plugin.mjs +1 -1
  33. package/retrieviewer.d.mts +10 -4
  34. package/retrieviewer.mjs +20 -14
  35. package/locomotion-core.mjs +0 -21
  36. package/locomotion-puppy.animal +0 -0
  37. package/vendor/procedural-animals/package.json +0 -40
  38. package/vendor/procedural-animals/src/animal.js +0 -146
  39. package/vendor/procedural-animals/src/bake.js +0 -51
  40. package/vendor/procedural-animals/src/build.js +0 -81
  41. package/vendor/procedural-animals/src/core/build/coatKit.js +0 -121
  42. package/vendor/procedural-animals/src/core/build/featherCards.js +0 -189
  43. package/vendor/procedural-animals/src/core/build/finEdges.js +0 -85
  44. package/vendor/procedural-animals/src/core/build/furSlope.js +0 -115
  45. package/vendor/procedural-animals/src/core/build/mesh.js +0 -67
  46. package/vendor/procedural-animals/src/core/build/pipeline.js +0 -272
  47. package/vendor/procedural-animals/src/core/build/seams.js +0 -183
  48. package/vendor/procedural-animals/src/core/build/warp.js +0 -112
  49. package/vendor/procedural-animals/src/core/build/weights.js +0 -393
  50. package/vendor/procedural-animals/src/core/math/vec.js +0 -81
  51. package/vendor/procedural-animals/src/core/motion/actions.js +0 -800
  52. package/vendor/procedural-animals/src/core/motion/bird.js +0 -3063
  53. package/vendor/procedural-animals/src/core/motion/birdActions.js +0 -1059
  54. package/vendor/procedural-animals/src/core/motion/common.js +0 -158
  55. package/vendor/procedural-animals/src/core/motion/index.js +0 -22
  56. package/vendor/procedural-animals/src/core/motion/quadruped.js +0 -2875
  57. package/vendor/procedural-animals/src/core/motion/snake.js +0 -1594
  58. package/vendor/procedural-animals/src/core/motion/spider.js +0 -1810
  59. package/vendor/procedural-animals/src/core/motion/swimmer.js +0 -1047
  60. package/vendor/procedural-animals/src/core/motion/swimmerActions.js +0 -613
  61. package/vendor/procedural-animals/src/core/render/animalObject.js +0 -262
  62. package/vendor/procedural-animals/src/core/render/coatMaterial.js +0 -1301
  63. package/vendor/procedural-animals/src/core/render/dqs.js +0 -159
  64. package/vendor/procedural-animals/src/core/render/eyes.js +0 -676
  65. package/vendor/procedural-animals/src/core/render/membranes.js +0 -77
  66. package/vendor/procedural-animals/src/core/render/skeleton.js +0 -41
  67. package/vendor/procedural-animals/src/core/rig/bird.js +0 -327
  68. package/vendor/procedural-animals/src/core/rig/quadruped.js +0 -76
  69. package/vendor/procedural-animals/src/core/rig/rig.js +0 -79
  70. package/vendor/procedural-animals/src/core/rig/snake.js +0 -76
  71. package/vendor/procedural-animals/src/core/rig/spider.js +0 -110
  72. package/vendor/procedural-animals/src/core/rig/swimmer.js +0 -181
  73. package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +0 -53
  74. package/vendor/procedural-animals/src/core/sdf/mesher.js +0 -238
  75. package/vendor/procedural-animals/src/core/sdf/sdf.js +0 -263
  76. package/vendor/procedural-animals/src/index.d.ts +0 -98
  77. package/vendor/procedural-animals/src/index.js +0 -29
  78. package/vendor/procedural-animals/src/registry.js +0 -48
  79. package/vendor/procedural-animals/src/species/bear/behaviour.js +0 -463
  80. package/vendor/procedural-animals/src/species/bear/claws.js +0 -147
  81. package/vendor/procedural-animals/src/species/bear/coat.js +0 -726
  82. package/vendor/procedural-animals/src/species/bear/index.js +0 -139
  83. package/vendor/procedural-animals/src/species/bear/motion.js +0 -112
  84. package/vendor/procedural-animals/src/species/bear/regions.js +0 -78
  85. package/vendor/procedural-animals/src/species/bear/rig.js +0 -112
  86. package/vendor/procedural-animals/src/species/bear/sculpt.js +0 -272
  87. package/vendor/procedural-animals/src/species/boar/behaviour.js +0 -335
  88. package/vendor/procedural-animals/src/species/boar/coat.js +0 -372
  89. package/vendor/procedural-animals/src/species/boar/index.js +0 -110
  90. package/vendor/procedural-animals/src/species/boar/motion.js +0 -85
  91. package/vendor/procedural-animals/src/species/boar/regions.js +0 -88
  92. package/vendor/procedural-animals/src/species/boar/rig.js +0 -111
  93. package/vendor/procedural-animals/src/species/boar/sculpt.js +0 -285
  94. package/vendor/procedural-animals/src/species/cat/behaviour.js +0 -559
  95. package/vendor/procedural-animals/src/species/cat/coat.js +0 -841
  96. package/vendor/procedural-animals/src/species/cat/index.js +0 -211
  97. package/vendor/procedural-animals/src/species/cat/motion.js +0 -101
  98. package/vendor/procedural-animals/src/species/cat/regions.js +0 -82
  99. package/vendor/procedural-animals/src/species/cat/rig.js +0 -100
  100. package/vendor/procedural-animals/src/species/cat/sculpt.js +0 -266
  101. package/vendor/procedural-animals/src/species/cat/whiskers.js +0 -110
  102. package/vendor/procedural-animals/src/species/cheetah/coat.js +0 -427
  103. package/vendor/procedural-animals/src/species/cheetah/index.js +0 -51
  104. package/vendor/procedural-animals/src/species/cheetah/joints.js +0 -3
  105. package/vendor/procedural-animals/src/species/cheetah/motion.js +0 -77
  106. package/vendor/procedural-animals/src/species/cheetah/regions.js +0 -95
  107. package/vendor/procedural-animals/src/species/cheetah/rig.js +0 -66
  108. package/vendor/procedural-animals/src/species/cheetah/sculpt.js +0 -158
  109. package/vendor/procedural-animals/src/species/chicken/coat.js +0 -313
  110. package/vendor/procedural-animals/src/species/chicken/coverts.js +0 -320
  111. package/vendor/procedural-animals/src/species/chicken/index.js +0 -110
  112. package/vendor/procedural-animals/src/species/chicken/motion.js +0 -177
  113. package/vendor/procedural-animals/src/species/chicken/regions.js +0 -66
  114. package/vendor/procedural-animals/src/species/chicken/rig.js +0 -144
  115. package/vendor/procedural-animals/src/species/chicken/sculpt.js +0 -389
  116. package/vendor/procedural-animals/src/species/chicken/wingLook.js +0 -66
  117. package/vendor/procedural-animals/src/species/chicken/wingStack.js +0 -124
  118. package/vendor/procedural-animals/src/species/cow/behaviour.js +0 -521
  119. package/vendor/procedural-animals/src/species/cow/coat.js +0 -465
  120. package/vendor/procedural-animals/src/species/cow/index.js +0 -118
  121. package/vendor/procedural-animals/src/species/cow/motion.js +0 -81
  122. package/vendor/procedural-animals/src/species/cow/regions.js +0 -98
  123. package/vendor/procedural-animals/src/species/cow/rig.js +0 -116
  124. package/vendor/procedural-animals/src/species/cow/sculpt.js +0 -339
  125. package/vendor/procedural-animals/src/species/crow/coat.js +0 -145
  126. package/vendor/procedural-animals/src/species/crow/index.js +0 -70
  127. package/vendor/procedural-animals/src/species/crow/joints.js +0 -3
  128. package/vendor/procedural-animals/src/species/crow/motion.js +0 -101
  129. package/vendor/procedural-animals/src/species/crow/regions.js +0 -50
  130. package/vendor/procedural-animals/src/species/crow/rig.js +0 -83
  131. package/vendor/procedural-animals/src/species/crow/sculpt.js +0 -118
  132. package/vendor/procedural-animals/src/species/deer/behaviour.js +0 -513
  133. package/vendor/procedural-animals/src/species/deer/coat.js +0 -391
  134. package/vendor/procedural-animals/src/species/deer/index.js +0 -106
  135. package/vendor/procedural-animals/src/species/deer/motion.js +0 -97
  136. package/vendor/procedural-animals/src/species/deer/regions.js +0 -60
  137. package/vendor/procedural-animals/src/species/deer/rig.js +0 -124
  138. package/vendor/procedural-animals/src/species/deer/sculpt.js +0 -297
  139. package/vendor/procedural-animals/src/species/dog/behaviour.js +0 -521
  140. package/vendor/procedural-animals/src/species/dog/coat.js +0 -495
  141. package/vendor/procedural-animals/src/species/dog/index.js +0 -144
  142. package/vendor/procedural-animals/src/species/dog/motion.js +0 -118
  143. package/vendor/procedural-animals/src/species/dog/regions.js +0 -61
  144. package/vendor/procedural-animals/src/species/dog/rig.js +0 -129
  145. package/vendor/procedural-animals/src/species/dog/sculpt.js +0 -246
  146. package/vendor/procedural-animals/src/species/eagle/coat.js +0 -250
  147. package/vendor/procedural-animals/src/species/eagle/index.js +0 -76
  148. package/vendor/procedural-animals/src/species/eagle/joints.js +0 -3
  149. package/vendor/procedural-animals/src/species/eagle/motion.js +0 -137
  150. package/vendor/procedural-animals/src/species/eagle/regions.js +0 -57
  151. package/vendor/procedural-animals/src/species/eagle/rig.js +0 -107
  152. package/vendor/procedural-animals/src/species/eagle/sculpt.js +0 -137
  153. package/vendor/procedural-animals/src/species/fish/coat.js +0 -271
  154. package/vendor/procedural-animals/src/species/fish/index.js +0 -88
  155. package/vendor/procedural-animals/src/species/fish/motion.js +0 -92
  156. package/vendor/procedural-animals/src/species/fish/regions.js +0 -27
  157. package/vendor/procedural-animals/src/species/fish/rig.js +0 -143
  158. package/vendor/procedural-animals/src/species/fish/sculpt.js +0 -214
  159. package/vendor/procedural-animals/src/species/fish/variants.js +0 -126
  160. package/vendor/procedural-animals/src/species/fox/behaviour.js +0 -314
  161. package/vendor/procedural-animals/src/species/fox/coat.js +0 -444
  162. package/vendor/procedural-animals/src/species/fox/index.js +0 -120
  163. package/vendor/procedural-animals/src/species/fox/motion.js +0 -81
  164. package/vendor/procedural-animals/src/species/fox/regions.js +0 -59
  165. package/vendor/procedural-animals/src/species/fox/rig.js +0 -91
  166. package/vendor/procedural-animals/src/species/fox/sculpt.js +0 -202
  167. package/vendor/procedural-animals/src/species/frog/behaviour.js +0 -590
  168. package/vendor/procedural-animals/src/species/frog/coat.js +0 -305
  169. package/vendor/procedural-animals/src/species/frog/index.js +0 -97
  170. package/vendor/procedural-animals/src/species/frog/motion.js +0 -69
  171. package/vendor/procedural-animals/src/species/frog/regions.js +0 -46
  172. package/vendor/procedural-animals/src/species/frog/rig.js +0 -156
  173. package/vendor/procedural-animals/src/species/frog/sculpt.js +0 -240
  174. package/vendor/procedural-animals/src/species/goat/behaviour.js +0 -509
  175. package/vendor/procedural-animals/src/species/goat/coat.js +0 -590
  176. package/vendor/procedural-animals/src/species/goat/index.js +0 -149
  177. package/vendor/procedural-animals/src/species/goat/motion.js +0 -95
  178. package/vendor/procedural-animals/src/species/goat/regions.js +0 -98
  179. package/vendor/procedural-animals/src/species/goat/rig.js +0 -181
  180. package/vendor/procedural-animals/src/species/goat/sculpt.js +0 -547
  181. package/vendor/procedural-animals/src/species/horse/coat.js +0 -361
  182. package/vendor/procedural-animals/src/species/horse/coatSeam.js +0 -122
  183. package/vendor/procedural-animals/src/species/horse/index.js +0 -80
  184. package/vendor/procedural-animals/src/species/horse/motion.js +0 -245
  185. package/vendor/procedural-animals/src/species/horse/regions.js +0 -60
  186. package/vendor/procedural-animals/src/species/horse/rig.js +0 -117
  187. package/vendor/procedural-animals/src/species/horse/sculpt.js +0 -316
  188. package/vendor/procedural-animals/src/species/horse/seamWeights.js +0 -272
  189. package/vendor/procedural-animals/src/species/lion/behaviour.js +0 -509
  190. package/vendor/procedural-animals/src/species/lion/coat.js +0 -1016
  191. package/vendor/procedural-animals/src/species/lion/index.js +0 -111
  192. package/vendor/procedural-animals/src/species/lion/motion.js +0 -87
  193. package/vendor/procedural-animals/src/species/lion/regions.js +0 -106
  194. package/vendor/procedural-animals/src/species/lion/rig.js +0 -110
  195. package/vendor/procedural-animals/src/species/lion/sculpt.js +0 -384
  196. package/vendor/procedural-animals/src/species/lion/whiskers.js +0 -132
  197. package/vendor/procedural-animals/src/species/pig/behaviour.js +0 -575
  198. package/vendor/procedural-animals/src/species/pig/coat.js +0 -730
  199. package/vendor/procedural-animals/src/species/pig/ears.js +0 -242
  200. package/vendor/procedural-animals/src/species/pig/index.js +0 -161
  201. package/vendor/procedural-animals/src/species/pig/motion.js +0 -105
  202. package/vendor/procedural-animals/src/species/pig/regions.js +0 -100
  203. package/vendor/procedural-animals/src/species/pig/rig.js +0 -152
  204. package/vendor/procedural-animals/src/species/pig/sculpt.js +0 -382
  205. package/vendor/procedural-animals/src/species/rabbit/behaviour.js +0 -605
  206. package/vendor/procedural-animals/src/species/rabbit/coat.js +0 -285
  207. package/vendor/procedural-animals/src/species/rabbit/index.js +0 -85
  208. package/vendor/procedural-animals/src/species/rabbit/motion.js +0 -85
  209. package/vendor/procedural-animals/src/species/rabbit/regions.js +0 -48
  210. package/vendor/procedural-animals/src/species/rabbit/rig.js +0 -99
  211. package/vendor/procedural-animals/src/species/rabbit/sculpt.js +0 -148
  212. package/vendor/procedural-animals/src/species/rat/behaviour.js +0 -539
  213. package/vendor/procedural-animals/src/species/rat/coat.js +0 -341
  214. package/vendor/procedural-animals/src/species/rat/index.js +0 -111
  215. package/vendor/procedural-animals/src/species/rat/motion.js +0 -90
  216. package/vendor/procedural-animals/src/species/rat/regions.js +0 -92
  217. package/vendor/procedural-animals/src/species/rat/rig.js +0 -112
  218. package/vendor/procedural-animals/src/species/rat/sculpt.js +0 -163
  219. package/vendor/procedural-animals/src/species/rat/whiskers.js +0 -119
  220. package/vendor/procedural-animals/src/species/shark/coat.js +0 -383
  221. package/vendor/procedural-animals/src/species/shark/index.js +0 -104
  222. package/vendor/procedural-animals/src/species/shark/motion.js +0 -69
  223. package/vendor/procedural-animals/src/species/shark/regions.js +0 -34
  224. package/vendor/procedural-animals/src/species/shark/rig.js +0 -194
  225. package/vendor/procedural-animals/src/species/shark/sculpt.js +0 -343
  226. package/vendor/procedural-animals/src/species/shark/variants.js +0 -105
  227. package/vendor/procedural-animals/src/species/sheep/behaviour.js +0 -522
  228. package/vendor/procedural-animals/src/species/sheep/coat.js +0 -529
  229. package/vendor/procedural-animals/src/species/sheep/index.js +0 -152
  230. package/vendor/procedural-animals/src/species/sheep/motion.js +0 -86
  231. package/vendor/procedural-animals/src/species/sheep/neck.js +0 -41
  232. package/vendor/procedural-animals/src/species/sheep/regions.js +0 -62
  233. package/vendor/procedural-animals/src/species/sheep/rig.js +0 -163
  234. package/vendor/procedural-animals/src/species/sheep/sculpt.js +0 -542
  235. package/vendor/procedural-animals/src/species/snake/coat.js +0 -315
  236. package/vendor/procedural-animals/src/species/snake/index.js +0 -73
  237. package/vendor/procedural-animals/src/species/snake/motion.js +0 -51
  238. package/vendor/procedural-animals/src/species/snake/regions.js +0 -51
  239. package/vendor/procedural-animals/src/species/snake/rig.js +0 -108
  240. package/vendor/procedural-animals/src/species/snake/sculpt.js +0 -122
  241. package/vendor/procedural-animals/src/species/spider/coat.js +0 -279
  242. package/vendor/procedural-animals/src/species/spider/index.js +0 -78
  243. package/vendor/procedural-animals/src/species/spider/motion.js +0 -72
  244. package/vendor/procedural-animals/src/species/spider/regions.js +0 -87
  245. package/vendor/procedural-animals/src/species/spider/rig.js +0 -118
  246. package/vendor/procedural-animals/src/species/spider/sculpt.js +0 -182
  247. package/vendor/procedural-animals/src/species/wolf/behaviour.js +0 -160
  248. package/vendor/procedural-animals/src/species/wolf/coat.js +0 -749
  249. package/vendor/procedural-animals/src/species/wolf/index.js +0 -107
  250. package/vendor/procedural-animals/src/species/wolf/motion.js +0 -80
  251. package/vendor/procedural-animals/src/species/wolf/regions.js +0 -57
  252. package/vendor/procedural-animals/src/species/wolf/rig.js +0 -87
  253. package/vendor/procedural-animals/src/species/wolf/sculpt.js +0 -339
  254. package/vendor/procedural-animals/src/worker.js +0 -29
@@ -1,118 +0,0 @@
1
- // Spider skeleton in bind pose (metres; dimensions below are written in millimetres).
2
- // Forward = +Z, up = +Y, the animal's left = +X. Two variants share the rig: the wolf spider
3
- // (Lycosidae, reference female Hogna carolinensis, body 25 mm) and the tarantula (Theraphosidae,
4
- // reference female Brachypelma hamorii, body 60 mm).
5
- import { buildRig } from '../../core/rig/rig.js';
6
- import { spiderBones, spiderLimbs, planarChain, solveBindElevations, legJoints, palpJoints, AXIAL_POINTS, AXIAL_BONES } from '../../core/rig/spider.js';
7
-
8
- const D2R = Math.PI / 180;
9
- const mm = (v) => v.map((x) => x * 0.001);
10
-
11
- // Per-variant anatomy (mm, degrees). leg: [I, II, III, IV] total lengths; seg: segment fractions
12
- // coxa, trochanter, femur, patella, tibia, metatarsus, tarsus; el: bind elevations of the segments
13
- // (the metatarsus is solved so the claw rests on the ground); r: segment radii (base, end).
14
- export const VARIANTS = {
15
- wolf: {
16
- unit: 0.013,
17
- bodyLen: 25,
18
- axial: { front: [0, 7.4, 6.5], ceph: [0, 7.6, 1.6], pedA: [0, 6.3, -4.5], pedB: [0, 6.1, -5.7], abdEnd: [0, 5.4, -17.2], spinTip: [0, 4.7, -18.5] },
19
- carapace: { len: 11, wid: 8.6, top: 9.9, rearTop: 7.3, bottom: 4.5, headW: 5.2 },
20
- abdomen: { c: [0, 6.5, -11.4], r: [3.9, 3.35, 6.1] },
21
- chel: { base: [0.95, 7.0, 6.1], tip: [0.9, 3.8, 7.0], fang: [0.15, 4.25, 6.75], r: [0.95, 0.72], fangR: 0.2 },
22
- coxa: { y: 5.1, x: [2.35, 2.75, 2.75, 2.45], z: [3.3, 1.4, -0.6, -2.6], az: [30, 66, 112, 150] },
23
- leg: [35, 33, 31, 43],
24
- seg: [0.08, 0.05, 0.26, 0.12, 0.2, 0.19, 0.1],
25
- el: [-14, 4, 30, -6, -28, 0, -14],
26
- legR: [[1.05, 0.95], [0.84, 0.8], [0.8, 0.68], [0.7, 0.63], [0.63, 0.53], [0.5, 0.4], [0.39, 0.29]],
27
- hindR: 1.06,
28
- tipY: 0.32,
29
- palp: { base: [1.75, 5.2, 5.4], az: 14, len: 16, seg: [0.12, 0.08, 0.3, 0.15, 0.18, 0.17], el: [-30, -10, 15, -30, 0, -50], r: [[0.62, 0.55], [0.5, 0.48], [0.46, 0.42], [0.42, 0.4], [0.4, 0.37], [0.37, 0.28]], tipY: 0.55 },
30
- spinR: 0.45,
31
- },
32
- tarantula: {
33
- unit: 0.028,
34
- bodyLen: 60,
35
- axial: { front: [0, 13.2, 12.8], ceph: [0, 14.2, 3.5], pedA: [0, 12.0, -11.6], pedB: [0, 11.8, -13.6], abdEnd: [0, 10.8, -41.5], spinTip: [0, 9.2, -46] },
36
- carapace: { len: 25, wid: 23.5, top: 16.2, rearTop: 14.0, bottom: 7.4, headW: 13 },
37
- abdomen: { c: [0, 12.4, -27.6], r: [12.0, 9.6, 14.4] },
38
- chel: { base: [3.0, 12.6, 11.2], tip: [2.9, 9.4, 18.0], fang: [2.6, 4.9, 16.4], r: [3.1, 2.4], fangR: 0.75 },
39
- coxa: { y: 8.6, x: [5.8, 6.7, 6.7, 6.0], z: [6.2, 2.0, -2.6, -7.0], az: [26, 60, 114, 150] },
40
- leg: [65, 60, 55, 72.5],
41
- seg: [0.09, 0.06, 0.25, 0.14, 0.2, 0.16, 0.1],
42
- el: [-10, 6, 34, -4, -30, 0, -13],
43
- legR: [[3.0, 2.7], [2.4, 2.3], [2.3, 2.0], [2.05, 1.95], [1.95, 1.75], [1.65, 1.45], [1.45, 1.25]],
44
- hindR: 1.04,
45
- tipY: 1.3,
46
- palp: { base: [4.6, 8.4, 10.8], az: 16, len: 37, seg: [0.14, 0.08, 0.28, 0.16, 0.18, 0.16], el: [-30, -10, 15, -30, 0, -40], r: [[2.2, 2.0], [1.9, 1.8], [1.8, 1.65], [1.65, 1.55], [1.55, 1.45], [1.45, 1.2]], tipY: 1.3 },
47
- spinR: 1.3,
48
- },
49
- };
50
-
51
- // Anatomy of one individual: the variant's reference numbers with the seeded proportions of
52
- // params (legK: leg length factor, abdK: abdomen size, palpBulb: male palpal bulbs).
53
- export function spiderDims(params = {}) {
54
- const V = VARIANTS[params.variant] || VARIANTS.wolf;
55
- const legK = params.legK || 1, abdK = params.abdK || 1;
56
- const d = JSON.parse(JSON.stringify(V));
57
- d.variant = VARIANTS[params.variant] ? params.variant : 'wolf';
58
- d.leg = V.leg.map((l) => l * legK);
59
- d.palp.len = V.palp.len * (0.5 + 0.5 * legK);
60
- d.abdomen.r = V.abdomen.r.map((r) => r * abdK);
61
- // a bigger abdomen hangs further back from the pedicel
62
- d.abdomen.c = [0, V.abdomen.c[1] + (abdK - 1) * 0.4 * V.abdomen.r[1], V.abdomen.c[2] - (abdK - 1) * V.abdomen.r[2]];
63
- d.axial.abdEnd = [0, V.axial.abdEnd[1] - (abdK - 1) * 0.3 * V.abdomen.r[1], V.axial.abdEnd[2] - 2 * (abdK - 1) * V.abdomen.r[2]];
64
- d.axial.spinTip = [0, V.axial.spinTip[1] - (abdK - 1) * 0.3 * V.abdomen.r[1], V.axial.spinTip[2] - 2 * (abdK - 1) * V.abdomen.r[2]];
65
- d.palpBulb = params.palpBulb || 0;
66
- return d;
67
- }
68
-
69
- export function spiderJoints(params = {}) {
70
- const d = spiderDims(params);
71
- const J = {};
72
- for (const [k, v] of Object.entries(d.axial)) J[k] = mm(v);
73
- J.cheBaseL = mm(d.chel.base);
74
- J.cheTipL = mm(d.chel.tip);
75
- J.fangTipL = mm(d.chel.fang);
76
- for (let i = 1; i <= 4; i++) {
77
- const L = d.leg[i - 1];
78
- const lens = d.seg.map((f) => f * L * 0.001);
79
- const base = mm([d.coxa.x[i - 1], d.coxa.y, d.coxa.z[i - 1]]);
80
- const el = solveBindElevations(base[1], lens, d.el.map((e) => e * D2R), 5, d.tipY * 0.001);
81
- planarChain(J, legJoints(i, 'L'), base, d.coxa.az[i - 1] * D2R, el, lens, 1);
82
- }
83
- {
84
- const P = d.palp;
85
- const lens = P.seg.map((f) => f * P.len * 0.001);
86
- const base = mm(P.base);
87
- // the tibia takes up the height so the tarsus meets the ground slanting forward
88
- const el = solveBindElevations(base[1], lens, P.el.map((e) => e * D2R), 4, P.tipY * 0.001);
89
- planarChain(J, palpJoints('L'), base, P.az * D2R, el, lens, 1);
90
- }
91
- return J;
92
- }
93
-
94
- export function spiderRig(params = {}) {
95
- const d = spiderDims(params);
96
- const J = spiderJoints(params);
97
- const U = d.unit;
98
- return buildRig({
99
- joints: J,
100
- unit: U,
101
- headOrigin: J.ceph,
102
- meta: { dims: d },
103
- bones: spiderBones(),
104
- axial: {
105
- points: AXIAL_POINTS,
106
- bones: AXIAL_BONES,
107
- // the carapace is rigid: head and prosoma share it (the engine never bends them apart); the
108
- // pedicel is a short stalk, blended narrowly into the abdomen
109
- blend: { 1: [-0.1, 0.1], 2: [-0.012, 0.004], 3: [-0.004, 0.02] },
110
- },
111
- limbs: spiderLimbs({
112
- leg: { tCore: 0.5, aCore: 0.05, aBody: -0.05, midX: 0.06 },
113
- palp: { tCore: 0.45, aCore: 0.04, aBody: -0.05, midX: 0.04 },
114
- }),
115
- appendages: [],
116
- webTags: [],
117
- });
118
- }
@@ -1,182 +0,0 @@
1
- // The spider, sculpted as a signed distance field (reference space, metres).
2
- //
3
- // Parts (meshed separately, see regions.js): 'body' (prosoma, pedicel, abdomen, spinnerets, palps,
4
- // coxae and trochanters), one part per leg ('legL1' .. 'legR4': coxa -> tarsus, the coxa and
5
- // trochanter duplicated so both surfaces agree across the cut), 'chelL'/'chelR' (rigid chelicerae)
6
- // and 'fangL'/'fangR' (rigid fangs). Eyes are glossy domes (look.lids 'simple') set in shallow
7
- // sockets on the head.
8
- import { spiderDims } from './rig.js';
9
- import { legJoints, legBones, palpJoints, palpBones } from '../../core/rig/spider.js';
10
- import { add, sub, mul, lerp, norm, cross, len } from '../../core/math/vec.js';
11
- import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
12
- import { QUALITY } from '../../core/build/pipeline.js';
13
-
14
- const M = 0.001;
15
- const mm = (v) => v.map((x) => x * M);
16
-
17
- // Eyes per variant (mm, head-local: relative to the ceph joint; left side). r: radius; yaw: outward
18
- // divergence of the view axis (rad, > PI/2 looks backward); pitch: upward tilt; back: how far the
19
- // dome centre sits inside the surface point.
20
- export const EYES = {
21
- // Lycosidae 4-2-2: a straight anterior row of 4 small eyes above the chelicerae, 2 huge posterior
22
- // median eyes looking forward, 2 posterior lateral eyes on top looking up and back
23
- wolf: [
24
- // (set into the carapace surface: the domes bulge ~0.4 r; the PME sit on the front of the face)
25
- { name: 'PME', c: [1.02, 1.2, 4.57], r: 0.47, yaw: 0.14, pitch: 0.02, back: 0.2 },
26
- { name: 'PLE', c: [1.78, 1.54, 2.72], r: 0.3, yaw: 2.1, pitch: 0.75, back: 0.14 },
27
- { name: 'AME', c: [0.42, 0.3, 5.26], r: 0.22, yaw: 0.05, pitch: -0.05, back: 0.07 },
28
- { name: 'ALE', c: [1.0, 0.3, 5.05], r: 0.17, yaw: 0.55, pitch: -0.05, back: 0.05 },
29
- ],
30
- // Theraphosidae: 8 small eyes clustered on a raised ocular tubercle
31
- tarantula: [
32
- { name: 'AME', c: [0.62, 2.55, 6.1], r: 0.5, yaw: 0.08, pitch: 0.5, back: 0.2 },
33
- { name: 'ALE', c: [1.62, 2.05, 6.25], r: 0.52, yaw: 0.6, pitch: 0.25, back: 0.2 },
34
- { name: 'PME', c: [0.85, 2.6, 5.05], r: 0.3, yaw: 0.5, pitch: 1.0, back: 0.12 },
35
- { name: 'PLE', c: [1.72, 2.2, 4.75], r: 0.42, yaw: 1.7, pitch: 0.45, back: 0.16 },
36
- ],
37
- };
38
-
39
- export function eyeSpec(e) {
40
- const r = e.r * M;
41
- return { c: mm(e.c), r, back: e.back * M, yaw: e.yaw, pitch: e.pitch, tilt: 0, lid: 0, R: r * 1.1, d: r * 0.6, off: 0, irisZ: r * 0.6, irisR: r * 0.8, name: e.name };
42
- }
43
-
44
- // minimum radius of thin parts per quality tier (coarse meshes would lose the tarsi otherwise)
45
- const MIN_R = { hero: 0, high: 0, medium: 0.26, low: 0.4, crowd: 0.58 }; // ~ one cell: legs stay >= 2 voxels thick
46
-
47
- export function sculptSpider(m, rig, params) {
48
- const J = rig.J, d = spiderDims(params);
49
- const F = d.unit / 0.013; // size relative to the wolf spider
50
- const minR = (MIN_R[params.quality] ?? 0) * M * F;
51
- const R = (r) => Math.max(r * M, minR);
52
- const HO = J.ceph;
53
- const hl = (v) => add(HO, mm(v));
54
- const X = [1, 0, 0];
55
- const ellY = (o) => {
56
- const y = norm(o.ydir);
57
- const z = norm(cross(o.lateral || X, y));
58
- return m.ell({ ...o, axis: z, up: y });
59
- };
60
- const wolf = d.variant === 'wolf';
61
- const C = d.carapace;
62
- const z0 = J.pedA[2] / M, z1 = J.front[2] / M, Lc = z1 - z0;
63
- const B = { bone: 'prosoma', group: 'axial', part: 'body' };
64
- const H = { bone: 'head', group: 'axial', part: 'body' };
65
-
66
- // ------------------------------------------------------------------ PROSOMA
67
- // carapace: thoracic dome, raised cephalic region, sloping rear; sternum below
68
- const thTop = C.rearTop + (C.top - C.rearTop) * (wolf ? 0.55 : 0.75);
69
- m.ell({ ...B, tag: 'thorax', c: mm([0, (thTop + C.bottom) / 2, z0 + 0.42 * Lc]), r: mm([C.wid / 2, (thTop - C.bottom) / 2, 0.41 * Lc]), k: 0 });
70
- m.ell({ ...B, tag: 'thoraxRear', c: mm([0, (C.rearTop + C.bottom) / 2 + 0.2 * F, z0 + 0.2 * Lc]), r: mm([C.wid * 0.36, (C.rearTop - C.bottom) / 2, 0.2 * Lc]), k: 0.9 * M * F });
71
- m.ell({ ...H, tag: 'cephalic', c: mm([0, C.top - (wolf ? 2.3 : 3.2) * F, z0 + 0.78 * Lc]), r: mm([C.headW / 2, (wolf ? 2.3 : 3.2) * F, 0.26 * Lc]), axis: norm([0, wolf ? 0.18 : 0.05, 1]), k: 1.2 * M * F });
72
- // clypeus: the face between the anterior eyes and the chelicerae
73
- m.ell({ ...H, tag: 'clypeus', c: add(J.front, mm([0, -0.2 * F, -0.9 * F])), r: mm([C.headW * 0.36, 1.1 * F, 0.9 * F]), k: 0.8 * M * F });
74
- m.ell({ ...B, tag: 'sternum', c: mm([0, C.bottom + 0.45 * F, z0 + 0.5 * Lc]), r: mm([C.wid * 0.27, 0.7 * F, 0.3 * Lc]), k: 0.8 * M * F });
75
- // labium and endites (mouthparts between the palp coxae)
76
- m.ell({ ...B, tag: 'labium', c: mm([0, C.bottom + 0.6 * F, z0 + 0.86 * Lc]), r: mm([0.9 * F, 0.55 * F, 0.9 * F]), k: 0.5 * M * F });
77
- // fovea: a short median groove on the thoracic dome, and the cephalic groove
78
- m.ell({ ...B, tag: 'fovea', c: mm([0, thTop + 0.02 * F, z0 + 0.36 * Lc]), r: mm([0.16 * F, 0.3 * F, 0.9 * F]), k: 0.25 * M * F, carve: true });
79
- if (!wolf) {
80
- // tarantula: low wide carapace with a raised ocular tubercle
81
- m.ell({ ...H, tag: 'tubercle', c: hl([0, 1.7, 5.4]), r: mm([2.3, 1.3, 1.9]), k: 1.1 * M * F });
82
- }
83
-
84
- // ------------------------------------------------------------------ EYES (sockets; the domes are eye meshes)
85
- for (const e of EYES[d.variant]) {
86
- const E = eyeSpec(e);
87
- for (const s of [1, -1]) {
88
- const ef = eyeFrameOf(E, HO, s);
89
- // a raised rim around the lens, cut open by the socket the dome sits in
90
- m.sphere({ ...H, tag: 'eyerim', c: add(ef.c, mul(ef.z, -E.r * 0.25)), rad: E.r * 1.05, k: E.r * 0.6 });
91
- m.sphere({ ...H, tag: 'eyesocket', c: add(ef.c, mul(ef.z, E.r * 0.1)), rad: E.r * 0.98, k: E.r * 0.15, carve: true });
92
- }
93
- }
94
-
95
- // ------------------------------------------------------------------ PEDICEL, ABDOMEN, SPINNERETS
96
- const A = { bone: 'abdomen', group: 'axial', part: 'body' };
97
- m.cone({ bone: 'pedicel', group: 'axial', part: 'body', tag: 'pedicel', a: J.pedA, b: J.pedB, ra: (wolf ? 0.75 : 1.9) * M * F / F * (wolf ? 1 : 1), rb: (wolf ? 0.7 : 1.8) * M, k: 0.3 * M * F });
98
- const ac = mm(d.abdomen.c), ar = mm(d.abdomen.r);
99
- m.ell({ ...A, tag: 'abdomen', c: ac, r: ar, axis: norm([0, 0.06, 1]), k: 0 });
100
- m.ell({ ...A, tag: 'abdomenFront', c: add(ac, [0, -ar[1] * 0.05, ar[2] * 0.52]), r: [ar[0] * 0.7, ar[1] * 0.72, ar[2] * 0.45], k: 1.0 * M * F });
101
- m.ell({ ...A, tag: 'abdomenRear', c: add(ac, [0, -ar[1] * 0.12, -ar[2] * 0.6]), r: [ar[0] * 0.72, ar[1] * 0.72, ar[2] * 0.42], k: 1.2 * M * F });
102
- // spinnerets: wolf 3 short pairs; tarantula 2 visible pairs, the posterior pair long and finger-like
103
- const SP = { bone: 'spinnerets', group: 'axial', part: 'body', tag: 'spinneret' };
104
- const st = J.abdEnd, sd = norm(sub(J.spinTip, J.abdEnd)), sl = len(sub(J.spinTip, J.abdEnd));
105
- for (const s of [1, -1]) {
106
- if (wolf) {
107
- m.cone({ ...SP, a: add(st, mm([0.45 * s, -0.25, 0.3])), b: add(add(st, mul(sd, sl * 0.9)), mm([0.5 * s, -0.2, 0])), ra: d.spinR * M, rb: d.spinR * 0.7 * M, k: 0.25 * M });
108
- m.cone({ ...SP, a: add(st, mm([0.2 * s, -0.6, 0.3])), b: add(add(st, mul(sd, sl * 0.7)), mm([0.2 * s, -0.55, 0])), ra: d.spinR * 0.8 * M, rb: d.spinR * 0.55 * M, k: 0.25 * M });
109
- } else {
110
- m.cone({ ...SP, a: add(st, mm([1.1 * s, -0.4, 0.8])), b: add(add(st, mul(sd, sl * 1.15)), mm([1.9 * s, 0.9, 0])), ra: d.spinR * M, rb: d.spinR * 0.62 * M, k: 0.8 * M });
111
- m.cone({ ...SP, a: add(st, mm([0.55 * s, -1.2, 0.8])), b: add(add(st, mul(sd, sl * 0.45)), mm([0.6 * s, -1.4, 0])), ra: d.spinR * 0.6 * M, rb: d.spinR * 0.45 * M, k: 0.6 * M });
112
- }
113
- }
114
-
115
- // ------------------------------------------------------------------ CHELICERAE AND FANGS (rigid parts)
116
- for (const S of ['L', 'R']) {
117
- const s = S === 'L' ? 1 : -1;
118
- const b0 = J['cheBase' + S], b1 = J['cheTip' + S], ft = J['fangTip' + S];
119
- const CH = { bone: 'chelicera' + S, group: 'chel' + S, part: 'chel' + S };
120
- const cr = d.chel.r.map((r) => r * M);
121
- const dir = norm(sub(b1, b0));
122
- m.cone({ ...CH, tag: 'chelicera', a: b0, b: add(b1, mul(dir, -cr[1] * 0.4)), ra: cr[0], rb: cr[1], k: 0 });
123
- // the stout basal boss bulging forward (wolf) / the long forward-projecting paturon (tarantula)
124
- ellY({ ...CH, tag: 'chelicera', c: add(lerp(b0, b1, 0.35), mm([0.1 * s * F, 0, (wolf ? 0.35 : 0.8) * F])), ydir: dir, r: [cr[0] * 0.92, len(sub(b1, b0)) * 0.4, cr[0] * 0.95], k: 0.5 * M * F });
125
- // fang groove with its row of teeth: a shallow furrow on the inner face
126
- ellY({ ...CH, tag: 'fangGroove', c: add(lerp(b0, b1, 0.8), mm([-0.55 * s * F, 0, 0.1 * F])), ydir: dir, r: [cr[1] * 0.35, len(sub(b1, b0)) * 0.22, cr[1] * 0.4], k: 0.2 * M * F, carve: true });
127
- const FG = { bone: 'fang' + S, group: 'fang' + S, part: 'fang' + S, tag: 'fang' };
128
- const fr = d.chel.fangR * M;
129
- // a curved fang: base, then bending toward the tip
130
- const fd = norm(sub(ft, b1)), fl = len(sub(ft, b1));
131
- const bend = norm(cross(fd, [s, 0, 0]));
132
- const mid = add(lerp(b1, ft, 0.5), mul(bend, fl * 0.12));
133
- m.cone({ ...FG, a: add(b1, mul(fd, -fr * 0.5)), b: mid, ra: fr, rb: fr * 0.62, k: 0.08 * M * F });
134
- m.cone({ ...FG, a: mid, b: ft, ra: fr * 0.62, rb: fr * 0.12, k: 0.08 * M * F });
135
- }
136
-
137
- // ------------------------------------------------------------------ PALPS (body part)
138
- for (const S of ['L', 'R']) {
139
- const pj = palpJoints(S), pb = palpBones(S);
140
- const g = { group: 'P' + S, part: 'body' };
141
- for (let k = 0; k < pb.length; k++) {
142
- const [ra, rb] = d.palp.r[k];
143
- const a = J[pj[k]], b = J[pj[k + 1]];
144
- m.cone({ ...g, bone: pb[k], tag: k === 0 ? 'palpcoxa' : 'palp', a, b, ra: R(ra * F / F), rb: R(rb), k: (k === 0 ? 0.6 : 0.09) * M * F });
145
- if (k > 0 && k < pb.length - 1) m.sphere({ ...g, bone: pb[k], tag: 'knuckle', c: b, rad: R(rb * 1.08), k: 0.08 * M * F });
146
- }
147
- if (d.palpBulb > 0) {
148
- // male: the swollen cymbium / palpal bulb ("boxing gloves")
149
- const a = J[pj[5]], b = J[pj[6]];
150
- // (swollen but compact: about the width of the palp tibia plus a third)
151
- ellY({ ...g, bone: pb[5], tag: 'palpbulb', c: lerp(a, b, 0.5), ydir: sub(b, a), r: mm([0.65 * (0.62 * F * d.palpBulb + 0.3 * F), len(sub(b, a)) / M * 0.36, 0.65 * (0.7 * F * d.palpBulb + 0.3 * F)]), k: 0.2 * M * F });
152
- }
153
- }
154
-
155
- // ------------------------------------------------------------------ LEGS
156
- for (const S of ['L', 'R']) {
157
- for (let i = 1; i <= 4; i++) {
158
- const lj = legJoints(i, S), lb = legBones(i, S), key = S + i;
159
- const thick = i === 4 ? d.hindR : i === 3 ? (1 + d.hindR) / 2 : 1;
160
- for (let k = 0; k < 7; k++) {
161
- const [ra, rb] = d.legR[k];
162
- const a = J[lj[k]], b = J[lj[k + 1]];
163
- const parts = k <= 2 ? ['body', 'leg' + key] : ['leg' + key];
164
- for (const part of parts) {
165
- const g = { group: key, part, bone: lb[k] };
166
- if (k === 0) {
167
- // coxa: a stout cylinder set into the prosoma between carapace margin and sternum
168
- m.cone({ ...g, tag: 'coxa', a: add(a, mul(norm(sub(b, a)), -0.6 * M * F)), b, ra: R(ra * thick), rb: R(rb * thick), k: part === 'body' ? 0.55 * M * F : 0.1 * M * F });
169
- } else {
170
- m.cone({ ...g, tag: ['coxa', 'troch', 'femur', 'patella', 'tibia', 'meta', 'tarsus'][k], a, b, ra: R(ra * thick), rb: R(rb * thick), k: 0.07 * M * F });
171
- // swollen joint condyles: the knee (femur-patella) is the biggest
172
- if (k < 6) m.sphere({ ...g, tag: 'knuckle', c: add(b, mul(norm(sub(b, a)), -rb * 0.25 * M)), rad: R(rb * thick * (k === 2 ? 1.12 : 1.06)), k: 0.07 * M * F });
173
- }
174
- }
175
- }
176
- // claw tuft: the rounded tarsus tip
177
- const tip = J[lj[7]], ta = J[lj[6]];
178
- m.sphere({ group: key, part: 'leg' + key, bone: lb[6], tag: 'claws', c: add(tip, mul(norm(sub(ta, tip)), d.legR[6][1] * 0.3 * M)), rad: R(d.legR[6][1] * thick * 1.02), k: 0.06 * M * F });
179
- }
180
- }
181
- return m;
182
- }
@@ -1,160 +0,0 @@
1
- // Wolf body language, layered over the core actions every frame (species.motion.hooks.update, see
2
- // core/motion/actions.js).
3
- //
4
- // Tail carriage by mood (Schenkel 1947 in Mech & Boitani 2003): hangs at rest, ~level in the
5
- // travelling trot (the carriage table in motion.js), raised stiff above the back in a threat or an
6
- // attack, tucked between the hind legs when hit or afraid. Ears: pricked forward when alert (a look
7
- // target), pinned flat in an attack (core) and when howling. Hackles: the long guard hair of the
8
- // mane, cape and saddle lifts during an attack (P.furRaise -> the coat shader). Snarl: the jaw opens
9
- // on the crouch before the bite so the canines show. Howling: an idle variant every 25-60 s of
10
- // standing still (or on demand via `motion.input.howl = true`): head thrown back 50-60 deg, ears
11
- // back, jaw half open in an "O", lasting 3-6 s.
12
- import { clamp, smooth, lerp, angDiff } from '../../core/motion/common.js';
13
- import { mx, mxLegs } from '../../core/motion/actions.js';
14
- const sm = (w) => w * w * (3 - 2 * w);
15
-
16
- // moveTo: a wolf slows down to turn onto a point close beside or behind it. The engine caps the speed
17
- // only by the heading error (1.5 sk beyond 1.2 rad), so with the wolf's calm turn rate (1.8 rad/s) a
18
- // target inside its turning circle was circled without end. A point is reachable
19
- // on a turn of radius R only while it lies outside the turning circle on its side: R < d / (2 sin err)
20
- // (d distance, err bearing from the heading). The speed is capped so the radius at the engine's yaw
21
- // limit, v / w(v), keeps a margin inside that bound; near the point and well off the heading the wolf
22
- // all but pivots, then goes. (Engine-wide, the same cap belongs in quadruped.js drive().)
23
- const ARRIVE_MARGIN = 0.8;
24
- function arriveCap(e, st) {
25
- const inp = e.input, cfg = e.cfg;
26
- // arrived (drive() dropped the target and zeroed the speed): stand facing the way it went instead of
27
- // pivoting on to the last bearing of the point (a front paw dragged ~2 % S in that pivot)
28
- if (st.tgt && !inp.target && !inp.follow && !inp.speed && Math.hypot(st.tgt.x - e.pos.x, st.tgt.z - e.pos.z) < 0.5 * cfg.k + 0.03 * e.speed) {
29
- inp.heading = e.heading + 0.25 * e.yawRate;
30
- e.wantHeading = inp.heading;
31
- }
32
- st.tgt = inp.target && !inp.follow ? (st.tgt || { x: 0, z: 0 }) : null;
33
- if (!st.tgt) return;
34
- st.tgt.x = inp.target.x; st.tgt.z = inp.target.z;
35
- if (!(e.wantSpeed > 0.05) || e.air?.active) return;
36
- const dx = inp.target.x - e.pos.x, dz = inp.target.z - e.pos.z, d = Math.hypot(dx, dz);
37
- const err = Math.abs(angDiff(e.heading, Math.atan2(dx, dz))), sn = Math.sin(err);
38
- if (sn < 1e-3) return;
39
- const rMax = (ARRIVE_MARGIN * d) / (2 * sn);
40
- // the engine's yaw-rate limit at speed v (quadruped.js step: pivots are slower than turns on the move)
41
- const wAt = (v) => Math.min(cfg.turnRate * lerp(0.55, 1, smooth(0.3, 2, v / cfg.sq)), cfg.latAccelMax / Math.max(v, 0.5 * cfg.sk));
42
- if (e.wantSpeed / wAt(e.wantSpeed) <= rMax) return;
43
- // v / w(v) grows with v: bisect for the fastest speed whose turning radius fits
44
- let lo = 0, hi = e.wantSpeed;
45
- for (let i = 0; i < 12; i++) { const m = 0.5 * (lo + hi); if (m / wAt(m) <= rMax) lo = m; else hi = m; }
46
- // (a point ahead that the straight line passes within the stop radius needs no turn: the cap fades out)
47
- const stopR = 0.35 * cfg.k + 0.02 * e.speed;
48
- e.wantSpeed = lerp(e.wantSpeed, lo, err < 1.2 ? smooth(0.4 * stopR, 0.8 * stopR, d * sn) : 1);
49
- }
50
-
51
- export function wolfUpdate(P, dt, L) {
52
- const e = L.engine;
53
- const st = L._wolf || (L._wolf = { howlIn: 25 + e.rand() * 20, howlT: -1, howlDur: 4, howlW: 0 });
54
- arriveCap(e, st);
55
- // (the sleeping forepaw pull-back below overrides this animal's fold placement only while it sleeps)
56
- if (st.acts && st.acts.fold && !L.postures.some((p) => p.name === 'sleep')) st.acts.fold = undefined;
57
- let raise = 0;
58
-
59
- for (const a of L.oneshots) {
60
- const w = sm(a.w);
61
- if (w <= 0) continue;
62
- if (a.name === 'attack') {
63
- const t = a.t;
64
- // threat -> lunge: hackles up, tail raised stiff above the back, snarl before the bite
65
- raise = Math.max(raise, w * (0.5 + 0.5 * smooth(0, 0.2, t)));
66
- mx(P, 'tailLift', 0.75, w); mx(P, 'tailStiff', 1.8, w);
67
- const snarl = smooth(0.0, 0.12, t) * (1 - smooth(0.22, 0.3, t));
68
- P.jaw = Math.max(P.jaw, 0.3 * snarl * w); // (the lower fangs come clear of the upper lip)
69
- mx(P, 'headRaise', -0.035, snarl * w);
70
- } else if (a.name === 'hit') {
71
- // flinch: tail clamped between the hind legs, ears flat (core), body drops (core)
72
- const k = w * (1 - smooth(0.45, 0.75, a.t) * 0.6);
73
- mx(P, 'tailLift', -0.8, k); mx(P, 'tailStiff', 1.6, k); mx(P, 'tailIdle', 0, k);
74
- }
75
- }
76
- // dying / dead: ears folded back flat against the neck
77
- for (const p of L.postures) {
78
- if (p.name === 'death') { const w = sm(clamp(p.w, 0, 1)) * smooth(0.3, 1.0, p.t); mx(P, 'earFlat', 1.15, w); mx(P, 'earTwitch', 0, w); mx(P, 'headRoll', p.side * 0.8, w); P.headPos.y += 0.05 * e.cfg.s * w; }
79
- }
80
- // curled sleep (curled1: a ring on one hip, the nose tucked by the tail). The spine
81
- // bends into a C (2.2 rad, rolled 0.45 onto the hip, the hind legs to the inside); the head turns back
82
- // along the inside of the curl and rests on the ground by the hind feet (yaw 2.3 rad; the occiput 20 cm
83
- // inside and 5 cm ahead of the turned chest's shoulders, 10 cm up: further back, the throat's stretch
84
- // > 3x rose past 4 % of its triangles); the brush sweeps round the outside of the hind feet and forward
85
- // to the nose (tailSide 3.4 curves it progressively, tailCurl -0.5 holds the root back: the old 2.4 rad
86
- // turned it near the root and tucked it under the belly). The forelegs stay forward on the ground, as in
87
- // curled1: tucked (the core's tuck places them in the unbent body frame, ~26 cm off, and the elbow
88
- // flipped on the way out), reached (the paw stands up) or turned with the chest (the inner elbow dropped
89
- // into the ground: 7-23 mm) they failed the metrics. (roll 0.45: 0.65 pressed the lower forearm 9-14 mm
90
- // into the ground, 0.5 up to 6 mm)
91
- for (const p of L.postures) {
92
- if (p.name === 'sleep' && p.tune.style !== 'lateral') {
93
- const c = sm(clamp(p.w, 0, 1)) * smooth(1.2, 3.2, p.t), side = p.side, k = e.cfg.k, fr = e.fr;
94
- mx(P, 'roll', side * 0.45, c); mx(P, 'bend', side * 2.2, c);
95
- mxLegs(P, 'side', 0, 0.55, c); mxLegs(P, 'spread', 0, 0, c);
96
- // forelegs drawn back under the head (curled1: the paws just show at the front of the ring, not a leg's
97
- // length ahead of it like a sphinx's): the engine's fold places the forepaw at zS + actions.fold.front.z
98
- // leg lengths, flat on the ground; this animal's own copy of that tuning moves it 25 cm back once the
99
- // curl has settled, the forearm and paw kept flat and the elbows folding up beside the chest. (A 'reach'
100
- // blend stood the paw up and swung the elbow 10 mm into the ground; a 'sit' blend stood the forelegs up
101
- // like posts; the core's tuck places the paw in the unbent body frame, ~26 cm off.) Skin penetration
102
- // 0.30-0.62 % S (seeds 1-4, every morph, both sides).
103
- const cF = sm(clamp(p.w, 0, 1)) * smooth(2.6, 4.4, p.t);
104
- if (!st.acts) { st.acts = { ...e.cfg.actions }; e.cfg.actions = st.acts; }
105
- const L0 = e.legs[0].def, z0 = (0.5 * L0.Lr + L0.Lmc) / L0.len;
106
- // (k -1.45, beta 0 and z0 are the engine's own fold values: continuous as the pull-back fades)
107
- st.acts.fold = cF > 1e-3 ? { front: { z: z0 - (cF * 0.25 * k) / L0.len, k: -1.45, beta: 0 } } : undefined;
108
- mx(P, 'headYaw', side * 2.3, c);
109
- // the chest's flat forward and left (its frame is the last frame's: the posture changes slowly)
110
- const q = fr.qCh;
111
- let fx = 2 * (q.x * q.z + q.w * q.y), fz = 1 - 2 * (q.x * q.x + q.y * q.y);
112
- const fl = Math.hypot(fx, fz) || 1; fx /= fl; fz /= fl;
113
- const lat = side * 0.2 * k, fwd = 0.05 * k;
114
- const tx = fr.shC.x + fz * lat + fx * fwd, tz = fr.shC.z - fx * lat + fz * fwd;
115
- const hp = P.headPos;
116
- hp.x += (tx - hp.x) * c; hp.z += (tz - hp.z) * c; hp.y += (e.terrainH(tx, tz) + 0.1 * k - hp.y) * c;
117
- mx(P, 'tailCurl', side * -0.5, c); mx(P, 'tailSide', side * 3.4, c); mx(P, 'tailStiff', 0.7, c);
118
- }
119
- }
120
-
121
- // lying: rolled onto one hip, both hind legs to that side (lying1), not a symmetric sphinx
122
- for (const p of L.postures) {
123
- if (p.name === 'lie') {
124
- const w = sm(clamp(p.w, 0, 1)) * smooth(0.6, 1.8, p.t);
125
- mx(P, 'roll', p.side * 0.25, w);
126
- mxLegs(P, 'side', 0, 0.5, w);
127
- }
128
- }
129
-
130
- // alert: ears pricked forward while watching something
131
- const idleW = L.idle.w;
132
- if (e.input.look && raise < 0.01) mx(P, 'earFlat', -0.18, clamp(P.lookW, 0, 1));
133
-
134
- // howling (idle variant)
135
- const still = idleW > 0.95 && !L.postures.length && !L.oneshots.some((a) => !a.stopping && a.name !== 'hit');
136
- if (st.howlT < 0) {
137
- if (still) st.howlIn -= dt;
138
- if (e.input.howl && idleW > 0.3) { e.input.howl = false; st.howlIn = 0; }
139
- if (st.howlIn <= 0 && still) { st.howlT = 0; st.howlDur = 3 + e.rand() * 3; }
140
- } else {
141
- st.howlT += dt;
142
- if (!still && idleW < 0.6) st.howlT = Math.max(st.howlT, st.howlDur);
143
- if (st.howlT > st.howlDur + 1.2) { st.howlT = -1; st.howlIn = 25 + e.rand() * 35; }
144
- }
145
- const hw = st.howlT < 0 ? 0 : smooth(0, 0.9, st.howlT) * (1 - smooth(st.howlDur, st.howlDur + 1.2, st.howlT));
146
- st.howlW = hw;
147
- if (hw > 0.001) {
148
- const w = hw * idleW;
149
- mx(P, 'lookW', 0, w);
150
- mx(P, 'headRaise', 0.07, w); mx(P, 'neckReach', -0.03, w);
151
- mx(P, 'headPitch', -1.0, w);
152
- // the "O" opens after the head is up, with a slight waver
153
- const o = smooth(0.5, 1.2, st.howlT) * (1 - smooth(st.howlDur - 0.3, st.howlDur + 0.4, st.howlT));
154
- mx(P, 'jaw', 0.2 + 0.03 * Math.sin(st.howlT * 5.1), o * w); mx(P, 'jawOmega', 6, w);
155
- mx(P, 'earFlat', 0.55, w); mx(P, 'earTwitch', 0, w);
156
- mx(P, 'breathAmp', 0.4, w); mx(P, 'eyelid', 0.45, o * w);
157
- mx(P, 'dropH', 0.05, w);
158
- }
159
- P.furRaise = Math.max(P.furRaise || 0, raise);
160
- }