@bitefoundry/retrieviewer 0.0.2 → 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 (261) 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 +75 -0
  6. package/INSTALLING.md +8 -5
  7. package/PLUGIN.md +13 -10
  8. package/PREREQUISITES.md +95 -0
  9. package/PUPPY-MEMORY.md +102 -1
  10. package/README.ko.md +110 -0
  11. package/README.md +119 -58
  12. package/RELEASING.md +27 -14
  13. package/THIRD-PARTY-NOTICES.md +5 -3
  14. package/braille.mjs +35 -9
  15. package/examples/live.mjs +2 -2
  16. package/integrations/desktop/platform.mjs +27 -0
  17. package/integrations/linux-overlay/README.md +83 -0
  18. package/integrations/linux-overlay/overlay.py +1094 -0
  19. package/integrations/macos-overlay/README.md +83 -0
  20. package/integrations/macos-overlay/overlay.jxa +639 -0
  21. package/integrations/opencode/runtime.mjs +4 -4
  22. package/integrations/opencode/tui.tsx +1 -1
  23. package/integrations/windows-overlay/Overlay.cs +4 -4
  24. package/integrations/windows-overlay/desktop.mjs +40 -8
  25. package/integrations/windows-overlay/protocol.mjs +11 -7
  26. package/integrations/windows-overlay/worker.mjs +13 -7
  27. package/package.json +41 -14
  28. package/puppy-comfort-sprites.mjs +25 -0
  29. package/puppy-companion-comfort-q5.bin.gz +0 -0
  30. package/puppy-companion-comfort.json +77 -0
  31. package/puppy-companion-life.mjs +49 -16
  32. package/puppy-companion-objects.mjs +12 -0
  33. package/puppy-frame-predictive.mjs +15 -9
  34. package/puppy-frame-store.mjs +2 -2
  35. package/puppy-paper-world.mjs +14 -0
  36. package/puppy-paper.mjs +65 -14
  37. package/retrieviewer-cli.mjs +10 -3
  38. package/retrieviewer-plugin.d.mts +1 -1
  39. package/retrieviewer-plugin.mjs +1 -1
  40. package/retrieviewer.d.mts +10 -4
  41. package/retrieviewer.mjs +20 -14
  42. package/locomotion-core.mjs +0 -21
  43. package/locomotion-puppy.animal +0 -0
  44. package/vendor/procedural-animals/package.json +0 -40
  45. package/vendor/procedural-animals/src/animal.js +0 -146
  46. package/vendor/procedural-animals/src/bake.js +0 -51
  47. package/vendor/procedural-animals/src/build.js +0 -81
  48. package/vendor/procedural-animals/src/core/build/coatKit.js +0 -121
  49. package/vendor/procedural-animals/src/core/build/featherCards.js +0 -189
  50. package/vendor/procedural-animals/src/core/build/finEdges.js +0 -85
  51. package/vendor/procedural-animals/src/core/build/furSlope.js +0 -115
  52. package/vendor/procedural-animals/src/core/build/mesh.js +0 -67
  53. package/vendor/procedural-animals/src/core/build/pipeline.js +0 -272
  54. package/vendor/procedural-animals/src/core/build/seams.js +0 -183
  55. package/vendor/procedural-animals/src/core/build/warp.js +0 -112
  56. package/vendor/procedural-animals/src/core/build/weights.js +0 -393
  57. package/vendor/procedural-animals/src/core/math/vec.js +0 -81
  58. package/vendor/procedural-animals/src/core/motion/actions.js +0 -800
  59. package/vendor/procedural-animals/src/core/motion/bird.js +0 -3063
  60. package/vendor/procedural-animals/src/core/motion/birdActions.js +0 -1059
  61. package/vendor/procedural-animals/src/core/motion/common.js +0 -158
  62. package/vendor/procedural-animals/src/core/motion/index.js +0 -22
  63. package/vendor/procedural-animals/src/core/motion/quadruped.js +0 -2875
  64. package/vendor/procedural-animals/src/core/motion/snake.js +0 -1594
  65. package/vendor/procedural-animals/src/core/motion/spider.js +0 -1810
  66. package/vendor/procedural-animals/src/core/motion/swimmer.js +0 -1047
  67. package/vendor/procedural-animals/src/core/motion/swimmerActions.js +0 -613
  68. package/vendor/procedural-animals/src/core/render/animalObject.js +0 -262
  69. package/vendor/procedural-animals/src/core/render/coatMaterial.js +0 -1301
  70. package/vendor/procedural-animals/src/core/render/dqs.js +0 -159
  71. package/vendor/procedural-animals/src/core/render/eyes.js +0 -676
  72. package/vendor/procedural-animals/src/core/render/membranes.js +0 -77
  73. package/vendor/procedural-animals/src/core/render/skeleton.js +0 -41
  74. package/vendor/procedural-animals/src/core/rig/bird.js +0 -327
  75. package/vendor/procedural-animals/src/core/rig/quadruped.js +0 -76
  76. package/vendor/procedural-animals/src/core/rig/rig.js +0 -79
  77. package/vendor/procedural-animals/src/core/rig/snake.js +0 -76
  78. package/vendor/procedural-animals/src/core/rig/spider.js +0 -110
  79. package/vendor/procedural-animals/src/core/rig/swimmer.js +0 -181
  80. package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +0 -53
  81. package/vendor/procedural-animals/src/core/sdf/mesher.js +0 -238
  82. package/vendor/procedural-animals/src/core/sdf/sdf.js +0 -263
  83. package/vendor/procedural-animals/src/index.d.ts +0 -98
  84. package/vendor/procedural-animals/src/index.js +0 -29
  85. package/vendor/procedural-animals/src/registry.js +0 -48
  86. package/vendor/procedural-animals/src/species/bear/behaviour.js +0 -463
  87. package/vendor/procedural-animals/src/species/bear/claws.js +0 -147
  88. package/vendor/procedural-animals/src/species/bear/coat.js +0 -726
  89. package/vendor/procedural-animals/src/species/bear/index.js +0 -139
  90. package/vendor/procedural-animals/src/species/bear/motion.js +0 -112
  91. package/vendor/procedural-animals/src/species/bear/regions.js +0 -78
  92. package/vendor/procedural-animals/src/species/bear/rig.js +0 -112
  93. package/vendor/procedural-animals/src/species/bear/sculpt.js +0 -272
  94. package/vendor/procedural-animals/src/species/boar/behaviour.js +0 -335
  95. package/vendor/procedural-animals/src/species/boar/coat.js +0 -372
  96. package/vendor/procedural-animals/src/species/boar/index.js +0 -110
  97. package/vendor/procedural-animals/src/species/boar/motion.js +0 -85
  98. package/vendor/procedural-animals/src/species/boar/regions.js +0 -88
  99. package/vendor/procedural-animals/src/species/boar/rig.js +0 -111
  100. package/vendor/procedural-animals/src/species/boar/sculpt.js +0 -285
  101. package/vendor/procedural-animals/src/species/cat/behaviour.js +0 -559
  102. package/vendor/procedural-animals/src/species/cat/coat.js +0 -841
  103. package/vendor/procedural-animals/src/species/cat/index.js +0 -211
  104. package/vendor/procedural-animals/src/species/cat/motion.js +0 -101
  105. package/vendor/procedural-animals/src/species/cat/regions.js +0 -82
  106. package/vendor/procedural-animals/src/species/cat/rig.js +0 -100
  107. package/vendor/procedural-animals/src/species/cat/sculpt.js +0 -266
  108. package/vendor/procedural-animals/src/species/cat/whiskers.js +0 -110
  109. package/vendor/procedural-animals/src/species/cheetah/coat.js +0 -427
  110. package/vendor/procedural-animals/src/species/cheetah/index.js +0 -51
  111. package/vendor/procedural-animals/src/species/cheetah/joints.js +0 -3
  112. package/vendor/procedural-animals/src/species/cheetah/motion.js +0 -77
  113. package/vendor/procedural-animals/src/species/cheetah/regions.js +0 -95
  114. package/vendor/procedural-animals/src/species/cheetah/rig.js +0 -66
  115. package/vendor/procedural-animals/src/species/cheetah/sculpt.js +0 -158
  116. package/vendor/procedural-animals/src/species/chicken/coat.js +0 -313
  117. package/vendor/procedural-animals/src/species/chicken/coverts.js +0 -320
  118. package/vendor/procedural-animals/src/species/chicken/index.js +0 -110
  119. package/vendor/procedural-animals/src/species/chicken/motion.js +0 -177
  120. package/vendor/procedural-animals/src/species/chicken/regions.js +0 -66
  121. package/vendor/procedural-animals/src/species/chicken/rig.js +0 -144
  122. package/vendor/procedural-animals/src/species/chicken/sculpt.js +0 -389
  123. package/vendor/procedural-animals/src/species/chicken/wingLook.js +0 -66
  124. package/vendor/procedural-animals/src/species/chicken/wingStack.js +0 -124
  125. package/vendor/procedural-animals/src/species/cow/behaviour.js +0 -521
  126. package/vendor/procedural-animals/src/species/cow/coat.js +0 -465
  127. package/vendor/procedural-animals/src/species/cow/index.js +0 -118
  128. package/vendor/procedural-animals/src/species/cow/motion.js +0 -81
  129. package/vendor/procedural-animals/src/species/cow/regions.js +0 -98
  130. package/vendor/procedural-animals/src/species/cow/rig.js +0 -116
  131. package/vendor/procedural-animals/src/species/cow/sculpt.js +0 -339
  132. package/vendor/procedural-animals/src/species/crow/coat.js +0 -145
  133. package/vendor/procedural-animals/src/species/crow/index.js +0 -70
  134. package/vendor/procedural-animals/src/species/crow/joints.js +0 -3
  135. package/vendor/procedural-animals/src/species/crow/motion.js +0 -101
  136. package/vendor/procedural-animals/src/species/crow/regions.js +0 -50
  137. package/vendor/procedural-animals/src/species/crow/rig.js +0 -83
  138. package/vendor/procedural-animals/src/species/crow/sculpt.js +0 -118
  139. package/vendor/procedural-animals/src/species/deer/behaviour.js +0 -513
  140. package/vendor/procedural-animals/src/species/deer/coat.js +0 -391
  141. package/vendor/procedural-animals/src/species/deer/index.js +0 -106
  142. package/vendor/procedural-animals/src/species/deer/motion.js +0 -97
  143. package/vendor/procedural-animals/src/species/deer/regions.js +0 -60
  144. package/vendor/procedural-animals/src/species/deer/rig.js +0 -124
  145. package/vendor/procedural-animals/src/species/deer/sculpt.js +0 -297
  146. package/vendor/procedural-animals/src/species/dog/behaviour.js +0 -521
  147. package/vendor/procedural-animals/src/species/dog/coat.js +0 -495
  148. package/vendor/procedural-animals/src/species/dog/index.js +0 -144
  149. package/vendor/procedural-animals/src/species/dog/motion.js +0 -118
  150. package/vendor/procedural-animals/src/species/dog/regions.js +0 -61
  151. package/vendor/procedural-animals/src/species/dog/rig.js +0 -129
  152. package/vendor/procedural-animals/src/species/dog/sculpt.js +0 -246
  153. package/vendor/procedural-animals/src/species/eagle/coat.js +0 -250
  154. package/vendor/procedural-animals/src/species/eagle/index.js +0 -76
  155. package/vendor/procedural-animals/src/species/eagle/joints.js +0 -3
  156. package/vendor/procedural-animals/src/species/eagle/motion.js +0 -137
  157. package/vendor/procedural-animals/src/species/eagle/regions.js +0 -57
  158. package/vendor/procedural-animals/src/species/eagle/rig.js +0 -107
  159. package/vendor/procedural-animals/src/species/eagle/sculpt.js +0 -137
  160. package/vendor/procedural-animals/src/species/fish/coat.js +0 -271
  161. package/vendor/procedural-animals/src/species/fish/index.js +0 -88
  162. package/vendor/procedural-animals/src/species/fish/motion.js +0 -92
  163. package/vendor/procedural-animals/src/species/fish/regions.js +0 -27
  164. package/vendor/procedural-animals/src/species/fish/rig.js +0 -143
  165. package/vendor/procedural-animals/src/species/fish/sculpt.js +0 -214
  166. package/vendor/procedural-animals/src/species/fish/variants.js +0 -126
  167. package/vendor/procedural-animals/src/species/fox/behaviour.js +0 -314
  168. package/vendor/procedural-animals/src/species/fox/coat.js +0 -444
  169. package/vendor/procedural-animals/src/species/fox/index.js +0 -120
  170. package/vendor/procedural-animals/src/species/fox/motion.js +0 -81
  171. package/vendor/procedural-animals/src/species/fox/regions.js +0 -59
  172. package/vendor/procedural-animals/src/species/fox/rig.js +0 -91
  173. package/vendor/procedural-animals/src/species/fox/sculpt.js +0 -202
  174. package/vendor/procedural-animals/src/species/frog/behaviour.js +0 -590
  175. package/vendor/procedural-animals/src/species/frog/coat.js +0 -305
  176. package/vendor/procedural-animals/src/species/frog/index.js +0 -97
  177. package/vendor/procedural-animals/src/species/frog/motion.js +0 -69
  178. package/vendor/procedural-animals/src/species/frog/regions.js +0 -46
  179. package/vendor/procedural-animals/src/species/frog/rig.js +0 -156
  180. package/vendor/procedural-animals/src/species/frog/sculpt.js +0 -240
  181. package/vendor/procedural-animals/src/species/goat/behaviour.js +0 -509
  182. package/vendor/procedural-animals/src/species/goat/coat.js +0 -590
  183. package/vendor/procedural-animals/src/species/goat/index.js +0 -149
  184. package/vendor/procedural-animals/src/species/goat/motion.js +0 -95
  185. package/vendor/procedural-animals/src/species/goat/regions.js +0 -98
  186. package/vendor/procedural-animals/src/species/goat/rig.js +0 -181
  187. package/vendor/procedural-animals/src/species/goat/sculpt.js +0 -547
  188. package/vendor/procedural-animals/src/species/horse/coat.js +0 -361
  189. package/vendor/procedural-animals/src/species/horse/coatSeam.js +0 -122
  190. package/vendor/procedural-animals/src/species/horse/index.js +0 -80
  191. package/vendor/procedural-animals/src/species/horse/motion.js +0 -245
  192. package/vendor/procedural-animals/src/species/horse/regions.js +0 -60
  193. package/vendor/procedural-animals/src/species/horse/rig.js +0 -117
  194. package/vendor/procedural-animals/src/species/horse/sculpt.js +0 -316
  195. package/vendor/procedural-animals/src/species/horse/seamWeights.js +0 -272
  196. package/vendor/procedural-animals/src/species/lion/behaviour.js +0 -509
  197. package/vendor/procedural-animals/src/species/lion/coat.js +0 -1016
  198. package/vendor/procedural-animals/src/species/lion/index.js +0 -111
  199. package/vendor/procedural-animals/src/species/lion/motion.js +0 -87
  200. package/vendor/procedural-animals/src/species/lion/regions.js +0 -106
  201. package/vendor/procedural-animals/src/species/lion/rig.js +0 -110
  202. package/vendor/procedural-animals/src/species/lion/sculpt.js +0 -384
  203. package/vendor/procedural-animals/src/species/lion/whiskers.js +0 -132
  204. package/vendor/procedural-animals/src/species/pig/behaviour.js +0 -575
  205. package/vendor/procedural-animals/src/species/pig/coat.js +0 -730
  206. package/vendor/procedural-animals/src/species/pig/ears.js +0 -242
  207. package/vendor/procedural-animals/src/species/pig/index.js +0 -161
  208. package/vendor/procedural-animals/src/species/pig/motion.js +0 -105
  209. package/vendor/procedural-animals/src/species/pig/regions.js +0 -100
  210. package/vendor/procedural-animals/src/species/pig/rig.js +0 -152
  211. package/vendor/procedural-animals/src/species/pig/sculpt.js +0 -382
  212. package/vendor/procedural-animals/src/species/rabbit/behaviour.js +0 -605
  213. package/vendor/procedural-animals/src/species/rabbit/coat.js +0 -285
  214. package/vendor/procedural-animals/src/species/rabbit/index.js +0 -85
  215. package/vendor/procedural-animals/src/species/rabbit/motion.js +0 -85
  216. package/vendor/procedural-animals/src/species/rabbit/regions.js +0 -48
  217. package/vendor/procedural-animals/src/species/rabbit/rig.js +0 -99
  218. package/vendor/procedural-animals/src/species/rabbit/sculpt.js +0 -148
  219. package/vendor/procedural-animals/src/species/rat/behaviour.js +0 -539
  220. package/vendor/procedural-animals/src/species/rat/coat.js +0 -341
  221. package/vendor/procedural-animals/src/species/rat/index.js +0 -111
  222. package/vendor/procedural-animals/src/species/rat/motion.js +0 -90
  223. package/vendor/procedural-animals/src/species/rat/regions.js +0 -92
  224. package/vendor/procedural-animals/src/species/rat/rig.js +0 -112
  225. package/vendor/procedural-animals/src/species/rat/sculpt.js +0 -163
  226. package/vendor/procedural-animals/src/species/rat/whiskers.js +0 -119
  227. package/vendor/procedural-animals/src/species/shark/coat.js +0 -383
  228. package/vendor/procedural-animals/src/species/shark/index.js +0 -104
  229. package/vendor/procedural-animals/src/species/shark/motion.js +0 -69
  230. package/vendor/procedural-animals/src/species/shark/regions.js +0 -34
  231. package/vendor/procedural-animals/src/species/shark/rig.js +0 -194
  232. package/vendor/procedural-animals/src/species/shark/sculpt.js +0 -343
  233. package/vendor/procedural-animals/src/species/shark/variants.js +0 -105
  234. package/vendor/procedural-animals/src/species/sheep/behaviour.js +0 -522
  235. package/vendor/procedural-animals/src/species/sheep/coat.js +0 -529
  236. package/vendor/procedural-animals/src/species/sheep/index.js +0 -152
  237. package/vendor/procedural-animals/src/species/sheep/motion.js +0 -86
  238. package/vendor/procedural-animals/src/species/sheep/neck.js +0 -41
  239. package/vendor/procedural-animals/src/species/sheep/regions.js +0 -62
  240. package/vendor/procedural-animals/src/species/sheep/rig.js +0 -163
  241. package/vendor/procedural-animals/src/species/sheep/sculpt.js +0 -542
  242. package/vendor/procedural-animals/src/species/snake/coat.js +0 -315
  243. package/vendor/procedural-animals/src/species/snake/index.js +0 -73
  244. package/vendor/procedural-animals/src/species/snake/motion.js +0 -51
  245. package/vendor/procedural-animals/src/species/snake/regions.js +0 -51
  246. package/vendor/procedural-animals/src/species/snake/rig.js +0 -108
  247. package/vendor/procedural-animals/src/species/snake/sculpt.js +0 -122
  248. package/vendor/procedural-animals/src/species/spider/coat.js +0 -279
  249. package/vendor/procedural-animals/src/species/spider/index.js +0 -78
  250. package/vendor/procedural-animals/src/species/spider/motion.js +0 -72
  251. package/vendor/procedural-animals/src/species/spider/regions.js +0 -87
  252. package/vendor/procedural-animals/src/species/spider/rig.js +0 -118
  253. package/vendor/procedural-animals/src/species/spider/sculpt.js +0 -182
  254. package/vendor/procedural-animals/src/species/wolf/behaviour.js +0 -160
  255. package/vendor/procedural-animals/src/species/wolf/coat.js +0 -749
  256. package/vendor/procedural-animals/src/species/wolf/index.js +0 -107
  257. package/vendor/procedural-animals/src/species/wolf/motion.js +0 -80
  258. package/vendor/procedural-animals/src/species/wolf/regions.js +0 -57
  259. package/vendor/procedural-animals/src/species/wolf/rig.js +0 -87
  260. package/vendor/procedural-animals/src/species/wolf/sculpt.js +0 -339
  261. package/vendor/procedural-animals/src/worker.js +0 -29
