@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,285 +0,0 @@
1
- // The rabbit's coat: dense soft agouti fur (banded hair tips), countershading to a white belly, the
2
- // rufous nape patch, pale eye rings, dark-rimmed ears with thinly furred pink insides, the scut
3
- // (dark on top, white underneath), furred feet; domestic colours as seeded variants (fawn, black,
4
- // white / REW albino, Dutch pied pattern grown as a signed distance on the surface).
5
- // Works in the reference space of rig.js; colours sampled from the reference photos.
6
- import { HEAD_O } from './rig.js';
7
- import { neckS } from './regions.js';
8
- import { SDFModel } from '../../core/sdf/sdf.js';
9
- import { norm, sub, dot, cross, len, add, mul, smoothstep, clamp, mix, fbm3 } from '../../core/math/vec.js';
10
- import { srgb, mix3, MAT } from '../../core/build/coatKit.js';
11
-
12
- // palette per colour variant (sRGB hex from reference photos)
13
- const PALETTES = {
14
- agouti: {
15
- back: 0x7d6c56, flank: 0x8d7a62, low: 0xa4907a, nape: 0x9c6a42, face: 0x937c5e, cheek: 0x9c8a6c,
16
- eyeRing: 0xcfc2a6, earOut: 0x8a7a64, earRim: 0x3b3024, earIn: 0xc9a193, chest: 0x9a7e5c,
17
- belly: 0xe8e2d6, tailTop: 0x3e342a, tailUnder: 0xf4f2ee, feet: 0xa8977e, nose: 0x8e6e62, claw: 0x6a5c50,
18
- agouti: 1.0, undercoat: 0.6,
19
- },
20
- fawn: {
21
- back: 0xc08a4c, flank: 0xc8955a, low: 0xd6a86c, nape: 0xd49a58, face: 0xcc975c, cheek: 0xd2a066,
22
- eyeRing: 0xe8d0a4, earOut: 0xbc8850, earRim: 0x8a5e32, earIn: 0xd8a898, chest: 0xd4a46a,
23
- belly: 0xf0e2c8, tailTop: 0xb07a40, tailUnder: 0xf4ecdc, feet: 0xe0c090, nose: 0xc89486, claw: 0xd8ccbc,
24
- agouti: 0.15, undercoat: 0.35,
25
- },
26
- black: {
27
- back: 0x2c2826, flank: 0x302b28, low: 0x39332f, nape: 0x2f2926, face: 0x302b28, cheek: 0x332d2a,
28
- eyeRing: 0x39332f, earOut: 0x2c2826, earRim: 0x1c1918, earIn: 0x7a6260, chest: 0x302b28,
29
- belly: 0x3e3733, tailTop: 0x1a1817, tailUnder: 0x2c2724, feet: 0x2a2522, nose: 0x3a2e2c, claw: 0x2a2624,
30
- agouti: 0.0, undercoat: 0.2,
31
- },
32
- white: {
33
- back: 0xece8e0, flank: 0xeeeae2, low: 0xf0ece4, nape: 0xece8e0, face: 0xeeeae2, cheek: 0xf0ece6,
34
- eyeRing: 0xf2eee8, earOut: 0xe8e2da, earRim: 0xe4dcd2, earIn: 0xe8b8b0, chest: 0xf0ece4,
35
- belly: 0xf4f2ee, tailTop: 0xeeeae2, tailUnder: 0xf6f4f0, feet: 0xf0ece4, nose: 0xd8a0a0, claw: 0xece4da,
36
- agouti: 0.0, undercoat: 0.1,
37
- },
38
- };
39
- // Dutch: the coloured parts (cheeks, ears, rear half) take the chosen base; white elsewhere
40
- const DUTCH_WHITE = 0xf2f0ea;
41
-
42
- function coatColours(p) {
43
- const base = PALETTES[p.colour || 'agouti'] || PALETTES.agouti;
44
- const k = p.coatWarmth || 0, l = p.coatLightness || 0;
45
- const tweak = (h) => { const c = srgb(h); return [c[0] * (1 + 0.16 * k + l), c[1] * (1 + 0.04 * k + l), c[2] * (1 - 0.16 * k + l)]; };
46
- const C = {};
47
- for (const [key, v] of Object.entries(base)) C[key] = typeof v === 'number' && key !== 'agouti' && key !== 'undercoat' ? (['belly', 'tailUnder', 'earIn', 'nose', 'claw'].includes(key) ? srgb(v) : tweak(v)) : v;
48
- return C;
49
- }
50
-
51
- export function rabbitCoat(ctx) {
52
- const { model, rig, pos, nrm, regionOf: partOf, weights, nV, params } = ctx;
53
- const { BONES, AXIAL } = rig;
54
- const COL = coatColours(params);
55
- const { dominant, axialS, skinIndex, skinWeight, limbMember } = weights;
56
- const AX = weights.axialLengths;
57
- const P = (v) => [pos[v * 3], pos[v * 3 + 1], pos[v * 3 + 2]];
58
- const N = (v) => [nrm[v * 3], nrm[v * 3 + 1], nrm[v * 3 + 2]];
59
- const sOcc = AX[1], sNeckBase = AX[3], sTailBase = AX[8];
60
- const isLimb = BONES.map((b) => /^(scapula|humerus|radius|metacarpus|fpaw|femur|tibia|metatarsus|hpaw)/.test(b.name));
61
- const isFoot = BONES.map((b) => /^(fpaw|hpaw|metacarpus)/.test(b.name));
62
- const isHindFoot = BONES.map((b) => /^(hpaw|metatarsus)/.test(b.name));
63
- const eyePrims = model.prims.filter((p) => p.tag === 'eyesocket');
64
- const nosePrim = model.prims.find((p) => p.tag === 'nose');
65
- const cleftPrim = model.prims.find((p) => p.tag === 'lipcleft');
66
- const earPrims = model.prims.filter((p) => p.tag === 'ear');
67
- const jawPrims = model.forPart('jaw');
68
- const headPrims = model.forPart('body').filter((p) => (p.bone === 'head' || p.bone === 'snout') && !p.carve);
69
- const dutch = !!params.dutch;
70
- const albino = params.colour === 'white';
71
-
72
- const region = new Uint8Array(nV); // 0 torso, 1 neck, 2 head, 4 tail, 5 ear, 6 jaw, 7 snout
73
- const legness = new Float32Array(nV);
74
- const legBone = new Int16Array(nV).fill(-1);
75
- for (let v = 0; v < nV; v++) {
76
- const bn = BONES[dominant[v]].name;
77
- const p = P(v);
78
- let lb = -1, lw = 0;
79
- for (let k = 0; k < 4; k++) {
80
- const b = skinIndex[v * 4 + k], w = skinWeight[v * 4 + k];
81
- if (isLimb[b] && w > lw) { lw = w; lb = b; }
82
- }
83
- legBone[v] = lb;
84
- legness[v] = lb >= 0 ? smoothstep(0.15, 0.85, limbMember[v]) : 0;
85
- if (partOf[v] === 2) region[v] = 6;
86
- else if (bn.startsWith('ear')) region[v] = 5;
87
- else if (bn === 'snout') region[v] = 7;
88
- else if (axialS[v] > sTailBase + 0.004 && bn.startsWith('tail')) region[v] = 4;
89
- else if (axialS[v] < sOcc + 0.004 || (partOf[v] === 1 && neckS(p[0], p[1], p[2]) > 0.01)) region[v] = 2;
90
- else if (axialS[v] < sNeckBase) region[v] = 1;
91
- else region[v] = 0;
92
- if (region[v] === 2 || region[v] >= 4) legness[v] = 0;
93
- }
94
-
95
- // Dutch pattern: signed distance (m, < 0 = white) of the white areas: blaze and muzzle, a collar
96
- // and the whole forequarters (the "saddle" line behind the shoulders), and the hind feet ("stops")
97
- const dutchSDF = (p, r, v) => {
98
- const h = sub(p, HEAD_O);
99
- if (r === 5 || r === 4) return 1; // ears and scut stay coloured
100
- if (r === 2 || r === 6 || r === 7) {
101
- // blaze: a wedge between the eyes widening to the muzzle; muzzle, lips, chin and throat white
102
- const blaze = Math.abs(h[0]) - (0.003 + 0.3 * Math.max(0, h[2] + 0.004));
103
- return Math.min(blaze, 0.024 - h[2], h[1] + 0.027);
104
- }
105
- // saddle line behind the shoulders, slanting back low on the body
106
- let d = (-0.02 - 0.25 * (0.12 - p[1]) + 0.003 * Math.sin(p[0] * 70)) - p[2];
107
- // hind feet: white "stops" from the toes to about mid-foot
108
- if (legBone[v] >= 0 && isHindFoot[legBone[v]]) d = Math.min(d, -0.072 - p[2]);
109
- return d;
110
- };
111
-
112
- const comb = new Float32Array(nV * 3);
113
- const tint = new Float32Array(nV * 4);
114
- const furLen = new Float32Array(nV);
115
- const markSDF = new Float32Array(nV).fill(1);
116
- const pattern = new Float32Array(nV).fill(1);
117
- const patternColor = new Float32Array(nV * 4);
118
- const surf = new Float32Array(nV * 4);
119
- const white = srgb(DUTCH_WHITE);
120
-
121
- for (let v = 0; v < nV; v++) {
122
- const p = P(v), n = N(v), r = region[v];
123
- const h = sub(p, HEAD_O);
124
- const bone = BONES[dominant[v]];
125
- const L = legness[v];
126
- let col, fl, mat = MAT.FUR, mark = 1, ag = COL.agouti, uc = COL.undercoat;
127
-
128
- // ---- comb
129
- let d;
130
- if (r === 5) d = norm(sub(bone.tail, bone.head));
131
- else if (r === 2 || r === 6 || r === 7) d = norm(add(norm(sub(h, [0, -0.018, 0.05])), [0, -0.1, -0.5]));
132
- else if (r === 4) d = norm(add(norm(sub(bone.tail, bone.head)), [0, 0.3, -0.3]));
133
- else {
134
- const seg = weights.segT[v * 2] | 0;
135
- const a = AXIAL.points[seg], b = AXIAL.points[Math.min(seg + 1, AXIAL.points.length - 1)];
136
- d = norm(add(norm(sub(b, a)), [0, -0.45 * Math.abs(n[0]), 0]));
137
- if (L > 0 && legBone[v] >= 0) {
138
- const lbn = BONES[legBone[v]];
139
- let dl = norm(sub(lbn.tail, lbn.head));
140
- if (/fpaw|hpaw|metatarsus/.test(lbn.name)) dl = norm(add(dl, [0, 0, 0.5]));
141
- else dl = norm(add(dl, [0, -0.3, -0.2]));
142
- d = norm(add(mul(d, 1 - L), mul(dl, L)));
143
- }
144
- }
145
- let t = sub(d, mul(n, dot(d, n)));
146
- if (len(t) < 1e-4) t = cross(n, [1, 0, 0]);
147
- t = norm(t);
148
- comb[v * 3] = t[0]; comb[v * 3 + 1] = t[1]; comb[v * 3 + 2] = t[2];
149
-
150
- // ---- colour, fur length, marks
151
- if (r === 0 || r === 1) {
152
- const up = clamp(n[1], -1, 1);
153
- col = mix3(COL.low, COL.flank, smoothstep(-0.3, 0.3, up));
154
- col = mix3(col, COL.back, smoothstep(0.3, 0.9, up));
155
- // rufous nape patch behind the ears
156
- col = mix3(col, COL.nape, smoothstep(0.2, 0.7, up) * (r === 1 ? 1 : smoothstep(0.06, 0.085, p[2])) * 0.8);
157
- // chest: buff, belly: white (countershading blended by normal and height)
158
- const ventral = smoothstep(-0.1, -0.6, n[1]) * smoothstep(0.14, 0.07, p[1]);
159
- const chest = smoothstep(0.03, 0.08, p[2]) * smoothstep(0.1, 0.5, n[2]) * smoothstep(0.15, 0.08, p[1]);
160
- col = mix3(col, COL.chest, chest * 0.8);
161
- col = mix3(col, COL.belly, Math.max(ventral, smoothstep(0.35, 0.8, -n[1])));
162
- fl = mix(0.0105, 0.012, smoothstep(0.3, -0.6, n[1]));
163
- fl = Math.max(fl, 0.012 * smoothstep(0.6, 0.95, n[1])); // dense back
164
- // rump fur a touch longer (the rounded loaf outline)
165
- if (p[2] < -0.1) fl += 0.002 * smoothstep(-0.1, -0.16, p[2]);
166
- ag *= 1 - smoothstep(0.2, 0.7, -n[1]);
167
- if (L > 0) {
168
- let lc = mix3(COL.flank, COL.belly, smoothstep(0.0, -0.8, n[0] * Math.sign(p[0] || 1)) * 0.7);
169
- const lb = legBone[v] >= 0 ? BONES[legBone[v]].name : '';
170
- let lf = mix(0.005, 0.0105, smoothstep(0.02, 0.1, p[1]));
171
- if (/fpaw|hpaw|metacarpus|metatarsus/.test(lb)) { lc = mix3(mix3(COL.feet, COL.flank, 0.35), COL.belly, smoothstep(0.0, -0.7, n[1]) * 0.4); lf = 0.006; }
172
- else if (/radius/.test(lb)) { lc = mix3(COL.feet, COL.flank, 0.5); lf = 0.005; }
173
- // the big haunch keeps the body colour on its outside
174
- if (/femur/.test(lb)) { lc = mix3(col, lc, smoothstep(0.08, 0.03, p[1])); lf = mix(fl, lf, 0.4); }
175
- col = mix3(col, lc, L);
176
- fl = mix(fl, lf, L);
177
- ag *= 1 - 0.6 * L * (/fpaw|hpaw|metacarpus|metatarsus|radius/.test(lb) ? 1 : 0);
178
- }
179
- } else if (r === 4) {
180
- // the scut: dark on top (the side facing out at rest), bright white underneath
181
- const bb = BONES[dominant[v]];
182
- const ax = norm(sub(bb.tail, bb.head));
183
- // "top" of the tail = its dorsal side (toward the back when curled down against the rump)
184
- const dorsal = norm(cross([1, 0, 0], ax));
185
- const top = dot(n, dorsal);
186
- col = mix3(COL.tailUnder, COL.tailTop, smoothstep(-0.1, 0.45, -top));
187
- fl = 0.016;
188
- ag *= 0.3;
189
- } else if (r === 5) {
190
- // ears: short fur outside with a dark rim, sparse hair on the pink inner skin
191
- const side = p[0] >= 0 ? 0 : 1;
192
- const ep = earPrims[side];
193
- const face = [ep.P[9], ep.P[10], ep.P[11]];
194
- const upE = [ep.P[6], ep.P[7], ep.P[8]], latE = [ep.P[3], ep.P[4], ep.P[5]];
195
- const c = [ep.P[0], ep.P[1], ep.P[2]];
196
- const q = sub(p, c);
197
- const along = dot(q, upE) / ep.P[13], across = dot(q, latE) / ep.P[12];
198
- const rim = 1 - Math.hypot(along, across); // 0 at the edge of the pinna
199
- const front = dot(n, face) * Math.sign(dot(face, [p[0] >= 0 ? 1 : -1, 0, 0]) || 1);
200
- const inner = smoothstep(0.1, 0.5, dot(n, face)) * smoothstep(0.02, 0.12, rim);
201
- col = mix3(COL.earOut, COL.earIn, inner);
202
- fl = mix(0.0022, 0.0009, inner);
203
- if (inner > 0.6) mat = albino || params.colour === 'black' ? MAT.FUR : MAT.FUR;
204
- // dark rim along the outer edge and the tip (wild / agouti)
205
- // a thin dark rim along the upper edge and around the tip only (not at the root)
206
- if (along > 0.1) mark = Math.min(mark, (rim - 0.035) * 0.03 + 0.003 * (1 - smoothstep(0.1, 0.6, along)));
207
- if (params.colour !== 'agouti') mark = 1;
208
- ag *= 0.5 * (1 - inner);
209
- void front;
210
- } else {
211
- // head, snout and jaw
212
- col = COL.face;
213
- const g3 = (cc, rr) => Math.exp(-(((Math.abs(h[0]) - cc[0]) / rr[0]) ** 2 + ((h[1] - cc[1]) / rr[1]) ** 2 + ((h[2] - cc[2]) / rr[2]) ** 2));
214
- col = mix3(col, COL.cheek, g3([0.017, -0.02, -0.005], [0.01, 0.012, 0.02]));
215
- // pale eye ring (the "spectacles") and pale lips / chin
216
- let ring = 0;
217
- for (const e of eyePrims) {
218
- const de = SDFModel.dist(e, p[0], p[1], p[2]);
219
- ring = Math.max(ring, smoothstep(0.0055, 0.0015, Math.abs(de)));
220
- }
221
- col = mix3(col, COL.eyeRing, ring * 0.6);
222
- const lips = g3([0.006, -0.03, 0.036], [0.009, 0.006, 0.014]);
223
- const chinW = r === 6 ? 0.9 : smoothstep(-0.028, -0.036, h[1]) * smoothstep(-0.2, -0.7, n[1]);
224
- col = mix3(col, COL.belly, clamp(Math.max(lips * 0.7, chinW), 0, 1));
225
- // nape colour at the back of the head
226
- col = mix3(col, COL.nape, smoothstep(-0.02, -0.04, h[2]) * smoothstep(0.0, 0.6, n[1]) * 0.6);
227
- fl = mix(0.0045, 0.0028, smoothstep(0.0, 0.035, h[2]));
228
- if (Math.abs(h[0]) > 0.016 && h[1] < -0.005) fl = Math.max(fl, 0.0055); // cheek fur
229
- ag *= 0.7;
230
- // eye rims: dark bare lid margin
231
- for (const e of eyePrims) {
232
- const de = SDFModel.dist(e, p[0], p[1], p[2]);
233
- if (Math.abs(de) < 0.0022) mark = Math.min(mark, Math.abs(de) - 0.0009);
234
- if (Math.abs(de) < 0.0009) { mat = MAT.DARK_SKIN; fl = 0; }
235
- else if (Math.abs(de) < 0.0025) fl = Math.min(fl, 0.001);
236
- }
237
- // nose leather (small, Y-shaped with the lip cleft) and the cleft itself
238
- if (nosePrim && SDFModel.dist(nosePrim, p[0], p[1], p[2]) < 0.0009 && h[2] > 0.0355 && h[1] > -0.024) { mat = MAT.NOSE; col = COL.nose; fl = 0; }
239
- if (cleftPrim) {
240
- const dc = SDFModel.dist(cleftPrim, p[0], p[1], p[2]);
241
- if (dc < 0.0012) { mark = Math.min(mark, dc - 0.0008); fl = Math.min(fl, 0.0008); }
242
- }
243
- // whisker pads: short dense fur
244
- if (r === 7) fl = Math.min(fl, 0.0032);
245
- // lips: head vertices touching the jaw surface, jaw vertices touching the head
246
- if (partOf[v] !== 2) {
247
- const dj = SDFModel.evalList(jawPrims, p[0], p[1], p[2]);
248
- if (dj < 0.0006) { mat = MAT.MOUTH; col = [0.3, 0.12, 0.12]; fl = 0; }
249
- } else {
250
- const dh = SDFModel.evalList(headPrims, p[0], p[1], p[2]);
251
- if (dh < 0.0) { mat = MAT.MOUTH; col = [0.3, 0.12, 0.12]; fl = 0; }
252
- }
253
- }
254
-
255
- // ---- Dutch white areas (pattern SDF, crisp but hair-ragged edges)
256
- if (dutch) {
257
- pattern[v] = dutchSDF(p, r, v);
258
- }
259
-
260
- // low-frequency colour variation
261
- const cv = fbm3(p[0] * 40, p[1] * 40, p[2] * 40, 3) - 0.5;
262
- col = [col[0] * (1 + 0.14 * cv), col[1] * (1 + 0.12 * cv), col[2] * (1 + 0.09 * cv)];
263
-
264
- tint[v * 4] = col[0]; tint[v * 4 + 1] = col[1]; tint[v * 4 + 2] = col[2]; tint[v * 4 + 3] = mat;
265
- furLen[v] = mat === MAT.FUR ? fl : 0;
266
- markSDF[v] = mark;
267
- patternColor[v * 4] = white[0]; patternColor[v * 4 + 1] = white[1]; patternColor[v * 4 + 2] = white[2]; patternColor[v * 4 + 3] = dutch ? 1 : 0;
268
- surf[v * 4] = 0; surf[v * 4 + 1] = 0; surf[v * 4 + 2] = clamp(ag, 0, 1); surf[v * 4 + 3] = uc;
269
- }
270
-
271
- // smooth fur length so shells do not step
272
- const nb = weights.neighbors;
273
- const tmp = new Float32Array(nV);
274
- for (let it = 0; it < 2; it++) {
275
- for (let v = 0; v < nV; v++) {
276
- const ns = nb[v];
277
- if (!ns.length || tint[v * 4 + 3] > 0) { tmp[v] = furLen[v]; continue; }
278
- let a = 0;
279
- for (const q of ns) a += furLen[q];
280
- tmp[v] = 0.5 * furLen[v] + (0.5 * a) / ns.length;
281
- }
282
- furLen.set(tmp);
283
- }
284
- return { comb, tint, pattern, mark: markSDF, furLen, patternColor, surf, region };
285
- }
@@ -1,85 +0,0 @@
1
- // European rabbit (Oryctolagus cuniculus): the wild agouti rabbit plus the common domestic colours.
2
- // The body plan proves the hopping path of the quadruped engine: long hind legs, feet flat at rest
3
- // and on the toes in motion, half-bound and bound gaits with the hind feet landing together, a
4
- // crouched resting stance, and rabbit behaviours (hop, nose twitch, ear swivels, grooming,
5
- // periscope, thumping, binky, zig-zag escape, grazing, boxing).
6
- import { rabbitRig, HEAD_O } from './rig.js';
7
- import { sculptRabbit, EYE } from './sculpt.js';
8
- import { rabbitRegions } from './regions.js';
9
- import { rabbitCoat } from './coat.js';
10
- import { motion } from './motion.js';
11
-
12
- // Seeded individual.
13
- // variant: 'wild' (default: agouti, the European rabbit), 'domestic' (random domestic colour),
14
- // 'agouti-domestic', 'fawn', 'black', 'white' (REW albino), 'dutch' (pied), 'lop'
15
- // age: 'adult' | 'juvenile' (a kit ~4-6 weeks: round head, short ears, big eyes and feet)
16
- function variation(R, o) {
17
- const sex = o.sex || (R() < 0.5 ? 'male' : 'female');
18
- const age = o.age || 'adult';
19
- const juv = age === 'juvenile';
20
- const g = () => (R() + R() + R() - 1.5) / 1.5; // ~[-1, 1], peaked
21
- const u = () => 2 * R() - 1; // uniform [-1, 1]
22
- let variant = o.variant || 'wild';
23
- if (variant === 'domestic') variant = ['agouti-domestic', 'fawn', 'black', 'white', 'dutch', 'lop'][Math.floor(R() * 6)];
24
- const domestic = variant !== 'wild';
25
- const lop = variant === 'lop';
26
- // colour: wild and agouti-domestic are agouti; lops come in any colour
27
- let colour = { wild: 'agouti', 'agouti-domestic': 'agouti', fawn: 'fawn', black: 'black', white: 'white', dutch: R() < 0.6 ? 'black' : 'agouti', lop: ['agouti', 'fawn', 'black', 'white'][Math.floor(R() * 4)] }[variant] || 'agouti';
28
- // size: wild 1.5-2.2 kg (length ~ mass^1/3); domestic breeds 1-3.5 kg; kits ~0.2-0.4 kg
29
- let size = (domestic ? 1.06 + 0.08 * g() : 1 + 0.07 * u()) * (sex === 'male' ? 1.01 : 0.99);
30
- if (juv) size *= 0.58;
31
- const earLen = (domestic ? 0.92 : 1) * (1 + 0.07 * g()) * (juv ? 0.78 : 1);
32
- return {
33
- sex, age, size, variant, colour, domestic, lop,
34
- dutch: variant === 'dutch',
35
- earLen,
36
- earWidth: (lop ? 1.25 : 1) * (1 + 0.05 * g()),
37
- headWidth: (domestic ? 1.06 : 1) * (sex === 'male' ? 1.03 : 1) * (juv ? 1.06 : 1),
38
- minThick: 0.0011,
39
- warps: [
40
- { type: 'legs', k: 1 + 0.04 * g() - (juv ? 0.04 : 0), top: 0.08 },
41
- { type: 'length', k: 1 + 0.03 * g() - (domestic ? 0.03 : 0) - (juv ? 0.06 : 0), z0: -0.12, z1: 0.07 },
42
- { type: 'girth', k: 1 + 0.06 * g() + (domestic ? 0.05 : 0), cy: 0.12, z0: -0.15, z1: 0.1 },
43
- { type: 'scaleAbout', c: HEAD_O, k: (sex === 'male' ? 1.02 : 0.99) * (1 + 0.02 * g()) * (juv ? 1.2 : 1) * (domestic ? 1.03 : 1), r0: 0.035, r1: 0.075 },
44
- ],
45
- coatWarmth: 1.1 * u(),
46
- coatLightness: 0.12 * u(),
47
- coatSeed: Math.floor(R() * 1e6),
48
- };
49
- }
50
-
51
- export default {
52
- id: 'rabbit',
53
- name: 'European rabbit',
54
- latin: 'Oryctolagus cuniculus',
55
- group: 'paws',
56
- plan: 'quadruped',
57
- covering: 'fur',
58
- variation,
59
- rig: (params) => rabbitRig(params),
60
- sculpt: (m, rig, params) => sculptRabbit(m, rig, params),
61
- regions: rabbitRegions,
62
- coat: rabbitCoat,
63
- eyeSpecs: (params) => [1, -1].map((side) => ({ side, spec: EYE, headOrigin: HEAD_O, bone: 'head', look: params.colour === 'white' ? EYE_ALBINO : EYE_LOOK })),
64
- motion,
65
- render: { markColor: [0.018, 0.014, 0.011], strandDensity: 1500, clumpDensity: 1.2, shellScale: 1, finWidth: 0.45 },
66
- };
67
-
68
- // Round pupil in a dark brown iris that fills the whole opening (no sclera shows).
69
- export const EYE_LOOK = {
70
- pupil: 'round',
71
- lids: 'mammal',
72
- iris: { inner: [0.02, 0.011, 0.006], mid: [0.045, 0.024, 0.012], hi: [0.1, 0.06, 0.03], outer: [0.012, 0.007, 0.004] },
73
- sclera: { color: [0.03, 0.02, 0.015], visible: false },
74
- lidColor: [0.05, 0.035, 0.028],
75
- pupilSize: [0.45, 0.62],
76
- };
77
- // REW albino: pale pink iris, red pupil (the fundus shows through)
78
- export const EYE_ALBINO = {
79
- pupil: 'round',
80
- lids: 'mammal',
81
- iris: { inner: [0.55, 0.12, 0.14], mid: [0.75, 0.42, 0.44], hi: [0.9, 0.6, 0.6], outer: [0.6, 0.3, 0.32] },
82
- sclera: { color: [0.6, 0.35, 0.35], visible: false },
83
- lidColor: [0.75, 0.5, 0.48],
84
- pupilSize: [0.35, 0.5],
85
- };
@@ -1,85 +0,0 @@
1
- // Rabbit motion data for the quadruped engine (schema: src/core/motion/quadruped.js).
2
- // Numbers are for the reference individual (params.size = 1, wild adult ~1.8 kg, hip height when
3
- // hopping ~0.15 m); the engine scales them by dynamic similarity for kits and big domestic breeds.
4
- //
5
- // Gaits (Hall et al. 2022, Kraatz et al. 2021, Heglund et al. 1974): rabbits
6
- // almost never walk. Grazing "shuffle" (hop-step: forefeet one after the other, both hind feet
7
- // slide forward together), half-bound (forefeet land one after the other, the hind feet land
8
- // TOGETHER beside / ahead of the forefeet) and the bound-like escape half-bound with a long
9
- // extended suspension. Offsets [FL, FR, HL, HR] relative to hind touchdown; HL = HR (feet together).
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
- // engine constants scale with the leg length relative to the cheetah's (0.234 m / 0.774 m)
16
- unit: 0.3,
17
- maxSpeed: 8,
18
- // (a hopper: its bound already folds the hind legs deep, and its hops carry their own bounce: the
19
- // engine's moving crouch, stride roll and variation jittered the hocks and wrists, and sitting back
20
- // on its haunches to brake pressed its long flat hind feet into the ground)
21
- moveCrouch: 0, stride: { bob: 1, bobSpring: true, roll: 0, vary: 0, brake: 0, gallop: 0 },
22
- accel: [9, 16],
23
- decel: 14,
24
- turnRate: 5.5,
25
- latAccelMax: 22,
26
- gears: { shuffle: 0.25, halfbound: 1.2, bound: 3.5 },
27
- gallopBlend: [1.2, 4],
28
- // the back flexes and extends in every hop, not only at a gallop
29
- flexBlend: [0.3, 1.5],
30
- hooks,
31
- gaits: [
32
- G('shuffle', 0.0, 1.3, 0.74, [0.44, 0.6, 0.0, 0.0], { liftF: 0.018, liftH: 0.02, bobF: 0.004, bobH: 0.01, flex: 0.04, lat: 0, fold: -0.2, heel: 10, tail: 0.1, drop: 0 }),
33
- G('shuffle', 0.35, 1.7, 0.62, [0.46, 0.6, 0.0, 0.0], { liftF: 0.024, liftH: 0.028, bobF: 0.006, bobH: 0.016, flex: 0.06, lat: 0, fold: -0.2, heel: 14, tail: 0.2, drop: 0 }),
34
- G('halfbound', 0.7, 2.2, 0.34, [0.5, 0.62, 0.0, 0.0], { liftF: 0.035, liftH: 0.045, bobF: 0.012, bobH: 0.02, flex: 0.1, lat: 0, fold: -0.2, heel: 18, tail: 0.4, drop: -0.012 }),
35
- G('halfbound', 1.8, 2.8, 0.26, [0.46, 0.58, 0.0, 0.0], { liftF: 0.045, liftH: 0.055, bobF: 0.016, bobH: 0.024, flex: 0.13, lat: 0, fold: -0.2, heel: 22, tail: 0.6, drop: -0.02 }),
36
- G('bound', 3.2, 3.4, 0.2, [0.44, 0.54, 0.0, 0.0], { liftF: 0.055, liftH: 0.06, bobF: 0.018, bobH: 0.026, flex: 0.17, lat: 0, fold: -0.2, heel: 25, tail: 0.85, drop: -0.022 }),
37
- G('bound', 6.5, 4.0, 0.16, [0.42, 0.52, 0.0, 0.0], { liftF: 0.06, liftH: 0.065, bobF: 0.02, bobH: 0.028, flex: 0.2, lat: 0, fold: -0.2, heel: 25, tail: 1, drop: -0.024 }),
38
- G('bound', 10, 4.4, 0.14, [0.42, 0.52, 0.0, 0.0], { liftF: 0.065, liftH: 0.07, bobF: 0.02, bobH: 0.03, flex: 0.22, lat: 0, fold: -0.2, heel: 25, tail: 1, drop: -0.026 }),
39
- ],
40
- feet: {
41
- // short forelegs: land close in front of the shoulder and lift early (limits / leg length)
42
- front: { type: 'digitigrade', curl: 50, contact: 0.5, flex: 4, lead: 0.15, liftBehind: 0.8, retract: 0.8, elbowDown: 0.4 },
43
- // flat on the ground at rest (bind), on the toes in motion (the pantograph lifts the heel)
44
- hind: { type: 'digitigrade', curl: 40, contact: 0.55, retract: 0.8, liftBehind: 0.25, plantRest: true, restTilt: 6 },
45
- },
46
- stance: { width: 1, gallopWidth: 0.85, sprawl: 0, crouch: 0, scuff: [6, 12, 0] },
47
- body: {
48
- // (sections of the half-extended bind sculpt: brisket bottom ~47 mm, belly ~35 mm, rump ~60 mm)
49
- chest: { y: 0.105, hh: 0.068, hw: 0.053 },
50
- pelvis: { y: 0.11, hh: 0.05, hw: 0.075 },
51
- mid: { y: 0.095, hh: 0.06, hw: 0.07 },
52
- back: 0.045,
53
- },
54
- head: {
55
- // [speed, raise (m), reach (m), pitch (rad, + = nose down)]
56
- carriage: [[0, 0, 0, 0], [0.7, -0.008, 0.006, 0.08], [3, -0.015, 0.012, 0.12], [8, -0.02, 0.018, 0.15]],
57
- stab: [[0, 0], [0.5, 0.15], [1.5, 0.2], [4, 0.25], [8, 0.3]],
58
- // a rabbit sees almost all round: it turns its head little (the skin of the short neck is
59
- // stretched by every degree the skull turns on the atlas)
60
- neckBend: 40, neckPivot: 0.5, yaw: 0.55, pitchUp: 0.4, pitchDown: 0.5,
61
- },
62
- tail: {
63
- // the scut is pressed down against the rump at rest and flipped up at speed (white flag)
64
- carriage: [
65
- [0.0, [-12, -24, -36]],
66
- [0.7, [-10, -18, -26]],
67
- [2.5, [-8, 12, 35]],
68
- [5, [-2, 28, 60]],
69
- ],
70
- stiffness: 2.2, sway: 0, flick: 0.4, wag: 0, swish: 0, curl: 0, balance: 0,
71
- radius: [0.014, 0.012],
72
- },
73
- ears: { mobility: 0.7, speedFlatten: 0.9, flattenSpeeds: [1.5, 7], twitch: 1.5, prick: 0.6 },
74
- breath: { rate: 0.8, amp: 0.02, pant: false, heatSpeed: 8 },
75
- actions: {
76
- attack: { style: 'bite-lunge' },
77
- eat: { style: 'graze', dropF: 0.1, dropH: 0.0, pitch: 1.6 },
78
- drink: { dropF: 0.12, dropH: 0.0, pitch: 1.6 },
79
- jump: { height: 0.45, distance: 1.0 },
80
- idle: { shift: 0.35, restep: false },
81
- sit: {},
82
- lie: {},
83
- sleep: { style: 'curl' },
84
- },
85
- };
@@ -1,48 +0,0 @@
1
- // Meshing plan: body at 1.85 mm, head (with the thin ears) at 1.1 mm, overlapping across the upper
2
- // neck and cross-faded, eyelid patches at 0.45 mm, and the lower jaw as its own rigid surface.
3
- import { rabbitJoints, HEAD_O } from './rig.js';
4
- import { EYE } from './sculpt.js';
5
- import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
6
- import { lerp, norm, sub, smoothstep } from '../../core/math/vec.js';
7
-
8
- const J0 = rabbitJoints();
9
- export const NECK_CUT = (() => {
10
- const d = norm(sub(J0.occiput, J0.neckBase));
11
- const c = lerp(J0.neckMid, J0.occiput, 0.3);
12
- return { c, d, band: 0.004 };
13
- })();
14
- 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];
15
-
16
- export const EYE_PATCH = { R: 0.0135, B: 0.002, h: 0.00045, centres: [1, -1].map((s) => eyeFrameOf(EYE, HEAD_O, s).c) };
17
- export function eyePatchWeight(x, y, z) {
18
- let dmin = 1e9;
19
- for (const c of EYE_PATCH.centres) dmin = Math.min(dmin, Math.hypot(x - c[0], y - c[1], z - c[2]));
20
- return 1 - smoothstep(EYE_PATCH.R - EYE_PATCH.B, EYE_PATCH.R + EYE_PATCH.B, dmin);
21
- }
22
-
23
- export function rabbitRegions(rig, params, Q) {
24
- const B = NECK_CUT.band, r = Q.res;
25
- const patches = Q.eyePatches ? EYE_PATCH.centres.map((c) => ({ c, R: EYE_PATCH.R, B: EYE_PATCH.B, h: EYE_PATCH.h * Math.max(1, r) })) : [];
26
- const lop = !!params.lop;
27
- // lop ears hang below the neck cut: keep them in the finely meshed head region
28
- const sH = lop ? (x, y, z) => Math.max(neckS(x, y, z), Math.min(Math.abs(x) - 0.036, z - 0.1, 0.16 - y)) : neckS;
29
- return {
30
- jobs: [
31
- [{ name: 'body', part: 'body', bmin: [-0.1, -0.012, -0.2], bmax: [0.1, 0.23, 0.15], h: 0.00185 * r, F: 4, clip: (x, y, z) => sH(x, y, z) < B }],
32
- [
33
- { name: 'head', part: 'body', bmin: [-0.075, lop ? 0.09 : 0.12, 0.07], bmax: [0.075, 0.345, 0.225], h: 0.0011 * r, F: 6, clip: (x, y, z) => sH(x, y, z) > -B, patches },
34
- { name: 'jaw', part: 'jaw', bmin: [-0.03, 0.15, 0.115], bmax: [0.03, 0.215, 0.2], h: 0.00105 * r, F: 6, rigidBone: 'jaw' },
35
- ],
36
- ],
37
- fade(x, y, z, name, patch) {
38
- const sN = sH(x, y, z);
39
- if (name === 'body') return 1 - smoothstep(-B, B, sN);
40
- if (name === 'head') {
41
- let f = smoothstep(-B, B, sN);
42
- if (patches.length) { const ew = eyePatchWeight(x, y, z); f *= patch ? ew : 1 - ew; }
43
- return f;
44
- }
45
- return 1;
46
- },
47
- };
48
- }
@@ -1,99 +0,0 @@
1
- // European rabbit (Oryctolagus cuniculus) skeleton in bind pose (metres). Forward = +Z, up = +Y,
2
- // the animal's left = +X.
3
- //
4
- // The bind pose stands with the hind legs half extended (see REAR_LIFT below); the rabbit's resting
5
- // crouch (the loaf: sitting on the haunches, forelegs upright, long hind feet flat on the ground) is
6
- // produced by the engine from it (behaviour.js). When the rabbit moves the hips rise and the heels
7
- // lift (the hind limb pantograph extends), so it hops on its toes.
8
- //
9
- // Wild adult ~1.8 kg, head-body 38 cm: femur 80 mm, tibia 92 mm, tarsus+metatarsus
10
- // 52 mm, hind digits 28 mm (hind foot heel -> claw ~88 mm); scapula 60 mm, humerus 59 mm, radius
11
- // 56 mm, metacarpus 22 mm; head 9 cm; ear 7.5-8.5 cm; tail (scut) ~5 cm.
12
- import { buildRig } from '../../core/rig/rig.js';
13
- import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
14
-
15
- export const TAIL_SEGS = 3;
16
- // head-local origin: on the midline at the height of the eye centres, level with them
17
- export const HEAD_O = [0, 0.219, 0.15];
18
-
19
- // ear pose per variant: erect (wild / most domestic) or lop (hanging beside the cheeks)
20
- export function earTip(params = {}) {
21
- if (params.lop) return [0.05, 0.15, 0.136];
22
- const e = params.earLen || 1;
23
- const base = [0.012, 0.238, 0.122];
24
- const d = [0.017 * e, 0.087 * e, -0.02 * e];
25
- return [base[0] + d[0], base[1] + d[1], base[2] + d[2]];
26
- }
27
-
28
- // The bind pose stands with the hind legs half extended (knee ~77 deg, hips up, back level): the
29
- // halfway point between the folded loaf and the extended push-off, so neither end of the hind
30
- // limb's range stretches the skin far. The rabbit's resting loaf is produced by the engine (the
31
- // hips are lowered at rest, behaviour.js). REAR_LIFT raises the rear of the body with the hips.
32
- export const REAR_LIFT = 0.037;
33
- export const rearW = (z) => { const t = Math.min(1, Math.max(0, (0.03 - z) / 0.12)); return t * t * (3 - 2 * t); };
34
- export const RL = (p) => [p[0], p[1] + REAR_LIFT * rearW(p[2]), p[2]];
35
-
36
- export function rabbitJoints(params = {}) {
37
- const J = {
38
- nose: [0, 0.2, 0.191],
39
- occiput: [0, 0.23, 0.115],
40
- neckMid: [0, 0.205, 0.097],
41
- neckBase: [0, 0.184, 0.076],
42
- chestMid: [0, 0.17, 0.05],
43
- thoraxRear: [0, 0.171, -0.003],
44
- lumbarMid: RL([0, 0.163, -0.052]),
45
- lumbosacral: RL([0, 0.135, -0.092]),
46
- tailBase: RL([0, 0.084, -0.146]),
47
- // forelimb: upright, the elbow tucked against the lower chest
48
- scapTopL: [0.024, 0.178, 0.058],
49
- shoulderL: [0.036, 0.126, 0.1],
50
- elbowL: [0.05, 0.076, 0.064],
51
- wristL: [0.045, 0.022, 0.079],
52
- mcpL: [0.043, 0.0075, 0.094],
53
- ftoeL: [0.043, 0.004, 0.111],
54
- // hind limb half extended: femur 76 mm, tibia 88 mm, knee ~77 deg, heel lifted 16.5 deg (the
55
- // femur's rotation between this pose and the loaf, so the hind-limb pantograph lands the foot
56
- // flat when the hips sit down); toes forward
57
- hipL: [0.031, 0.125, -0.086],
58
- kneeL: [0.05, 0.0762, -0.0277],
59
- hockL: [0.044, 0.0234, -0.0981],
60
- mtpL: [0.044, 0.0085, -0.048],
61
- htoeL: [0.043, 0.0045, -0.02],
62
- snoutBase: [0, 0.208, 0.174],
63
- jawHinge: [0, 0.206, 0.13],
64
- jawTip: [0, 0.185, 0.171],
65
- earBaseL: [0.012, 0.238, 0.122],
66
- earTipL: earTip(params),
67
- };
68
- // the scut: pressed down against the rump (dark upper side out, white underside hidden)
69
- tailChain(J, 'tailBase', [-12, -24, -36], [0.016, 0.016, 0.014]);
70
- return J;
71
- }
72
-
73
- export function rabbitRig(params = {}) {
74
- const J = rabbitJoints(params);
75
- return buildRig({
76
- joints: J,
77
- // characteristic length relative to the cheetah: shoulder height ~0.135 m / 0.76 m
78
- unit: 0.18,
79
- headOrigin: HEAD_O,
80
- bones: quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true, extra: [['snout', 'snoutBase', 'nose', 'head', { region: 'head', group: 'snout' }]] }),
81
- axial: {
82
- points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
83
- bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
84
- // the skull reaches back into the nape; the scut takes only its own tuft, not the rump
85
- blend: { 1: [-0.25, 0.3, 1.0], 2: [-0.12, 0.12], 8: [0.03, 0.09] },
86
- },
87
- limbs: quadrupedLimbs({
88
- front: { tCore: 0.9, aCore: 0.07, aBody: 0.05, midX: 0.0 },
89
- hind: params.hindField || { tCore: 1.0, aCore: 0.12, aBody: 0.1, midX: 0.01 },
90
- }),
91
- appendages: [
92
- { group: 'earL', bone: 'earL', blend: [-0.06, 0.08] },
93
- { group: 'earR', bone: 'earR', blend: [-0.06, 0.08] },
94
- { group: 'snout', bone: 'snout', blend: [-0.004, 0.01] },
95
- ],
96
- webTags: ['flankfold', 'thighfront', 'scapmuscle'],
97
- });
98
- }
99
-