@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,152 +0,0 @@
1
- // Domestic sheep (Ovis aries). Cloven-hoofed grazer in wool: the fleece is a sculpted volume broken
2
- // into locks (sculpt.js) under short, tightly clumped, matte shells (the crimped staple tips), with a
3
- // clean short-haired face and legs; horizontal bar pupils in amber irises; spiral horns in Merino
4
- // rams; the flock animal's alarm, constant chewing while grazing, bleating, the ram's charge and the
5
- // ewe's foot stamp (behaviour.js).
6
- import { sheepRig, HEAD_O } from './rig.js';
7
- import { sculptSheep, EYE } from './sculpt.js';
8
- import { sheepRegions } from './regions.js';
9
- import { sheepCoat } 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
-
14
- const pick = (R, table) => {
15
- let x = R() * table.reduce((s, [, w]) => s + w, 0);
16
- for (const [k, w] of table) { x -= w; if (x <= 0) return k; }
17
- return table[table.length - 1][0];
18
- };
19
-
20
- // Breeds / morphs (variants). fleece: [min, max] total fleece length (m, a year's growth);
21
- // horned: share of rams with horns; docked: share of docked tails; ear: carriage (rig.js EAR_SET)
22
- const BREEDS = {
23
- whiteface: { coats: [['white', 1]], fleece: [0.05, 0.12], horned: 0, docked: 0.6, ear: 'lateral', roman: [0, 0.2], topknot: 0.25, size: 1, legs: 1, girth: 1 },
24
- suffolk: { coats: [['suffolk', 1]], fleece: [0.04, 0.09], horned: 0, docked: 0.65, ear: 'droop', roman: [0.7, 1], topknot: 0, size: 1.08, legs: 1.03, girth: 1.03 },
25
- merino: { coats: [['merino', 1]], fleece: [0.06, 0.1], horned: 0.95, docked: 0.85, ear: 'small', roman: [0.2, 0.5], topknot: 1, size: 0.94, legs: 0.97, girth: 1 },
26
- black: { coats: [['black', 75], ['brown', 25]], fleece: [0.05, 0.12], horned: 0.3, docked: 0.4, ear: 'lateral', roman: [0, 0.3], topknot: 0.15, size: 0.98, legs: 1, girth: 1 },
27
- shorn: { coats: [['white', 60], ['texel', 40]], fleece: [0.004, 0.015], horned: 0, docked: 0.7, ear: 'lateral', roman: [0, 0.2], topknot: 0, size: 1, legs: 1, girth: 1 },
28
- };
29
-
30
- export default {
31
- id: 'sheep',
32
- name: 'Sheep',
33
- latin: 'Ovis aries',
34
- group: 'hooves',
35
- plan: 'quadruped',
36
- covering: 'fur',
37
- variants: [
38
- { id: 'whiteface', name: 'White-faced sheep', latin: 'Ovis aries' },
39
- { id: 'suffolk', name: 'Suffolk', latin: 'Ovis aries' },
40
- { id: 'merino', name: 'Merino', latin: 'Ovis aries' },
41
- { id: 'black', name: 'Black sheep', latin: 'Ovis aries' },
42
- { id: 'shorn', name: 'Shorn sheep', latin: 'Ovis aries' },
43
- ],
44
-
45
- // Seeded individual. Breed / morph (o.variant: whiteface (default type), suffolk, merino, black,
46
- // shorn) sets the colours, ears, Roman nose, horns and fleece; sex: ewe or ram (heavier, broader,
47
- // thick neck, curled horns in horned breeds); age: adult or lamb (juvenile: long legs, short body,
48
- // big head and ears, short tight curly fleece, long tail). The fleece length (params.fleece,
49
- // 0 = shorn .. 0.15 m) is seeded within the breed's range (overrides: { fleece }).
50
- variation(R0, o) {
51
- // (the pipeline's stream is correlated between neighbouring seeds: re-mix it through an integer hash)
52
- let h = (Math.floor(R0() * 4294967296) ^ Math.imul((o.seed ?? 1) + 0x632be5ab, 0x9e3779b1)) >>> 0;
53
- h = Math.imul(h ^ (h >>> 16), 0x85ebca6b); h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35); h = (h ^ (h >>> 16)) >>> 0;
54
- const R = rng(h);
55
- for (let i = 0; i < 3; i++) R();
56
- const variant = BREEDS[o.variant] ? o.variant : pick(R, [['whiteface', 40], ['suffolk', 24], ['merino', 16], ['black', 10], ['shorn', 10]]);
57
- const Bd = BREEDS[variant];
58
- const sex = o.sex || (R() < 0.4 ? 'male' : 'female');
59
- const age = o.age || (R() < 0.18 ? 'juvenile' : 'adult');
60
- const lamb = age === 'juvenile';
61
- const ram = sex === 'male' && !lamb;
62
- const g = () => (R() + R() + R() - 1.5) / 1.5; // ~[-1, 1], peaked
63
- const coat = pick(R, Bd.coats);
64
- // fleece length: a year's growth for adults, 10-20 mm tight curls for lambs
65
- const u = 0.5 + 0.5 * g();
66
- let fleece = lamb ? 0.012 + 0.01 * R() : Bd.fleece[0] + (Bd.fleece[1] - Bd.fleece[0]) * u;
67
- if (o.overrides && o.overrides.fleece !== undefined) fleece = o.overrides.fleece;
68
- fleece = Math.max(0, Math.min(0.15, fleece));
69
- // the outer staple tips are shells; the rest of the fleece is sculpted volume
70
- const staple = Math.max(0.005, Math.min(0.018, 0.25 * fleece + 0.004)) * (lamb ? 1.1 : 1);
71
- const wool = fleece > 0.035 ? fleece - staple : 0; // (short fleeces: shells over the body skin only)
72
- let horns = null;
73
- if (ram && R() < Bd.horned) horns = { turns: (variant === 'merino' ? 1.0 : 0.75) + 0.35 * R(), base: 0.03 + 0.009 * R(), r0: 0.95 + 0.1 * R(), flare: 0.8 + 0.4 * R() };
74
- else if (lamb && sex === 'male' && R() < Bd.horned) horns = { turns: 0.12 + 0.06 * R(), base: 0.012, r0: 0.75, flare: 0.5 };
75
- const docked = !lamb ? R() < Bd.docked : R() < Bd.docked * 0.5;
76
- const tailLen = docked ? 0.06 + 0.04 * R() : 0.3 + 0.08 * R();
77
- const size = (ram ? 1.13 + 0.05 * R() : 1) * (1 + 0.045 * g()) * Bd.size * (lamb ? 0.62 : 1);
78
- return {
79
- sex, age, size, variant, coat,
80
- fleece, staple, wool,
81
- horns,
82
- tailLen,
83
- ear: Bd.ear,
84
- earLift: R(),
85
- roman: (Bd.roman[0] + (Bd.roman[1] - Bd.roman[0]) * R()) + (ram ? 0.2 : 0),
86
- topknot: R() < Bd.topknot ? 0.4 + 0.6 * R() : 0,
87
- folds: variant === 'merino' && !lamb ? (ram ? 0.7 : 0.4) + 0.3 * R() : 0,
88
- muscle: coat === 'texel' ? 0.6 + 0.4 * R() : 0.3 * R(),
89
- udder: sex === 'female' && !lamb ? 0.1 + 0.6 * R() : 0,
90
- heavy: ram ? 0.6 + 0.4 * R() : 0,
91
- hoofStripe: R(),
92
- hornColor: variant === 'black' ? 0x6a5846 : 0xb09a78,
93
- coatShade: g(), coatLightness: 0.05 * g(),
94
- coatSeed: Math.floor(R() * 1e6),
95
- minThick: 0.004,
96
- warps: [
97
- // (the head scale first: its centre is the unwarped head origin)
98
- { type: 'scaleAbout', c: HEAD_O, k: (1 + 0.035 * g()) * (lamb ? 1.22 : 1) * (ram ? 1.06 : 1), r0: 0.1, r1: 0.2 },
99
- { type: 'legs', k: (1 + 0.035 * g()) * Bd.legs * (lamb ? 1.24 : 1), top: 0.36 },
100
- { type: 'length', k: (1 + 0.035 * g()) * (lamb ? 0.84 : 1), z0: -0.4, z1: 0.3 },
101
- { type: 'girth', k: (1 + 0.04 * g()) * Bd.girth * (ram ? 1.05 : 1) * (lamb ? 0.9 : 1), cy: 0.47, z0: -0.5, z1: 0.36 },
102
- ],
103
- };
104
- },
105
- rig: (params) => sheepRig(params),
106
- sculpt: (m, rig, params) => sculptSheep(m, rig, params),
107
- regions: sheepRegions,
108
- coat: sheepCoat,
109
- eyeSpecs: (params) => [1, -1].map((side) => ({ side, spec: EYE, headOrigin: HEAD_O, bone: 'head', look: eyeLook(params) })),
110
- motion,
111
- // wool: fine, dense strands in small tight clumps (crimped staple tips); matte
112
- render: (params) => ({
113
- markColor: srgb(['suffolk', 'black'].includes(params.variant) ? 0x141212 : 0x5c4a46),
114
- strandDensity: params.variant === 'merino' ? 1500 : 1150,
115
- clumpDensity: (params.fleece || 0) > 0.02 ? 1.9 : 1.3,
116
- shellScale: 1,
117
- finWidth: 0.35,
118
- // (the short face and leg hair forms small tufts too, each leaning its own way: the face reads as short
119
- // hair rather than a smooth rubber skin, and the highlight on a black face breaks up instead of running
120
- // in glossy streaks; the default [0.0055, 0.016] left 4-6 mm hair untufted)
121
- clumpLen: [0.0015, 0.009],
122
- // (no silhouette fins: over a sculpted fleece they drew the lock bumps' contours as dark seams across
123
- // the back and the rump, and on short coats (shorn, lambs) they traced the head / body mesh hand-over
124
- // down the neck as a dotted line; the shells alone give the short coat's soft edge)
125
- fins: false,
126
- // (core render hint: the wool's shells slide down the staple as they rise; where the neck creases (the
127
- // throat when grazing, the side of the neck toward which the head turns) they dove under the skin of the
128
- // fold and it showed as a jagged bald line. Taken ~5 mm nearer the camera they stay on top; face and leg
129
- // hair shorter than 8 mm is untouched)
130
- shellDepthBias: [0.6, 0.008],
131
- }),
132
- };
133
-
134
- // The sheep's eye: a horizontal bar pupil (rectangular, 2.5-3 : 1 when constricted) in a golden to
135
- // amber-brown iris, sclera hardly visible, dark lids; lambs paler.
136
- const IRISES = [
137
- { inner: 0x9c7a34, mid: 0xb8913f, hi: 0xd4b066, outer: 0x5e4418 }, // amber (default)
138
- { inner: 0x6e5020, mid: 0x8a6a30, hi: 0xa8864a, outer: 0x3e2a10 }, // darker amber-brown
139
- { inner: 0xa88a48, mid: 0xc8a85a, hi: 0xe0c888, outer: 0x6a5020 }, // pale golden
140
- ];
141
- function eyeLook(params) {
142
- const s = ((params.coatSeed || 0) % 100) / 100;
143
- const ir = IRISES[params.age === 'juvenile' ? 2 : s < 0.6 ? 0 : s < 0.9 ? 1 : 2];
144
- return {
145
- pupil: 'bar',
146
- lids: 'mammal',
147
- iris: { inner: srgb(ir.inner), mid: srgb(ir.mid), hi: srgb(ir.hi), outer: srgb(ir.outer) },
148
- sclera: { color: [0.45, 0.38, 0.32], visible: false },
149
- lidColor: [0.03, 0.025, 0.022],
150
- pupilSize: [0.1, 0.34],
151
- };
152
- }
@@ -1,86 +0,0 @@
1
- // Sheep motion data for the quadruped engine (schema: src/core/motion/quadruped.js).
2
- // Numbers are for the reference individual (params.size = 1, a 0.70 m, 70 kg ewe); the engine
3
- // scales them by dynamic similarity for lambs and big rams.
4
- //
5
- // Gaits: lateral-sequence 4-beat walk (0.9-1.3 m/s: 0.96-1.25 Hz,
6
- // duty 0.66 -> 0.60, hoof swing height 49 mm fore / 55 mm hind, Kim & Breur 2008, treadmill studies),
7
- // 2-beat diagonal trot (1.8-2.4 Hz, duty 0.45 -> 0.37), a 3-beat canter (right lead) in flock flight
8
- // and the transverse gallop (2.5-3 Hz). Crossovers: walk -> trot at Froude ~0.45 (1.8 m/s for a
9
- // 0.72 m hip height), trot -> canter / gallop 4.3 m/s at ~2.5 Hz (Heglund et al. 1974: v = 1.535
10
- // M^0.24, f = 4.48 M^-0.14 for 70 kg).
11
- import { hooks } from './behaviour.js';
12
-
13
- const G = (name, v, f, D, off, o) => ({ name, v, f, D, off, ...o });
14
-
15
- export const motion = {
16
- maxSpeed: 8.5,
17
- accel: [3, 6.5],
18
- decel: 7,
19
- turnRate: 3.0,
20
- latAccelMax: 8,
21
- gears: { walk: 0.95, trot: 2.8, canter: 4.7, gallop: 6.8 },
22
- gallopBlend: [4.0, 6.5],
23
- // name v f D [FL, FR, HL, HR]
24
- gaits: [
25
- G('walk', 0.0, 0.75, 0.7, [0.25, 0.75, 0.0, 0.5], { liftF: 0.042, liftH: 0.046, bobF: 0.01, bobH: 0.01, flex: 0, lat: 0.02, fold: 0.65, heel: 18, tail: 0, drop: 0 }),
26
- G('walk', 1.5, 1.28, 0.6, [0.27, 0.77, 0.0, 0.5], { liftF: 0.05, liftH: 0.055, bobF: 0.022, bobH: 0.022, flex: 0, lat: 0.025, fold: 0.85, heel: 26, tail: 0.1, drop: 0 }),
27
- G('trot', 2.05, 1.9, 0.45, [0.52, 0.02, 0.0, 0.5], { liftF: 0.075, liftH: 0.062, bobF: 0.026, bobH: 0.026, flex: 0.01, lat: 0.0, fold: 1.05, heel: 36, tail: 0.12, drop: 0.006 }),
28
- G('trot', 3.8, 2.3, 0.36, [0.52, 0.02, 0.0, 0.5], { liftF: 0.09, liftH: 0.075, bobF: 0.03, bobH: 0.03, flex: 0.015, lat: 0.0, fold: 1.15, heel: 52, tail: 0.16, drop: 0.01 }),
29
- G('canter', 4.4, 2.35, 0.35, [0.3, 0.55, 0.0, 0.27], { liftF: 0.1, liftH: 0.085, bobF: 0.024, bobH: 0.032, flex: 0.06, lat: 0, fold: 1.2, heel: 38, tail: 0.20, drop: 0.015 }),
30
- G('canter', 5.1, 2.45, 0.32, [0.3, 0.55, 0.0, 0.26], { liftF: 0.105, liftH: 0.09, bobF: 0.025, bobH: 0.034, flex: 0.08, lat: 0, fold: 1.25, heel: 48, tail: 0.24, drop: 0.02 }),
31
- G('gallop', 6.0, 2.6, 0.28, [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.3, heel: 45, tail: 0.28, drop: 0.022 }),
32
- G('gallop', 8.5, 2.85, 0.24, [0.56, 0.66, 0.0, 0.1], { liftF: 0.115, liftH: 0.11, bobF: 0.024, bobH: 0.034, flex: 0.12, lat: 0, fold: 1.25, heel: 40, tail: 0.40, drop: 0.035 }),
33
- ],
34
- feet: {
35
- // cloven hooves on fairly upright pasterns: the fetlock sinks a little under load, the claws flip
36
- // in swing, breakover about the claw tips
37
- front: { type: 'unguligrade', contact: 1.0, curl: 62, flex: 4, sink: 6, hoofFlex: 15, swingBack: 0.06, liftBehind: 0.95 },
38
- hind: { type: 'unguligrade', contact: 0.92, curl: 60, flex: 4, sink: 8, hoofFlex: 15, swingBack: 0.02 },
39
- },
40
- stance: { width: 1, gallopWidth: 0.8, sprawl: 0, crouch: 0, scuff: [10, 20, 0] },
41
- // torso cross-sections of the shorn body (bind pose, reference size): centre height, half height,
42
- // half width (half heights include the legs folded under the chest and thighs when lying down);
43
- // behaviour.js adds the fleece of the individual
44
- body: {
45
- chest: { y: 0.47, hh: 0.25, hw: 0.165 },
46
- mid: { y: 0.47, hh: 0.24, hw: 0.18 },
47
- pelvis: { y: 0.53, hh: 0.3, hw: 0.17 },
48
- rump: { z: -0.43, y: 0.53, hh: 0.3, hw: 0.14 },
49
- back: 0.06,
50
- },
51
- head: {
52
- // [speed, raise (m), reach (m), pitch (rad, + = nose down)]: head up and alert at rest, lower and
53
- // forward at the walk (following the flock), stretched forward in flight
54
- carriage: [[0, 0.02, -0.01, -0.04], [0.95, -0.02, 0.01, 0.03], [2.5, -0.02, 0.03, 0.03], [4.2, -0.05, 0.05, 0.08], [8, -0.08, 0.08, 0.12]],
55
- stab: [[0, 0], [0.95, 0.15], [2.5, 0.45], [4.2, 0.35], [8, 0.4]],
56
- neckBend: 34, neckPivot: 0.75, yaw: 0.85, pitchUp: 0.65, pitchDown: 0.9, mouth: 'jawTip',
57
- },
58
- tail: {
59
- // [speed, pitch per segment from horizontal (deg), base -> tip]: hangs straight down (the docked
60
- // stump too), lifts a little when running
61
- carriage: [
62
- [0.0, [-38, -64, -76, -82, -86, -88]],
63
- [1.4, [-34, -60, -74, -80, -84, -86]],
64
- [3.5, [-32, -58, -72, -79, -83, -85]],
65
- [7, [-28, -52, -66, -74, -78, -80]],
66
- ],
67
- stiffness: 0.9, sway: 5, flick: 0.4, wag: 0, swish: 0, curl: 0, balance: 0,
68
- radius: [0.035, 0.025],
69
- },
70
- ears: { rest: [0, 0], mobility: 0.9, speedFlatten: 0.25, twitch: 1.5, prick: 0.25 },
71
- breath: { rate: 0.3, amp: 0.006, pant: false, pantRate: 2.2, pantAmp: 0.014, heatSpeed: 6 },
72
- actions: {
73
- // grazing: muzzle on the sward, the forefeet a little spread
74
- eat: { style: 'graze', dropF: 0.1, dropH: 0, pitch: 0.9, ahead: 0.6 },
75
- drink: { dropF: 0.1, dropH: 0, pitch: 0.9, ahead: 0.6 },
76
- // a low jump with the forelegs tucked (0.5-1 m obstacles)
77
- jump: { height: 0.6, distance: 1.4, land: [0.16, 0.14] },
78
- sit: { dropH: 0.8 },
79
- // kneels on both carpi first, then drops the hindquarters; rises hind end first (ruminant)
80
- lie: { down: 'front', up: 'hind' },
81
- sleep: { down: 'front', up: 'hind' },
82
- // lying sternal: forelegs folded under the chest (carpus flexed, cannons back along the ground)
83
- fold: { front: { z: -0.2, k: 1.45, beta: 0.9 } },
84
- },
85
- hooks,
86
- };
@@ -1,41 +0,0 @@
1
- // The head / body meshing boundary across the upper neck (regions.js), also used by the sculpt and
2
- // the coat.
3
- import { HZ, hl, EAR_BASE, EAR_SET, earTip } from './rig.js';
4
- import { norm } from '../../core/math/vec.js';
5
-
6
- // cut across the neck just behind the ears, perpendicular to the head's axis (the dense head mesh
7
- // stops where the neck wool starts: the head emerges from the fleece)
8
- // (two planes: one across the head's axis behind the ears, one tilted through the throat behind the
9
- // jaw so the lower neck and the breast stay in the body)
10
- const C1 = hl([0, 0, -0.078]), C2 = [0, 0.76, 0.5], D2 = norm([0, 0.45, 1]);
11
- export const NECK_CUT = { c: C1, d: HZ, band: 0.012 };
12
- // ... and the ears, swept back past that plane, stay in the head mesh: a zone round every ear any
13
- // individual can carry (each carriage, ear lift and the horned ram's base), left side; mirrored by |x|
14
- const EAR_SEGS = [];
15
- for (const ear of Object.keys(EAR_SET)) {
16
- for (const earLift of [0, 0.5, 1]) {
17
- for (const horns of [null, { turns: 1 }]) {
18
- const base = horns ? [0.05, 0.002, -0.066] : EAR_BASE;
19
- EAR_SEGS.push([hl(base), hl(earTip({ ear, earLift, horns }, base))]);
20
- }
21
- }
22
- }
23
- const EAR_R = 0.038;
24
- function earDist(x, y, z) {
25
- let dm = 1e9;
26
- for (const [a, b] of EAR_SEGS) {
27
- const dx = b[0] - a[0], dy = b[1] - a[1], dz = b[2] - a[2];
28
- const px = Math.abs(x) - a[0], py = y - a[1], pz = z - a[2];
29
- const t = Math.max(0, Math.min(1, (px * dx + py * dy + pz * dz) / (dx * dx + dy * dy + dz * dz)));
30
- const d = Math.hypot(px - dx * t, py - dy * t, pz - dz * t);
31
- if (d < dm) dm = d;
32
- }
33
- return dm;
34
- }
35
- export const neckS = (x, y, z) => {
36
- const s = Math.min(
37
- (x - C1[0]) * HZ[0] + (y - C1[1]) * HZ[1] + (z - C1[2]) * HZ[2],
38
- (y - C2[1]) * D2[1] + (z - C2[2]) * D2[2],
39
- );
40
- return s > EAR_R ? s : Math.max(s, EAR_R - earDist(x, y, z));
41
- };
@@ -1,62 +0,0 @@
1
- // Meshing plan: body at 5.6 mm (0.8 % of the withers height; the fleece makes a large surface),
2
- // head at 2.6 mm overlapping the body across the upper neck and cross-faded, eyelid patches at
3
- // 0.9 mm, the lower lip / chin as its own rigid surface (the mouth opens) and the horns as a rigid
4
- // keratin surface on the skull.
5
- import { EYE } from './sculpt.js';
6
- import { HEAD_O, hl } from './rig.js';
7
- import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
8
- import { smoothstep } from '../../core/math/vec.js';
9
-
10
- export { NECK_CUT, neckS } from './neck.js';
11
- import { NECK_CUT, neckS } from './neck.js';
12
-
13
- export const EYE_PATCH = { R: 0.024, B: 0.004, h: 0.0011, centres: [1, -1].map((s) => eyeFrameOf(EYE, HEAD_O, s).c) };
14
- // the front of the nose re-meshed finer too: the nostril slits (7 x 20 mm carves) and the philtrum came out of
15
- // the 4-5 mm face cells as ragged dark blotches; ~1.2 mm cells (2.4 at medium) give clean slits
16
- export const NOSE_PATCH = { R: 0.024, B: 0.004, h: 0.0012, centres: [hl([0, -0.022, 0.195])] };
17
- const ballWeight = (P, x, y, z) => {
18
- let dmin = 1e9;
19
- for (const c of P.centres) dmin = Math.min(dmin, Math.hypot(x - c[0], y - c[1], z - c[2]));
20
- return 1 - smoothstep(P.R - P.B, P.R + P.B, dmin);
21
- };
22
- export const eyePatchWeight = (x, y, z) => ballWeight(EYE_PATCH, x, y, z);
23
- // (the patches lie far apart: a point is in one at most)
24
- export const patchWeight = (x, y, z) => Math.max(ballWeight(EYE_PATCH, x, y, z), ballWeight(NOSE_PATCH, x, y, z));
25
-
26
- export function sheepRegions(rig, params, Q) {
27
- const r = Q.res;
28
- const W = 0.2 + (params.wool || 0) * 1.3;
29
- const hBody = 0.0065 * (1 + 1.6 * (params.wool || 0)) * r;
30
- // (the band is wider than a body cell, so the body's cut edge, which lies up to a cell into the band,
31
- // stays in its hidden half: at the low and crowd tiers a 12 mm band left it on show, an open seam
32
- // across the top of the neck)
33
- const B = Math.max(NECK_CUT.band, hBody * 1.2);
34
- // (eyelid patches at medium too: Safari and phones show medium, and the coarse face cut the almond into a
35
- // ragged notch)
36
- const patches = (Q.eyePatches || r <= 2) ? [EYE_PATCH, NOSE_PATCH].flatMap((P) => P.centres.map((c) => ({ c, R: P.R, B: P.B, h: P.h * Math.max(1, r) }))) : [];
37
- // (the face a little finer at medium: the nostril slits and the lip line came out ragged)
38
- const hm = r === 2 ? 0.78 : 1;
39
- const head = [
40
- { name: 'head', part: 'body', bmin: [-0.3, 0.5, 0.3], bmax: [0.3, 1.05, 0.8], h: 0.0031 * r * hm, F: 6, clip: (x, y, z) => neckS(x, y, z) > -B, patches },
41
- { name: 'jaw', part: 'jaw', bmin: [-0.05, 0.5, 0.45], bmax: [0.05, 0.8, 0.8], h: 0.0027 * r * hm, F: 6, rigidBone: 'jaw' },
42
- ];
43
- if (params.horns && params.horns.turns > 0) {
44
- head.push({ name: 'horn', part: 'horn', bmin: [-0.36, 0.5, 0.2], bmax: [0.36, 1.12, 0.8], h: (params.horns.base > 0.025 ? 0.0042 : 0.003) * r, F: 6, rigidBone: 'head' });
45
- }
46
- return {
47
- jobs: [
48
- [{ name: 'body', part: 'body', bmin: [-W - 0.02, -0.01, -0.62 - W], bmax: [W + 0.02, 1.02, 0.72], h: hBody, F: 4, clip: (x, y, z) => neckS(x, y, z) < B }],
49
- head,
50
- ],
51
- fade(x, y, z, name, patch) {
52
- const sN = neckS(x, y, z);
53
- if (name === 'body') return 1 - smoothstep(-B, B, sN);
54
- if (name === 'head') {
55
- let f = smoothstep(-B, B, sN);
56
- if (patches.length) { const ew = patchWeight(x, y, z); f *= patch ? ew : 1 - ew; }
57
- return f;
58
- }
59
- return 1;
60
- },
61
- };
62
- }
@@ -1,163 +0,0 @@
1
- // Sheep skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
2
- // Reference individual: a white-faced medium-wool ewe (Dorset / Cheviot / Texel type), 0.70 m at the
3
- // withers (skeleton, without the fleece), ~70 kg. Landmarks measured on
4
- // side2.jpg (1 px = 1.67 mm), side3_texel.jpg (shorn: nose -> buttock 1.73 SH, belly 0.39 SH, head
5
- // 0.37 SH) and the research limb table (sheep have long cannons, short forearms).
6
- //
7
- // Hooves: the standard quadruped bones plus a hoof bone per leg, exactly like the horse and the goat:
8
- // fpaw / hpaw = pastern (fetlock -> coffin joint), fhoof / hhoof = the cloven hoof (coffin joint ->
9
- // toe), so the engine keeps the claws flat while the fetlock sinks under load.
10
- //
11
- // The rig depends on the individual through the ears (lateral and horizontal; long and drooping in
12
- // the Suffolk: params.ear) and the tail (long, hanging to the hocks, or docked: params.tail).
13
- import { buildRig } from '../../core/rig/rig.js';
14
- import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
15
-
16
- export const TAIL_SEGS = 6;
17
-
18
- // Head frame: modelled along its own axis (poll -> muzzle), pitched 37 degrees nose-down in the
19
- // bind pose; the dorsal line falls a further 11 degrees from the axis toward the nose (sculpt.js topY),
20
- // so the nasal line stands 48 degrees to the ground (side2: 46 deg). (At 48 degrees for the axis, the
21
- // nasal line stood at 59: a face hanging straight down from a high dome, the "boot".) Head-local
22
- // coordinates: x lateral, y dorsal (forehead side), z along the axis toward the muzzle; origin on the
23
- // axis 0.07 m in front of the poll, level with the eyes.
24
- export const HEAD_PITCH = (33 * Math.PI) / 180;
25
- export const HZ = [0, -Math.sin(HEAD_PITCH), Math.cos(HEAD_PITCH)];
26
- export const HY = [0, Math.cos(HEAD_PITCH), Math.sin(HEAD_PITCH)];
27
- const POLL = [0, 0.895, 0.54]; // top of the poll (skin), bind
28
- export const HEAD_O = [0, POLL[1] + 0.07 * HZ[1], POLL[2] + 0.07 * HZ[2]];
29
- 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]];
30
- // head-local direction -> world
31
- export const hdir = (v) => [v[0], v[1] * HY[1] + v[2] * HZ[1], v[1] * HY[2] + v[2] * HZ[2]];
32
-
33
- // ears (head-local, left): carried out to the sides and swept back, so the leaf reads from the side as well
34
- // as from the front (front1, face1, side4_suffolk, extra/Suffolk_sheep_20790901685, Tete_de_brebie_Suffolk:
35
- // "aeroplane" ears seen from the front, a long blade reaching back past the poll seen from the side). Given
36
- // as a world direction in the bind pose (back = degrees swept back from straight out, down = degrees below
37
- // level) and a length; the Suffolk's are longer and hang a little; the Merino's smaller. (Straight out to
38
- // the sides, an ear seen from the side was only its foreshortened stalk: a stub against the poll.)
39
- // (At 40-46 deg back with the blade on edge, the ear read as a pink cup standing up from the side and a
40
- // paddle behind the poll. At 32-36 deg back the near ear, seen from the side, was still a short
41
- // pink cup over the poll (its length foreshortened) and the far ear a paddle; now 46-48 deg back (Suffolk 40)
42
- // and 20 deg below level (side2: the ear a leaf held level, pointing back, its inside showing), the blade's
43
- // turn in sculpt.js.)
44
- export const EAR_BASE = [0.056, 0.006, -0.058]; // (at the top corners of the head, behind the eyes)
45
- export const EAR_SET = {
46
- lateral: { back: 46, down: 20, len: 0.135 },
47
- droop: { back: 40, down: 28, len: 0.152 },
48
- small: { back: 48, down: 14, len: 0.112 },
49
- };
50
- // world direction (bind) -> head-local
51
- const toLocal = (d) => [d[0], d[1] * HY[1] + d[2] * HY[2], d[1] * HZ[1] + d[2] * HZ[2]];
52
- export function earTip(params = {}, base = EAR_BASE) {
53
- const E = EAR_SET[params.ear] || EAR_SET.lateral;
54
- // (a horned ram's ear comes out under the horn's sweep: less swept back, or it runs into the coil)
55
- const back = (params.horns && params.horns.turns > 0.3 ? 0.35 : 1) * E.back * Math.PI / 180;
56
- const down = (E.down + 14 * ((params.earLift ?? 0.5) - 0.5)) * Math.PI / 180;
57
- const d = toLocal([Math.cos(down) * Math.cos(back), -Math.sin(down), -Math.cos(down) * Math.sin(back)]);
58
- const L = E.len;
59
- return [base[0] + d[0] * L, base[1] + d[1] * L, base[2] + d[2] * L];
60
- }
61
-
62
- // tail: long (undocked, to the hocks) or docked (a short stump)
63
- export function tailSpec(params = {}) {
64
- const L = params.tailLen ?? 0.34;
65
- const w = [0.2, 0.19, 0.17, 0.16, 0.14, 0.14];
66
- const long = L > 0.15;
67
- return {
68
- len: L,
69
- lens: w.map((f) => f * L),
70
- pitch: long ? [-38, -64, -76, -82, -86, -88] : [-28, -45, -55, -60, -62, -64],
71
- };
72
- }
73
-
74
- export function sheepJoints(params = {}) {
75
- const earB = params.horns && params.horns.turns > 0.3 ? [0.05, 0.002, -0.066] : EAR_BASE;
76
- const J = {
77
- nose: hl([0, -0.014, 0.195]), // (the front of the nose pad and upper lip: the engine keeps it off the ground)
78
- occiput: hl([0, -0.045, -0.1]), // (behind the poll and horn bases: the skull top is all 'head')
79
- neckMid: [0, 0.715, 0.425],
80
- neckBase: [0, 0.555, 0.285],
81
- chestMid: [0, 0.585, 0.13],
82
- thoraxRear: [0, 0.61, -0.03],
83
- lumbarMid: [0, 0.622, -0.17],
84
- lumbosacral: [0, 0.625, -0.3],
85
- tailBase: [0, 0.612, -0.47],
86
- // fore: scapula sloping ~60 deg, humerus down and back, forearm and cannon vertical, pastern ~50
87
- // deg (research: humerus 0.17, radius 0.18, cannon 0.13)
88
- scapTopL: [0.056, 0.668, 0.21],
89
- shoulderL: [0.086, 0.49, 0.305],
90
- elbowL: [0.08, 0.345, 0.215],
91
- wristL: [0.068, 0.185, 0.232],
92
- mcpL: [0.062, 0.064, 0.238],
93
- fcoffinL: [0.062, 0.028, 0.258],
94
- ftoeL: [0.062, 0.002, 0.3],
95
- // hind: hip joint, stifle, hock, fetlock, coffin joint, toe (femur 0.20, tibia 0.23, cannon 0.15)
96
- hipL: [0.076, 0.555, -0.33],
97
- kneeL: [0.09, 0.385, -0.215],
98
- hockL: [0.064, 0.215, -0.385],
99
- mtpL: [0.058, 0.066, -0.365],
100
- hcoffinL: [0.058, 0.029, -0.343],
101
- htoeL: [0.058, 0.002, -0.3],
102
- jawHinge: hl([0, -0.045, -0.02]),
103
- jawTip: hl([0, -0.064, 0.189]), // (the front of the lower lip: the mouth the engine puts on the ground)
104
- // (horned rams: the ears come out below and behind the horn bases)
105
- earBaseL: hl(earB),
106
- earTipL: hl(earTip(params, earB)),
107
- // udder (ewes) / scrotum (rams): its own rigid bone below the pelvis, so it can fold up out of the
108
- // ground when the sheep lies down (hooks.pose)
109
- udderTop: [0, 0.4, -0.3],
110
- udderBot: [0, 0.27, -0.29],
111
- };
112
- const T = tailSpec(params);
113
- tailChain(J, 'tailBase', T.pitch, T.lens);
114
- return J;
115
- }
116
-
117
- export function sheepBones() {
118
- const b = quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true });
119
- for (const d of b) {
120
- if (d[0] === 'fpaw{S}') { d[2] = 'fcoffin{S}'; d[4] = { region: 'limb', group: 'F{S}' }; }
121
- if (d[0] === 'hpaw{S}') { d[2] = 'hcoffin{S}'; d[4] = { region: 'limb', group: 'H{S}' }; }
122
- }
123
- b.push(['udder', 'udderTop', 'udderBot', 'pelvis', { region: 'torso', group: 'udder' }]);
124
- b.push(
125
- ['fhoof{S}', 'fcoffin{S}', 'ftoe{S}', 'fpaw{S}', { region: 'foot', group: 'F{S}' }],
126
- ['hhoof{S}', 'hcoffin{S}', 'htoe{S}', 'hpaw{S}', { region: 'foot', group: 'H{S}' }],
127
- );
128
- return b;
129
- }
130
-
131
- export function sheepRig(params = {}, J = sheepJoints(params)) {
132
- const limbs = quadrupedLimbs({
133
- front: { tCore: 0.5, aCore: 0.05, aBody: -0.15, midX: 0.0 },
134
- hind: { tCore: 0.45, aCore: 0.022, aBody: -0.2, midX: 0.008 },
135
- });
136
- 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); }
137
- return buildRig({
138
- joints: J,
139
- unit: 0.92,
140
- headOrigin: HEAD_O,
141
- bones: sheepBones(),
142
- axial: {
143
- points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
144
- bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
145
- // the skull's influence reaches back into the throat (widening with the depth below the axis)
146
- blend: { 1: [-0.01, 0.17, 7], 2: [-0.19, 0.22, 0], 3: [-0.22, 0.17, 0] },
147
- bodyTail: 0, // (the britch wool does not blend into the tail: it tore when the thighs folded to lie down)
148
- // (core weights.js `cascade`: the occiput's throat lever reaches past the mid-neck joint, where the default
149
- // chain weighting cut the skull's share from 0.2-0.4 to 0 within 2 cm of coarse neck: the neck wool creased
150
- // along that line, a jagged crack, whenever the head dropped or turned. It now fades out over the 7 cm past
151
- // the joint. Not in the Merino: the fade stretches the neck wool a little more when grazing and sleeping
152
- // (pattern edges > 1.5x 29.8 -> 31.0 % of 30), and its crease is left to the shells' depth bias, index.js)
153
- cascade: params.variant === 'merino' ? false : { 1: 0.07 },
154
- },
155
- limbs,
156
- appendages: [
157
- { group: 'earL', bone: 'earL', blend: [-0.002, 0.004] },
158
- { group: 'earR', bone: 'earR', blend: [-0.002, 0.004] },
159
- { group: 'udder', bone: 'udder', blend: [-0.004, 0.02] },
160
- ],
161
- webTags: ['flankfold', 'thighfront', 'scapmuscle', 'pectoral', 'forearmweb', 'woolarm', 'woolthigh', 'woolweb'],
162
- });
163
- }