@@ -1,149 +0,0 @@
1
- // Domestic goat (Capra hircus). Cloven-hoofed browser: the horse's hoof rig (pastern + hoof bone)
2
- // with two claws per foot, scimitar horns (a rigid keratin surface on the skull), beard and wattles,
3
- // horizontal bar pupils in pale amber irises, the short tail carried up, cud chewing, browsing on the
4
- // hind legs and the rearing head clash.
5
- import { goatRig, goatJoints, HEAD_O } from './rig.js';
6
- import { add, sub, mul } from '../../core/math/vec.js';
7
- import { sculptGoat, EYE } from './sculpt.js';
8
- import { goatRegions } from './regions.js';
9
- import { goatCoat } from './coat.js';
10
- import { srgb } from '../../core/build/coatKit.js';
11
- import { rng } from '../../core/math/vec.js';
12
- import { motion } from './motion.js';
13
- import { QUALITY } from '../../core/build/pipeline.js';
14
-
15
- // a kid's short neck: the head and the upper neck move down the neck by 20 % of its length (12 % for lop ears: further,
16
- // the hanging ear's tip ran into the throat), shortening the neck above its lowest 15 % (from the neck base the shift
17
- // reached the scapulae, and the Nubian kid's sprint jittered at the wrist, p99 0.084 % S)
18
- const J0 = goatJoints();
19
- const NECK_BASE = add(J0.neckBase, mul(sub(J0.occiput, J0.neckBase), 0.15));
20
- const kidNeck = (lop) => mul(sub(J0.occiput, J0.neckBase), lop ? -0.12 : -0.2);
21
-
22
- const pick = (R, table) => {
23
- let x = R() * table.reduce((s, [, w]) => s + w, 0);
24
- for (const [k, w] of table) { x -= w; if (x <= 0) return k; }
25
- return table[table.length - 1][0];
26
- };
27
-
28
- // Breeds (variants) and their coats (coat.js COATS). salt: the breed's own seed stream, so a seed gives
29
- // a different animal in every breed (with one stream, seed N was the same individual in five coats and
30
- // seeds 1-2 were kids in every breed); picked so that seed 1 is a horned adult doe (the reference
31
- // individual, the tools' default) and seeds 2-4 hold a horned buck, a kid and a doe
32
- const BREEDS = {
33
- saanen: { salt: 158, coats: [['saanen', 1]], polled: 0.4, ear: 'erect', roman: 0, legs: 1, girth: 1, horn: 0xb4a07c },
34
- alpine: { salt: 746, coats: [['chamoisee', 40], ['coublanc', 25], ['toggenburg', 20], ['britishalpine', 15]], polled: 0.35, ear: 'erect', roman: 0, legs: 1.0, girth: 0.98, horn: 0x8a7050 },
35
- pied: { salt: 208, coats: [['pied', 60], ['piedbrown', 40]], polled: 0.3, ear: 'erect', roman: 0.15, legs: 0.98, girth: 1.02, horn: 0x9e8058 },
36
- nubian: { salt: 398, coats: [['nubianred', 40], ['nubiantan', 35], ['nubianblack', 25]], polled: 0.5, ear: 'lop', roman: 1, legs: 1.06, girth: 0.97, horn: 0x7a6248 },
37
- boer: { salt: 165, coats: [['boer', 1]], polled: 0.05, ear: 'lop', roman: 0.7, legs: 0.9, girth: 1.1, horn: 0x5e4c3a },
38
- };
39
-
40
- export default {
41
- id: 'goat',
42
- name: 'Goat',
43
- latin: 'Capra hircus',
44
- group: 'hooves',
45
- plan: 'quadruped',
46
- covering: 'fur',
47
- variants: Object.keys(BREEDS),
48
-
49
- // Seeded individual. Breed (o.variant: saanen, alpine, pied, nubian, boer) sets coat colours, ears,
50
- // Roman nose and build; sex: doe (udder) or buck (heavier, broader, a mane and "pants", big horns,
51
- // long beard); age: adult or kid (juvenile: long legs, short body, big head, horn buds, fluffy
52
- // coat). Horns (scimitar, larger in bucks) or polled; beard (bucks, many does); wattles (some).
53
- variation(R0, o) {
54
- // (a re-mixed stream: the early draws of neighbouring seeds were correlated, e.g. 16 of seeds 1-20
55
- // came out polled)
56
- const salt = BREEDS[o.variant] ? BREEDS[o.variant].salt : 0;
57
- const R = rng(Math.floor(R0() * 4294967296) ^ Math.imul(o.seed ?? 1, 0x9e3779b1) ^ 0x2545f491 ^ Math.imul(salt, 0x85ebca6b));
58
- const variant = BREEDS[o.variant] ? o.variant : pick(R, [['saanen', 30], ['alpine', 30], ['pied', 20], ['nubian', 15], ['boer', 5]]);
59
- const Bd = BREEDS[variant];
60
- const sex = o.sex || (R() < 0.45 ? 'male' : 'female');
61
- const age = o.age || (R() < 0.15 ? 'juvenile' : 'adult');
62
- const kid = age === 'juvenile';
63
- const buck = sex === 'male' && !kid;
64
- const g = () => (R() + R() + R() - 1.5) / 1.5; // ~[-1, 1], peaked
65
- const coat = pick(R, Bd.coats);
66
- const polled = R() < Bd.polled;
67
- let horns = null;
68
- if (!polled) {
69
- if (kid) horns = { len: 0.02 + 0.01 * R(), base: 0.008, curve: 0.2, spread: 0.12, upright: 0.3 };
70
- else if (buck) horns = { len: 0.3 + 0.18 * R(), base: 0.024 + 0.006 * R(), curve: 1.6 + 0.5 * R(), spread: 0.18 + 0.16 * R(), upright: 0.1 * R() };
71
- else horns = { len: 0.14 + 0.1 * R(), base: 0.0125 + 0.0035 * R(), curve: 0.9 + 0.45 * R(), spread: 0.08 + 0.1 * R(), upright: 0.2 * R() };
72
- }
73
- const beardP = variant === 'nubian' || variant === 'boer' ? 0.3 : 0.65;
74
- const beard = kid ? 0 : buck ? 0.12 + 0.1 * R() : R() < beardP ? 0.05 + 0.07 * R() : 0;
75
- const size = (buck ? 1.12 : 1) * (1 + 0.045 * g()) * (variant === 'nubian' ? 1.04 : 1) * (kid ? 0.58 : 1);
76
- return {
77
- sex, age, size, variant, coat,
78
- horns, beard,
79
- wattles: R() < 0.3,
80
- earLift: R(),
81
- ear: Bd.ear,
82
- // (a kid's face is straight: the Roman arch grows in with age, and on a kid's short face it swelled)
83
- roman: Bd.roman * (0.75 + 0.25 * R()) * (kid ? 0.35 : 1),
84
- udder: sex === 'female' && !kid ? 0.2 + 0.8 * R() : 0,
85
- heavy: buck ? 0.7 + 0.3 * R() : 0,
86
- mane: buck ? 0.4 + 0.6 * R() : 0,
87
- // (the long-haired landrace roll only: every buck had a 0.25 share of its skirt, which made every buck's barrel
88
- // a sheep's fleece; a dairy buck's body coat is as short and sleek as a doe's)
89
- shaggy: (variant === 'alpine' && R() < 0.25 ? 0.4 : 0),
90
- hornColor: Bd.horn,
91
- coatShade: g(), coatLightness: 0.05 * g(),
92
- coatSeed: Math.floor(R() * 1e6),
93
- // (the quality tier's mesh scale: the horns' cells, their least thickness and their sculpted growth ridges follow it)
94
- tierRes: (QUALITY[o.quality] || QUALITY.high).res,
95
- minThick: 0.005, // (thin parts at the coarse tiers: at 8 mm the erect ear's floor under its cup showed pinholes at medium)
96
- warps: [
97
- // a kid's neck is short (kid_side, front2: the head carried forward at about the height of the withers; with
98
- // the adult's neck its upright neck and high head read as a llama)
99
- ...(kid ? [{ type: 'shift', a: NECK_BASE, b: J0.occiput, d: kidNeck(Bd.ear === 'lop') }] : []),
100
- // (the head scale next: its centre is the head origin, where the shift has moved it)
101
- { type: 'scaleAbout', c: kid ? add(HEAD_O, kidNeck(Bd.ear === 'lop')) : HEAD_O, k: (1 + 0.035 * g()) * (kid ? 1.18 : 1) * (buck ? 1.06 : 1), r0: 0.1, r1: 0.2 },
102
- { type: 'legs', k: (1 + 0.035 * g()) * Bd.legs * (kid ? 1.18 : 1), top: 0.46 },
103
- { type: 'length', k: (1 + 0.035 * g()) * (kid ? 0.84 : 1), z0: -0.32, z1: 0.32 },
104
- { type: 'girth', k: (1 + 0.04 * g()) * Bd.girth * (buck ? 1.06 : 1) * (kid ? 0.92 : 1), cy: 0.56, z0: -0.4, z1: 0.38 },
105
- ],
106
- };
107
- },
108
- rig: (params) => goatRig(params),
109
- sculpt: (m, rig, params) => sculptGoat(m, rig, params),
110
- regions: goatRegions,
111
- coat: goatCoat,
112
- eyeSpecs: (params) => [1, -1].map((side) => ({ side, spec: EYE, headOrigin: HEAD_O, bone: 'head', look: eyeLook(params) })),
113
- motion,
114
- // (marks are the lash lines: soft brown-grey on pink-skinned white coats, dark otherwise)
115
- // (clumpDensity is the density of the tufts, not the clumping strength: lower means bigger tufts. At 0.6
116
- // the 9-11 mm coat broke into 6-14 mm tufts that read as astrakhan curls, and a buck's back at 0.45 as a
117
- // pebbled rug; side2 / side3 / walk1 show a sleek coat of fine lengthwise hair. finWidth 0.4 gave the
118
- // outline a regular zipper hem at hero)
119
- // (a buck's sleek body takes the does' fine tufts, 1.5: his long mane clumps through its length anyway; 1.1 on every
120
- // buck read as a fleece)
121
- render: (params) => ({ markColor: srgb(pinkSkinned(params) ? 0x4a3934 : 0x241f1d), strandDensity: 1400, clumpDensity: longHair(params) ? 1.1 : params.sex === 'male' && params.age !== 'juvenile' ? 1.5 : 1.6, shellScale: 0.9, finWidth: 0.3, matBorders: true }),
122
- };
123
-
124
- // The goat's signature eye: a strongly elongated horizontal bar pupil in a pale golden / amber iris
125
- //, sclera hidden, dark lids. Some lines have blue-grey irises.
126
- // (mid / hi lightened ~15 %: under the cornea they rendered darker than their hex, a dark bead)
127
- const IRISES = [
128
- { inner: 0xb88f30, mid: 0xdcb24a, hi: 0xf0d284, outer: 0x6a4a18 }, // golden
129
- { inner: 0xa87f3c, mid: 0xe8d28a, hi: 0xf6e8b0, outer: 0x7a6030 }, // pale yellow
130
- { inner: 0x74501e, mid: 0xb08238, hi: 0xd49e52, outer: 0x3e2810 }, // brown-amber
131
- { inner: 0x5e7280, mid: 0xa2bccb, hi: 0xc8dae2, outer: 0x3a4650 }, // blue
132
- ];
133
- // shaggy (long-haired landrace) goats: long coarse hair lies in bigger locks (small tight tufts read as a lamb's wool)
134
- const longHair = (params) => (params.shaggy || 0) > 0.3;
135
- // white-coated goats (and the white areas of pied / Boer coats) have pink skin: nose, lips, lids
136
- const pinkSkinned = (params) => ['saanen', 'pied', 'piedbrown'].includes(params.coat);
137
- function eyeLook(params) {
138
- const s = ((params.coatSeed || 0) % 100) / 100;
139
- const ir = IRISES[s < 0.45 ? 0 : s < 0.75 ? 1 : s < 0.96 ? 2 : 3];
140
- return {
141
- pupil: 'bar',
142
- lids: 'mammal',
143
- iris: { inner: srgb(ir.inner), mid: srgb(ir.mid), hi: srgb(ir.hi), outer: srgb(ir.outer) },
144
- sclera: { color: [0.55, 0.5, 0.45], visible: false },
145
- // (pink-grey lids on white goats: side2, face3; dark on the others)
146
- lidColor: pinkSkinned(params) ? srgb(0x8a6a62) : [0.03, 0.025, 0.022],
147
- pupilSize: [0.09, 0.32],
148
- };
149
- }
@@ -1,95 +0,0 @@
1
- // Goat motion data for the quadruped engine (schema: src/core/motion/quadruped.js).
2
- // Numbers are for the reference individual (params.size = 1, a 0.78 m Saanen doe); the engine
3
- // scales them by dynamic similarity for kids, pygmies and big bucks.
4
- //
5
- // Gaits: lateral-sequence 4-beat walk (duty 0.72 -> 0.62), 2-beat
6
- // diagonal trot (hind lands ~2 % before its diagonal fore, duty 0.45 -> 0.36) and the transverse
7
- // gallop (LH, RH, LF, RF). Crossovers sit at the predicted transitions: walk -> trot at Froude
8
- // ~0.45 (1.85 m/s for a 0.78 m goat), trot -> gallop 4.2 m/s at ~2.5 Hz (Heglund et al. 1974:
9
- // v = 1.535 M^0.24, f = 4.48 M^-0.14 for 65 kg).
10
- import { hooks } from './behaviour.js';
11
-
12
- const G = (name, v, f, D, off, o) => ({ name, v, f, D, off, ...o });
13
-
14
- export const motion = {
15
- maxSpeed: 8.5,
16
- accel: [3.5, 7],
17
- decel: 7,
18
- turnRate: 1.7, // agile: pivots on the hind legs
19
- latAccelMax: 4.5,
20
- gears: { walk: 1.0, trot: 2.7, gallop: 5.6 },
21
- gallopBlend: [3.8, 6.5],
22
- // name v f D [FL, FR, HL, HR]
23
- gaits: [
24
- G('walk', 0.0, 0.85, 0.72, [0.25, 0.75, 0.0, 0.5], { liftF: 0.045, liftH: 0.04, bobF: 0.012, bobH: 0.012, flex: 0, lat: 0.02, fold: 0.7, heel: 30, tail: 0, drop: 0 }),
25
- G('walk', 1.5, 1.35, 0.62, [0.25, 0.75, 0.0, 0.5], { liftF: 0.055, liftH: 0.048, bobF: 0.025, bobH: 0.025, flex: 0, lat: 0.025, fold: 0.85, heel: 40, tail: 0.1, drop: 0 }),
26
- G('trot', 2.2, 2.05, 0.45, [0.52, 0.02, 0.0, 0.5], { liftF: 0.08, liftH: 0.065, bobF: 0.028, bobH: 0.028, flex: 0.01, lat: 0.0, fold: 1.05, heel: 50, tail: 0.3, drop: 0.006 }),
27
- G('trot', 3.4, 2.4, 0.37, [0.52, 0.02, 0.0, 0.5], { liftF: 0.095, liftH: 0.08, bobF: 0.032, bobH: 0.032, flex: 0.015, lat: 0.0, fold: 1.15, heel: 55, tail: 0.4, drop: 0.01 }),
28
- G('gallop', 4.8, 2.7, 0.3, [0.55, 0.65, 0.0, 0.1], { liftF: 0.11, liftH: 0.1, bobF: 0.022, bobH: 0.03, flex: 0.1, lat: 0, fold: 1.15, heel: 45, tail: 0.7, drop: 0.02 }),
29
- G('gallop', 8.5, 3.0, 0.23, [0.56, 0.66, 0.0, 0.1], { liftF: 0.13, liftH: 0.12, bobF: 0.024, bobH: 0.034, flex: 0.14, lat: 0, fold: 1.4, heel: 40, tail: 1.0, drop: 0.035 }),
30
- ],
31
- feet: {
32
- // cloven hooves: the fetlock sinks a little under load, the digit flips in swing, breakover
33
- // about the claw tips; pointed hard claws plant precisely (contact near the toe)
34
- front: { type: 'unguligrade', contact: 0.9, curl: 70, flex: 4, sink: 14, hoofFlex: 20, swingBack: 0.07 },
35
- hind: { type: 'unguligrade', contact: 0.9, curl: 70, flex: 4, sink: 12, hoofFlex: 20, swingBack: 0.02 },
36
- },
37
- stance: { width: 1, gallopWidth: 0.8, sprawl: 0, crouch: 0, scuff: [10, 20, 0] },
38
- // torso cross-sections (bind pose, reference size): centre height, half height, half width
39
- // (half heights include the legs folded under the chest and thighs when lying down)
40
- body: {
41
- // (0.28 with the pelvis's 0.36: the body lies level on its folded legs; the chest at 0.25 under the higher rump
42
- // pitched forward onto the folded forelegs, a Boer buck's forearm 5 cm in the ground asleep)
43
- chest: { y: 0.56, hh: 0.28, hw: 0.15 },
44
- mid: { y: 0.55, hh: 0.23, hw: 0.17 },
45
- // (the hindquarters rest on the folded hind legs: lying at 0.3 the stifles folded in against the belly and the skin
46
- // between the thigh and the flank crumpled into a pocket in front of the stifle, a light torn knob from the side)
47
- pelvis: { y: 0.63, hh: 0.36, hw: 0.16 },
48
- back: 0.06,
49
- },
50
- head: {
51
- // [speed, raise (m), reach (m), pitch (rad, + = nose down)]: head high and alert at rest, a
52
- // little lower and forward at the walk, stretched forward in the gallop
53
- carriage: [[0, 0.03, -0.015, -0.05], [1.0, 0.0, 0.01, 0.02], [2.7, -0.01, 0.03, 0.02], [5, -0.06, 0.06, 0.1], [8, -0.1, 0.09, 0.14]],
54
- stab: [[0, 0], [1.0, 0.15], [2.7, 0.45], [5, 0.35], [8, 0.4]],
55
- neckBend: 34, neckPivot: 0.55, yaw: 0.9, pitchUp: 0.7, pitchDown: 0.9, mouth: 'jawTip',
56
- },
57
- tail: {
58
- // [speed, pitch per segment from horizontal (deg), base -> tip]: carried up, higher when running
59
- carriage: [
60
- [0.0, [28, 42, 55, 62, 66]],
61
- [1.5, [30, 45, 58, 64, 68]],
62
- [3.5, [36, 52, 64, 70, 72]],
63
- [7, [42, 58, 70, 74, 76]],
64
- ],
65
- stiffness: 1.2, sway: 4, flick: 1, wag: 0, swish: 0, curl: 0, balance: 0,
66
- radius: [0.03, 0.02],
67
- },
68
- ears: { rest: [0, 0], mobility: 1.3, speedFlatten: 0.3, twitch: 1.6, prick: 0.5 },
69
- breath: { rate: 0.32, amp: 0.006, pant: false, pantRate: 2, pantAmp: 0.015, heatSpeed: 6 },
70
- actions: {
71
- // grazing: the long face already hangs 60 deg nose-down in the bind pose
72
- // (the face nearly vertical, 77 deg nose-down: at 1.1 rad the head was cocked back against the lowered neck, the
73
- // poll extended 120 deg from its standing angle and the nape's skin folded to 0.65 of its length, its hair standing
74
- // apart in a frayed band; the throat stretched more too: > 3x 1.37 -> 0.98 % of the kid's mesh in eat and drink)
75
- eat: { style: 'graze', dropF: 0.1, dropH: 0, pitch: 1.35, ahead: 0.5 },
76
- drink: { dropF: 0.1, dropH: 0, pitch: 1.3, ahead: 0.5 },
77
- // sure-footed: a high standing jump, landing on four feet close together (opts.target lands
78
- // exactly there)
79
- jump: { height: 0.75, distance: 1.3, land: [0.16, 0.14] },
80
- sit: { dropH: 0.8 },
81
- // kneels on the carpi first, then drops the hindquarters; rises hind end first
82
- lie: { down: 'front', up: 'hind' },
83
- sleep: { down: 'front', up: 'hind' },
84
- // lying sternal: forelegs folded under the chest (carpus flexed, cannons back along the ground)
85
- fold: { front: { z: -0.2, k: 1.45, beta: 0.9 } },
86
- },
87
- hooks,
88
- // the long lop ears of Nubians and Boers hang and swing with the head; they barely prick or twist
89
- // (the engine swivels a pinna about its own long axis toward what the goat looks at: a hanging ear
90
- // twisted 25 deg about its root)
91
- variants: {
92
- nubian: { ears: { mobility: 0.5, speedFlatten: 0.15, twitch: 0.4, prick: 0.06 } },
93
- boer: { ears: { mobility: 0.5, speedFlatten: 0.15, twitch: 0.4, prick: 0.06 } },
94
- },
95
- };
@@ -1,98 +0,0 @@
1
- // Meshing plan: body at 5.4 mm (0.7 % of the withers height, like the cheetah), head at 2.6 mm
2
- // overlapping the body across the upper neck and cross-faded, eyelid patches at 0.9 mm, the lower
3
- // lip / chin / beard as its own rigid surface (the mouth opens) and the horns as a rigid keratin
4
- // surface on the skull.
5
- import { EYE, hornPath, hornCell, hornSplit, hornTipCell } from './sculpt.js';
6
- import { HEAD_O, hqOf, goatJoints } from './rig.js';
7
- import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
8
- import { norm, smoothstep, clamp } from '../../core/math/vec.js';
9
-
10
- const J = goatJoints();
11
- // The head mesh takes over across a plane through the upper neck, 30 % of the way from the mid neck
12
- // to the occiput, its normal the upper neck axis turned 45 deg forward (toward the head): it crosses
13
- // the nape ~6 cm behind the poll and the throat ~9 cm below the jaw angle, both where the neck is a
14
- // smooth tube and the fine and coarse meshes agree. (The first cut ran behind the poll and into the
15
- // concave jaw angle / throat junction, where they did not: a crack from the poll to the throat. A
16
- // plane square to the upright neck cut through the lower face, which hangs forward below the throat.)
17
- const NECK_U = norm([0, J.occiput[1] - J.neckMid[1], J.occiput[2] - J.neckMid[2]]);
18
- const NECK_A = Math.atan2(NECK_U[1], NECK_U[2]) - Math.PI / 4;
19
- export const NECK_CUT = {
20
- c: [0, J.neckMid[1] + 0.3 * (J.occiput[1] - J.neckMid[1]), J.neckMid[2] + 0.3 * (J.occiput[2] - J.neckMid[2])],
21
- d: [0, Math.sin(NECK_A), Math.cos(NECK_A)], band: 0.014,
22
- };
23
- export const neckS = (x, y, z) => (x - NECK_CUT.c[0]) * NECK_CUT.d[0] + (y - NECK_CUT.c[1]) * NECK_CUT.d[1] + (z - NECK_CUT.c[2]) * NECK_CUT.d[2];
24
-
25
- export const EYE_PATCH = { R: 0.024, B: 0.004, h: 0.0011, centres: [1, -1].map((s) => eyeFrameOf(EYE, HEAD_O, s).c) };
26
- export function eyePatchWeight(x, y, z) {
27
- let dmin = 1e9;
28
- for (const c of EYE_PATCH.centres) dmin = Math.min(dmin, Math.hypot(x - c[0], y - c[1], z - c[2]));
29
- return 1 - smoothstep(EYE_PATCH.R - EYE_PATCH.B, EYE_PATCH.R + EYE_PATCH.B, dmin);
30
- }
31
-
32
- export function goatRegions(rig, params, Q) {
33
- // (the band: wider than a body cell, so the body's cut edge, which lies up to a cell into the band,
34
- // stays in its hidden half: at the crowd tier a 25 mm cell left it on the visible side of a 14 mm band,
35
- // at the low tier 0.95 of a cell left one edge of a buck's neck uncovered)
36
- const r = Q.res, B = Math.max(NECK_CUT.band, 0.0059 * r * 1.2);
37
- const Ho = HEAD_O;
38
- // eyelid patches at hero, high and medium (what Safari and phones show): without them the 24 x 16 mm aperture's lid
39
- // margin fell on the medium tier's 5.6 mm face cells and tore into pale and dark flakes round every eye
40
- // (the full 24 mm patch: the face mesh stops a cell inside it, and at 21.5 mm that cut reached the lid margin, 19-22
41
- // exposed edges round the eyes at medium)
42
- const patches = (Q.eyePatches || r <= 2) ? EYE_PATCH.centres.map((c) => ({ c, R: EYE_PATCH.R, B: EYE_PATCH.B, h: EYE_PATCH.h * Math.max(1, r) })) : [];
43
- const head = [
44
- // (the long, broad lop ears of Nubians and Boers are meshed with the head: its cells 6 % coarser keep a
45
- // lop-eared buck inside the hero budget, 133k -> 128k vertices)
46
- { name: 'head', part: 'body', bmin: [-0.3, 0.6, 0.33], bmax: [0.3, Ho[1] + 0.14, Ho[2] + 0.24], h: 0.0028 * r * (params.ear === 'lop' ? (params.sex === 'male' && params.age !== 'juvenile' ? (r === 2 ? 1.13 : 1.12) : 1.06) : 1), F: 6, clip: (x, y, z) => neckS(x, y, z) > -B, patches },
47
- { name: 'jaw', part: 'jaw', bmin: [-0.06, Ho[1] - 0.27, Ho[2] - 0.09], bmax: [0.06, Ho[1] - 0.03, Ho[2] + 0.22], h: 0.0028 * r, F: 6, rigidBone: 'jaw' },
48
- ];
49
- // (the beard's locks are 7-12 mm thick: at the medium tier's 6.8 mm cells their tips folded over, back faces showing;
50
- // 5.4 mm there)
51
- if ((params.beard || 0) > 0.01) head.push({ name: 'beard', part: 'beard', bmin: [-0.07, Ho[1] - 0.46, Ho[2] - 0.16], bmax: [0.07, Ho[1] - 0.06, Ho[2] + 0.18], h: 0.0034 * (r === 2 ? 1.6 : r), F: 6, rigidBone: 'beard' });
52
- if (params.wattles) head.push({ name: 'wattle', part: 'wattle', bmin: [-0.06, Ho[1] - 0.2, Ho[2] - 0.18], bmax: [0.06, Ho[1] + 0.03, Ho[2] + 0.02], h: 0.0022 * r, F: 6, rigidBone: 'neck2' });
53
- // the udder / a buck's scrotum: its own closed surface, rigid on the udder bone (sculpt.js) (the scrotum
54
- // coarser: a horned, bearded lop-eared buck was 200 vertices over the hero budget)
55
- const adult = params.age !== 'juvenile', male = params.sex === 'male', HQ = hqOf(params);
56
- if (adult && (male || (params.udder ?? 0.5) > 0.05)) head.push({ name: 'udder', part: 'udder', bmin: [-0.11, 0.17, -0.44 + HQ], bmax: [0.11, male ? 0.62 : 0.56, -0.2 + HQ], h: (male ? 0.005 : 0.0042) * r, F: 6, rigidBone: 'udder' });
57
- if (params.horns && params.horns.len > 0) {
58
- // the box from the horn centre lines (both sides) plus the horn radius and two cells: a fixed box
59
- // cut the horn bases off (they start at the poll, z 0.65, and a doe's horns reach z 0.68)
60
- // (cells with the horn's girth: a buck's longest, thickest horns took 18k vertices at 3.2 mm, and a
61
- // lop-eared buck with them and a long beard came to 137k at hero, over the 130k budget)
62
- // (at most the low tier's cells at the crowd tier too: 16 mm cells left a buck's horn a chain of ragged lumps;
63
- // the horn is also kept ~0.45 of a cell thick there, sculpt.js hornPath)
64
- // (at the low and crowd tiers the tapering outer part is its own solid at the medium tier's cells, sculpt.js hornSplit)
65
- const h = hornCell(params, r), hT = hornTipCell(params);
66
- const box = (part, hh, from, to) => {
67
- const bmin = [1e9, 1e9, 1e9], bmax = [-1e9, -1e9, -1e9];
68
- for (const s of [1, -1]) {
69
- const pth = hornPath(params, s), J = hornSplit(params, pth);
70
- pth.forEach((q, i) => {
71
- if (J >= 0 && (i < from(J) || i > to(J, pth.length))) return;
72
- const m = q.r * 1.25 + 2 * hh + 0.004;
73
- for (let k = 0; k < 3; k++) { bmin[k] = Math.min(bmin[k], q.p[k] - m); bmax[k] = Math.max(bmax[k], q.p[k] + m); }
74
- });
75
- }
76
- head.push({ name: part, part, bmin, bmax, h: hh, F: 6, rigidBone: 'head' });
77
- };
78
- const split = hornSplit(params, hornPath(params, 1)) >= 0;
79
- box('horn', h, () => 0, (J, n) => (split ? J : n));
80
- if (split) box('horntip', hT, (J) => J - 2, (J, n) => n);
81
- }
82
- return {
83
- jobs: [
84
- [{ name: 'body', part: 'body', bmin: [-0.26, -0.01, -0.66], bmax: [0.26, 1.0, 0.7], h: 0.0059 * r, F: 4, clip: (x, y, z) => neckS(x, y, z) < B }],
85
- head,
86
- ],
87
- fade(x, y, z, name, patch) {
88
- const sN = neckS(x, y, z);
89
- if (name === 'body') return 1 - smoothstep(-B, B, sN);
90
- if (name === 'head') {
91
- let f = smoothstep(-B, B, sN);
92
- if (patches.length) { const ew = eyePatchWeight(x, y, z); f *= patch ? ew : 1 - ew; }
93
- return f;
94
- }
95
- return 1;
96
- },
97
- };
98
- }
@@ -1,181 +0,0 @@
1
- // Goat skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
2
- // Reference individual: a Saanen-type dairy doe, 0.78 m at the withers, ~65 kg (ADGA standard). Landmarks measured on side3.jpg (4x grid, 1 px = 1.39 mm) and side2.jpg
3
- // (1 px = 1.84 mm), limb segments from published goat osteometry.
4
- //
5
- // Hooves: the standard quadruped bones plus a hoof bone per leg, exactly like the horse:
6
- // fpaw / hpaw = pastern (fetlock -> coffin joint), fhoof / hhoof = the cloven hoof (coffin joint ->
7
- // toe), so the engine keeps the claws flat while the fetlock sinks under load.
8
- //
9
- // The rig depends on the individual only through the ears (erect / lateral in Swiss breeds, long and
10
- // pendulous in the Nubian: params.ear).
11
- import { buildRig } from '../../core/rig/rig.js';
12
- import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
13
-
14
- export const TAIL_SEGS = 5;
15
- // a lop ear's root blend: the ear takes the skin up to 3 cm onto the head and down to 5 cm along the ear (it hangs with
16
- // gravity, turning up to 25 deg about its root against the skull: at [-0.006, 0.02] the root and the web between the
17
- // blade and the cheek stretched 3x on 1 % more of the mesh when grazing)
18
- export const LOPBL = [-0.03, 0.05];
19
-
20
- // Head frame: modelled along its own axis (poll -> muzzle), pitched 42 degrees nose-down in the
21
- // bind pose. Head-local coordinates: x lateral, y dorsal (forehead side), z along the nasal line toward
22
- // the muzzle; origin on the axis 0.07 m in front of the poll, level with the eyes.
23
- // (side2 and walk1: the eye -> nose-tip line runs 33-34 deg below the horizontal and the forehead
24
- // 51-60 deg; the poll stands ~0.3 SH above the withers, the neck rises at ~55-64 deg. The head was
25
- // carried at 54 deg with the forehead profile at 68 deg, 5-7 cm low: a grazing horse's carriage)
26
- export const HEAD_PITCH = (42 * Math.PI) / 180;
27
- export const HZ = [0, -Math.sin(HEAD_PITCH), Math.cos(HEAD_PITCH)];
28
- export const HY = [0, Math.cos(HEAD_PITCH), Math.sin(HEAD_PITCH)];
29
- const POLL = [0, 0.975, 0.59]; // top of the poll (skin), bind
30
- export const HEAD_O = [0, POLL[1] + 0.07 * HZ[1], POLL[2] + 0.07 * HZ[2]];
31
- export const hl = (v) => [HEAD_O[0] + v[0], HEAD_O[1] + v[1] * HY[1] + v[2] * HZ[1], HEAD_O[2] + v[1] * HY[2] + v[2] * HZ[2]];
32
- // a kid's face is short: in front of the eyes the head-local z (along the nasal line) is compressed by
33
- // KID_FACE (front2, kid_side: a big braincase and eyes over a short, small muzzle; the whole head scaled
34
- // up gave a kid an adult's bulbous muzzle). faceZ maps an adult head-local z to the kid's, unFaceZ back.
35
- export const KID_FACE = 0.78;
36
- export const faceZ = (z, kid) => (kid && z > 0.02 ? 0.02 + (z - 0.02) * KID_FACE : z);
37
- export const unFaceZ = (z, kid) => (kid && z > 0.02 ? 0.02 + (z - 0.02) / KID_FACE : z);
38
- // head-local point (adult coordinates) -> world, with the kid's short face
39
- export const hlk = (v, kid) => hl([v[0], v[1], faceZ(v[2], kid)]);
40
- // head-local direction -> world
41
- export const hdir = (v) => [v[0], v[1] * HY[1] + v[2] * HZ[1], v[1] * HY[2] + v[2] * HZ[2]];
42
- // world point -> head-local
43
- export const toHL = (p) => { const d = [p[0] - HEAD_O[0], p[1] - HEAD_O[1], p[2] - HEAD_O[2]]; return [d[0], d[1] * HY[1] + d[2] * HY[2], d[1] * HZ[1] + d[2] * HZ[2]]; };
44
-
45
- // ear tips (head-local, left): Swiss erect / lateral ears point out, a little up and forward;
46
- // Nubian / Boer lop ears hang straight down beside the face (their tip is placed in world space
47
- // below the base, clear of the cheek: see goatJoints)
48
- export const EAR_BASE = [0.048, 0.026, -0.06];
49
- export const EAR_TIP = {
50
- erect: [0.2, 0.015, -0.02],
51
- };
52
- // the hindquarters (hip joint, hind limb, pelvis, tail root, udder) sit this far further forward than
53
- // the first model: side1 / side2 give a body (point of shoulder -> point of buttock) of 1.06-1.09 SH,
54
- // the model had 1.24 SH, its hip points, tail head and buttock 10-18 cm behind side2's
55
- // (adults 0.07, not 0.095: the hind hooves stood 0.17 SH ahead of the rump's outline at the toe, against
56
- // 0.06-0.12 in side2 / side3; now 0.14 at the toe, 0.05 at the heel, the cannons under the pin bones. Kids keep
57
- // 0.095: their hind legs stand under the short body, kid_side, and with them further back the Nubian kid's
58
- // sprint jittered at the wrist, p99 0.086 % S)
59
- export const hqOf = (params = {}) => (params.age === 'juvenile' ? 0.095 : 0.07);
60
-
61
- export function goatJoints(params = {}) {
62
- // (erect ears: carried from level-lateral (face3) to up-and-out (face1), params.earLift 0..1)
63
- const lop = params.ear === 'lop';
64
- const kid = params.age === 'juvenile';
65
- // (kids carry their big ears up and out: front2, kid_side)
66
- const lift = kid ? Math.max(0.6, params.earLift ?? 0.5) : (params.earLift ?? 0.5);
67
- const HQ = hqOf(params);
68
- const J = {
69
- nose: hlk([0, -0.024, 0.205], kid), // (the front of the nose pad and upper lip: the engine keeps it off the ground)
70
- occiput: hl([0, -0.045, -0.1]), // (behind the poll and the horn bases: the skull top is all 'head')
71
- neckMid: [0, 0.8, 0.472],
72
- neckBase: [0, 0.64, 0.35],
73
- chestMid: [0, 0.668, 0.17],
74
- thoraxRear: [0, 0.692, 0.015],
75
- lumbarMid: [0, 0.702, -0.1],
76
- lumbosacral: [0, 0.707, -0.215],
77
- tailBase: [0, 0.71, -0.4],
78
- // fore: scapula sloping ~65 deg, humerus down and back (45 deg from vertical), radius and cannon
79
- // vertical, pastern ~50 deg (cloven hoof)
80
- // (the elbow 1.7 cm further back: with the humerus 40 deg from vertical the shoulder -> wrist span was
81
- // 93 % of humerus + radius, the engine's reach limit left the foreleg a 0.45 m stance sweep against
82
- // the hind leg's 0.75 m, and it cut the fore stances short: duty 0.53 / 0.34 / 0.20 at the walk,
83
- // trot and gallop against the table's 0.65 / 0.42 / 0.29, a high hackney flick and pacing walk)
84
- scapTopL: [0.055, 0.745, 0.265],
85
- shoulderL: [0.088, 0.53, 0.372],
86
- elbowL: [0.083, 0.405, 0.245],
87
- wristL: [0.07, 0.21, 0.252],
88
- mcpL: [0.064, 0.07, 0.256],
89
- fcoffinL: [0.064, 0.03, 0.279],
90
- ftoeL: [0.064, 0.002, 0.323],
91
- // hind: hip joint, stifle, hock, fetlock, coffin joint, toe (the cannon vertical: it stood 6 deg
92
- // forward, sickle-hocked)
93
- hipL: [0.078, 0.63, -0.36 + HQ],
94
- kneeL: [0.093, 0.45, -0.24 + HQ],
95
- hockL: [0.066, 0.25, -0.44 + HQ],
96
- mtpL: [0.06, 0.075, -0.442 + HQ],
97
- hcoffinL: [0.06, 0.031, -0.419 + HQ],
98
- htoeL: [0.06, 0.002, -0.374 + HQ],
99
- jawHinge: hl([0, -0.045, -0.02]),
100
- jawTip: hlk([0, -0.078, 0.185], kid),
101
- // (a lop ear's root sits further back on the skull: hanging from the erect ear's root, the broad blade
102
- // covered the eye)
103
- earBaseL: hl(lop ? [EAR_BASE[0], EAR_BASE[1] - 0.006, EAR_BASE[2] - 0.01] : EAR_BASE),
104
- // udder (does): its own rigid bone below the pelvis, so it can fold up out of the ground when the
105
- // doe lies down (hooks.pose)
106
- // beard: its own bone below the chin (hangs from the jaw; hooks.pose swings it out of the ground)
107
- beardTop: hlk([0, -0.094, 0.115], kid),
108
- udderTop: [0, 0.44, -0.34 + HQ],
109
- udderBot: [0, 0.3, -0.325 + HQ],
110
- };
111
- // lop ears (Nubian, Boer): long and broad, hanging down beside the face and jaw from the base, flaring out
112
- // to 9 cm from the root at the tip and a little back of vertical, so the blade stays behind the eye (side_boer,
113
- // the Nubian standard; hanging straight down with the face pitched 42 deg nose-down it covered the eye) and
114
- // clear of the throat (within the 2 cm blend of the throat skin it took neck weights and stretched)
115
- const eb = J.earBaseL;
116
- // (a kid's lop ears are shorter: its head is scaled up as a whole, and full-length ears hung below its knees)
117
- // (Nubian ears ~25 cm, reaching below the jaw; a Boer's a little shorter: at 21 cm they ended at the
118
- // mouth corner, short paddles)
119
- const le = (kid ? 0.82 : 1) * (params.variant === 'boer' ? 0.9 : 1);
120
- J.earTipL = lop ? [eb[0] + 0.1 * le, eb[1] - 0.225 * le, eb[2] - 0.05 * le]
121
- : hl([EAR_TIP.erect[0] - 0.02 * lift, EAR_TIP.erect[1] - 0.03 + 0.11 * lift, EAR_TIP.erect[2] + 0.02 * lift]);
122
- // (a kid's erect ears are long for its head: as long as its face, front2)
123
- if (kid && !lop) for (let i = 0; i < 3; i++) J.earTipL[i] = eb[i] + (J.earTipL[i] - eb[i]) * 1.15;
124
- J.beardTip = [J.beardTop[0], J.beardTop[1] - Math.max(0.03, params.beard || 0), J.beardTop[2] - 0.01];
125
- // the short flat tail is carried up (research: erect most of the time)
126
- tailChain(J, 'tailBase', [28, 42, 55, 62, 66], [0.035, 0.032, 0.03, 0.028, 0.026]);
127
- return J;
128
- }
129
-
130
- export function goatBones() {
131
- const b = quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true });
132
- for (const d of b) {
133
- if (d[0] === 'fpaw{S}') { d[2] = 'fcoffin{S}'; d[4] = { region: 'limb', group: 'F{S}' }; }
134
- if (d[0] === 'hpaw{S}') { d[2] = 'hcoffin{S}'; d[4] = { region: 'limb', group: 'H{S}' }; }
135
- }
136
- b.push(['udder', 'udderTop', 'udderBot', 'pelvis', { region: 'torso', group: 'udder' }]);
137
- b.push(['beard', 'beardTop', 'beardTip', 'jaw', { region: 'jaw', group: 'jaw' }]);
138
- b.push(
139
- ['fhoof{S}', 'fcoffin{S}', 'ftoe{S}', 'fpaw{S}', { region: 'foot', group: 'F{S}' }],
140
- ['hhoof{S}', 'hcoffin{S}', 'htoe{S}', 'hpaw{S}', { region: 'foot', group: 'H{S}' }],
141
- );
142
- return b;
143
- }
144
-
145
- export function goatRig(params = {}, J = goatJoints(params)) {
146
- const limbs = quadrupedLimbs({
147
- front: { tCore: 0.5, aCore: 0.05, aBody: -0.15, midX: 0.0 },
148
- hind: { tCore: 0.45, aCore: 0.022, aBody: -0.11, midX: 0.008 },
149
- });
150
- for (const L of Object.values(limbs)) { L.bones.push((L.front ? 'fhoof' : 'hhoof') + L.S); L.distal.push((L.front ? 'fhoof' : 'hhoof') + L.S); }
151
- return buildRig({
152
- joints: J,
153
- unit: 1.03,
154
- headOrigin: HEAD_O,
155
- bones: goatBones(),
156
- axial: {
157
- points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
158
- bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
159
- // the skull's influence reaches back into the throat (widening with the depth below the axis)
160
- // (a narrower lever, 0.5, kept the cheek out of the blend but gathered the stretch at the jaw angle:
161
- // fewer triangles over 2x, more over 3x; the throat stretch is cured in the poses instead, the grazing
162
- // head pitch and a kid's short face, see motion.js and rig.js faceZ)
163
- // (the neck base blends over 8 cm each side: the skin over the withers stretched 3x when the head went
164
- // down or round to the flank)
165
- // (15 cm: at 8 cm the skin over the withers bent over a ridge when the neck went down to graze; the Boer
166
- // keeps 11 cm: wider, its broad chest front took neck weights, and lying dead it rested 11 mm in the
167
- // ground, and its red / white border across the lower neck stretched)
168
- blend: { 1: [-0.05, 0.14, 4.5], 3: params.variant === 'boer' ? [-0.11, 0.11, 0] : [-0.15, 0.15, 0] },
169
- bodyTail: 0, // (the rump and buttocks do not blend into the tail: they tore when the thighs folded to lie down)
170
- },
171
- limbs,
172
- appendages: [
173
- // (a long lop ear swings about its root as the head moves: its root blends over 2.6 cm, where an
174
- // erect ear's took 6 mm and tore; reaching 1 cm onto the head it dragged the skin behind the root)
175
- { group: 'earL', bone: 'earL', blend: params.ear === 'lop' ? LOPBL : [-0.002, 0.004] },
176
- { group: 'earR', bone: 'earR', blend: params.ear === 'lop' ? LOPBL : [-0.002, 0.004] },
177
- { group: 'udder', bone: 'udder', blend: [-0.004, 0.02] },
178
- ],
179
- webTags: ['flankfold', 'thighfront', 'scapmuscle', 'pectoral', 'forearmweb'],
180
- });
181
- }