@bitefoundry/retrieviewer 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/ASSET-PROVENANCE.md +6 -0
  2. package/ASSETS-LICENSE.md +2 -1
  3. package/ATTRIBUTION.md +6 -1
  4. package/COMFORT-ART.md +65 -0
  5. package/DESKTOP-PLATFORMS.md +75 -0
  6. package/INSTALLING.md +8 -5
  7. package/PLUGIN.md +13 -10
  8. package/PREREQUISITES.md +95 -0
  9. package/PUPPY-MEMORY.md +102 -1
  10. package/README.ko.md +110 -0
  11. package/README.md +119 -58
  12. package/RELEASING.md +27 -14
  13. package/THIRD-PARTY-NOTICES.md +5 -3
  14. package/braille.mjs +35 -9
  15. package/examples/live.mjs +2 -2
  16. package/integrations/desktop/platform.mjs +27 -0
  17. package/integrations/linux-overlay/README.md +83 -0
  18. package/integrations/linux-overlay/overlay.py +1094 -0
  19. package/integrations/macos-overlay/README.md +83 -0
  20. package/integrations/macos-overlay/overlay.jxa +639 -0
  21. package/integrations/opencode/runtime.mjs +4 -4
  22. package/integrations/opencode/tui.tsx +1 -1
  23. package/integrations/windows-overlay/Overlay.cs +4 -4
  24. package/integrations/windows-overlay/desktop.mjs +40 -8
  25. package/integrations/windows-overlay/protocol.mjs +11 -7
  26. package/integrations/windows-overlay/worker.mjs +13 -7
  27. package/package.json +41 -14
  28. package/puppy-comfort-sprites.mjs +25 -0
  29. package/puppy-companion-comfort-q5.bin.gz +0 -0
  30. package/puppy-companion-comfort.json +77 -0
  31. package/puppy-companion-life.mjs +49 -16
  32. package/puppy-companion-objects.mjs +12 -0
  33. package/puppy-frame-predictive.mjs +15 -9
  34. package/puppy-frame-store.mjs +2 -2
  35. package/puppy-paper-world.mjs +14 -0
  36. package/puppy-paper.mjs +65 -14
  37. package/retrieviewer-cli.mjs +10 -3
  38. package/retrieviewer-plugin.d.mts +1 -1
  39. package/retrieviewer-plugin.mjs +1 -1
  40. package/retrieviewer.d.mts +10 -4
  41. package/retrieviewer.mjs +20 -14
  42. package/locomotion-core.mjs +0 -21
  43. package/locomotion-puppy.animal +0 -0
  44. package/vendor/procedural-animals/package.json +0 -40
  45. package/vendor/procedural-animals/src/animal.js +0 -146
  46. package/vendor/procedural-animals/src/bake.js +0 -51
  47. package/vendor/procedural-animals/src/build.js +0 -81
  48. package/vendor/procedural-animals/src/core/build/coatKit.js +0 -121
  49. package/vendor/procedural-animals/src/core/build/featherCards.js +0 -189
  50. package/vendor/procedural-animals/src/core/build/finEdges.js +0 -85
  51. package/vendor/procedural-animals/src/core/build/furSlope.js +0 -115
  52. package/vendor/procedural-animals/src/core/build/mesh.js +0 -67
  53. package/vendor/procedural-animals/src/core/build/pipeline.js +0 -272
  54. package/vendor/procedural-animals/src/core/build/seams.js +0 -183
  55. package/vendor/procedural-animals/src/core/build/warp.js +0 -112
  56. package/vendor/procedural-animals/src/core/build/weights.js +0 -393
  57. package/vendor/procedural-animals/src/core/math/vec.js +0 -81
  58. package/vendor/procedural-animals/src/core/motion/actions.js +0 -800
  59. package/vendor/procedural-animals/src/core/motion/bird.js +0 -3063
  60. package/vendor/procedural-animals/src/core/motion/birdActions.js +0 -1059
  61. package/vendor/procedural-animals/src/core/motion/common.js +0 -158
  62. package/vendor/procedural-animals/src/core/motion/index.js +0 -22
  63. package/vendor/procedural-animals/src/core/motion/quadruped.js +0 -2875
  64. package/vendor/procedural-animals/src/core/motion/snake.js +0 -1594
  65. package/vendor/procedural-animals/src/core/motion/spider.js +0 -1810
  66. package/vendor/procedural-animals/src/core/motion/swimmer.js +0 -1047
  67. package/vendor/procedural-animals/src/core/motion/swimmerActions.js +0 -613
  68. package/vendor/procedural-animals/src/core/render/animalObject.js +0 -262
  69. package/vendor/procedural-animals/src/core/render/coatMaterial.js +0 -1301
  70. package/vendor/procedural-animals/src/core/render/dqs.js +0 -159
  71. package/vendor/procedural-animals/src/core/render/eyes.js +0 -676
  72. package/vendor/procedural-animals/src/core/render/membranes.js +0 -77
  73. package/vendor/procedural-animals/src/core/render/skeleton.js +0 -41
  74. package/vendor/procedural-animals/src/core/rig/bird.js +0 -327
  75. package/vendor/procedural-animals/src/core/rig/quadruped.js +0 -76
  76. package/vendor/procedural-animals/src/core/rig/rig.js +0 -79
  77. package/vendor/procedural-animals/src/core/rig/snake.js +0 -76
  78. package/vendor/procedural-animals/src/core/rig/spider.js +0 -110
  79. package/vendor/procedural-animals/src/core/rig/swimmer.js +0 -181
  80. package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +0 -53
  81. package/vendor/procedural-animals/src/core/sdf/mesher.js +0 -238
  82. package/vendor/procedural-animals/src/core/sdf/sdf.js +0 -263
  83. package/vendor/procedural-animals/src/index.d.ts +0 -98
  84. package/vendor/procedural-animals/src/index.js +0 -29
  85. package/vendor/procedural-animals/src/registry.js +0 -48
  86. package/vendor/procedural-animals/src/species/bear/behaviour.js +0 -463
  87. package/vendor/procedural-animals/src/species/bear/claws.js +0 -147
  88. package/vendor/procedural-animals/src/species/bear/coat.js +0 -726
  89. package/vendor/procedural-animals/src/species/bear/index.js +0 -139
  90. package/vendor/procedural-animals/src/species/bear/motion.js +0 -112
  91. package/vendor/procedural-animals/src/species/bear/regions.js +0 -78
  92. package/vendor/procedural-animals/src/species/bear/rig.js +0 -112
  93. package/vendor/procedural-animals/src/species/bear/sculpt.js +0 -272
  94. package/vendor/procedural-animals/src/species/boar/behaviour.js +0 -335
  95. package/vendor/procedural-animals/src/species/boar/coat.js +0 -372
  96. package/vendor/procedural-animals/src/species/boar/index.js +0 -110
  97. package/vendor/procedural-animals/src/species/boar/motion.js +0 -85
  98. package/vendor/procedural-animals/src/species/boar/regions.js +0 -88
  99. package/vendor/procedural-animals/src/species/boar/rig.js +0 -111
  100. package/vendor/procedural-animals/src/species/boar/sculpt.js +0 -285
  101. package/vendor/procedural-animals/src/species/cat/behaviour.js +0 -559
  102. package/vendor/procedural-animals/src/species/cat/coat.js +0 -841
  103. package/vendor/procedural-animals/src/species/cat/index.js +0 -211
  104. package/vendor/procedural-animals/src/species/cat/motion.js +0 -101
  105. package/vendor/procedural-animals/src/species/cat/regions.js +0 -82
  106. package/vendor/procedural-animals/src/species/cat/rig.js +0 -100
  107. package/vendor/procedural-animals/src/species/cat/sculpt.js +0 -266
  108. package/vendor/procedural-animals/src/species/cat/whiskers.js +0 -110
  109. package/vendor/procedural-animals/src/species/cheetah/coat.js +0 -427
  110. package/vendor/procedural-animals/src/species/cheetah/index.js +0 -51
  111. package/vendor/procedural-animals/src/species/cheetah/joints.js +0 -3
  112. package/vendor/procedural-animals/src/species/cheetah/motion.js +0 -77
  113. package/vendor/procedural-animals/src/species/cheetah/regions.js +0 -95
  114. package/vendor/procedural-animals/src/species/cheetah/rig.js +0 -66
  115. package/vendor/procedural-animals/src/species/cheetah/sculpt.js +0 -158
  116. package/vendor/procedural-animals/src/species/chicken/coat.js +0 -313
  117. package/vendor/procedural-animals/src/species/chicken/coverts.js +0 -320
  118. package/vendor/procedural-animals/src/species/chicken/index.js +0 -110
  119. package/vendor/procedural-animals/src/species/chicken/motion.js +0 -177
  120. package/vendor/procedural-animals/src/species/chicken/regions.js +0 -66
  121. package/vendor/procedural-animals/src/species/chicken/rig.js +0 -144
  122. package/vendor/procedural-animals/src/species/chicken/sculpt.js +0 -389
  123. package/vendor/procedural-animals/src/species/chicken/wingLook.js +0 -66
  124. package/vendor/procedural-animals/src/species/chicken/wingStack.js +0 -124
  125. package/vendor/procedural-animals/src/species/cow/behaviour.js +0 -521
  126. package/vendor/procedural-animals/src/species/cow/coat.js +0 -465
  127. package/vendor/procedural-animals/src/species/cow/index.js +0 -118
  128. package/vendor/procedural-animals/src/species/cow/motion.js +0 -81
  129. package/vendor/procedural-animals/src/species/cow/regions.js +0 -98
  130. package/vendor/procedural-animals/src/species/cow/rig.js +0 -116
  131. package/vendor/procedural-animals/src/species/cow/sculpt.js +0 -339
  132. package/vendor/procedural-animals/src/species/crow/coat.js +0 -145
  133. package/vendor/procedural-animals/src/species/crow/index.js +0 -70
  134. package/vendor/procedural-animals/src/species/crow/joints.js +0 -3
  135. package/vendor/procedural-animals/src/species/crow/motion.js +0 -101
  136. package/vendor/procedural-animals/src/species/crow/regions.js +0 -50
  137. package/vendor/procedural-animals/src/species/crow/rig.js +0 -83
  138. package/vendor/procedural-animals/src/species/crow/sculpt.js +0 -118
  139. package/vendor/procedural-animals/src/species/deer/behaviour.js +0 -513
  140. package/vendor/procedural-animals/src/species/deer/coat.js +0 -391
  141. package/vendor/procedural-animals/src/species/deer/index.js +0 -106
  142. package/vendor/procedural-animals/src/species/deer/motion.js +0 -97
  143. package/vendor/procedural-animals/src/species/deer/regions.js +0 -60
  144. package/vendor/procedural-animals/src/species/deer/rig.js +0 -124
  145. package/vendor/procedural-animals/src/species/deer/sculpt.js +0 -297
  146. package/vendor/procedural-animals/src/species/dog/behaviour.js +0 -521
  147. package/vendor/procedural-animals/src/species/dog/coat.js +0 -495
  148. package/vendor/procedural-animals/src/species/dog/index.js +0 -144
  149. package/vendor/procedural-animals/src/species/dog/motion.js +0 -118
  150. package/vendor/procedural-animals/src/species/dog/regions.js +0 -61
  151. package/vendor/procedural-animals/src/species/dog/rig.js +0 -129
  152. package/vendor/procedural-animals/src/species/dog/sculpt.js +0 -246
  153. package/vendor/procedural-animals/src/species/eagle/coat.js +0 -250
  154. package/vendor/procedural-animals/src/species/eagle/index.js +0 -76
  155. package/vendor/procedural-animals/src/species/eagle/joints.js +0 -3
  156. package/vendor/procedural-animals/src/species/eagle/motion.js +0 -137
  157. package/vendor/procedural-animals/src/species/eagle/regions.js +0 -57
  158. package/vendor/procedural-animals/src/species/eagle/rig.js +0 -107
  159. package/vendor/procedural-animals/src/species/eagle/sculpt.js +0 -137
  160. package/vendor/procedural-animals/src/species/fish/coat.js +0 -271
  161. package/vendor/procedural-animals/src/species/fish/index.js +0 -88
  162. package/vendor/procedural-animals/src/species/fish/motion.js +0 -92
  163. package/vendor/procedural-animals/src/species/fish/regions.js +0 -27
  164. package/vendor/procedural-animals/src/species/fish/rig.js +0 -143
  165. package/vendor/procedural-animals/src/species/fish/sculpt.js +0 -214
  166. package/vendor/procedural-animals/src/species/fish/variants.js +0 -126
  167. package/vendor/procedural-animals/src/species/fox/behaviour.js +0 -314
  168. package/vendor/procedural-animals/src/species/fox/coat.js +0 -444
  169. package/vendor/procedural-animals/src/species/fox/index.js +0 -120
  170. package/vendor/procedural-animals/src/species/fox/motion.js +0 -81
  171. package/vendor/procedural-animals/src/species/fox/regions.js +0 -59
  172. package/vendor/procedural-animals/src/species/fox/rig.js +0 -91
  173. package/vendor/procedural-animals/src/species/fox/sculpt.js +0 -202
  174. package/vendor/procedural-animals/src/species/frog/behaviour.js +0 -590
  175. package/vendor/procedural-animals/src/species/frog/coat.js +0 -305
  176. package/vendor/procedural-animals/src/species/frog/index.js +0 -97
  177. package/vendor/procedural-animals/src/species/frog/motion.js +0 -69
  178. package/vendor/procedural-animals/src/species/frog/regions.js +0 -46
  179. package/vendor/procedural-animals/src/species/frog/rig.js +0 -156
  180. package/vendor/procedural-animals/src/species/frog/sculpt.js +0 -240
  181. package/vendor/procedural-animals/src/species/goat/behaviour.js +0 -509
  182. package/vendor/procedural-animals/src/species/goat/coat.js +0 -590
  183. package/vendor/procedural-animals/src/species/goat/index.js +0 -149
  184. package/vendor/procedural-animals/src/species/goat/motion.js +0 -95
  185. package/vendor/procedural-animals/src/species/goat/regions.js +0 -98
  186. package/vendor/procedural-animals/src/species/goat/rig.js +0 -181
  187. package/vendor/procedural-animals/src/species/goat/sculpt.js +0 -547
  188. package/vendor/procedural-animals/src/species/horse/coat.js +0 -361
  189. package/vendor/procedural-animals/src/species/horse/coatSeam.js +0 -122
  190. package/vendor/procedural-animals/src/species/horse/index.js +0 -80
  191. package/vendor/procedural-animals/src/species/horse/motion.js +0 -245
  192. package/vendor/procedural-animals/src/species/horse/regions.js +0 -60
  193. package/vendor/procedural-animals/src/species/horse/rig.js +0 -117
  194. package/vendor/procedural-animals/src/species/horse/sculpt.js +0 -316
  195. package/vendor/procedural-animals/src/species/horse/seamWeights.js +0 -272
  196. package/vendor/procedural-animals/src/species/lion/behaviour.js +0 -509
  197. package/vendor/procedural-animals/src/species/lion/coat.js +0 -1016
  198. package/vendor/procedural-animals/src/species/lion/index.js +0 -111
  199. package/vendor/procedural-animals/src/species/lion/motion.js +0 -87
  200. package/vendor/procedural-animals/src/species/lion/regions.js +0 -106
  201. package/vendor/procedural-animals/src/species/lion/rig.js +0 -110
  202. package/vendor/procedural-animals/src/species/lion/sculpt.js +0 -384
  203. package/vendor/procedural-animals/src/species/lion/whiskers.js +0 -132
  204. package/vendor/procedural-animals/src/species/pig/behaviour.js +0 -575
  205. package/vendor/procedural-animals/src/species/pig/coat.js +0 -730
  206. package/vendor/procedural-animals/src/species/pig/ears.js +0 -242
  207. package/vendor/procedural-animals/src/species/pig/index.js +0 -161
  208. package/vendor/procedural-animals/src/species/pig/motion.js +0 -105
  209. package/vendor/procedural-animals/src/species/pig/regions.js +0 -100
  210. package/vendor/procedural-animals/src/species/pig/rig.js +0 -152
  211. package/vendor/procedural-animals/src/species/pig/sculpt.js +0 -382
  212. package/vendor/procedural-animals/src/species/rabbit/behaviour.js +0 -605
  213. package/vendor/procedural-animals/src/species/rabbit/coat.js +0 -285
  214. package/vendor/procedural-animals/src/species/rabbit/index.js +0 -85
  215. package/vendor/procedural-animals/src/species/rabbit/motion.js +0 -85
  216. package/vendor/procedural-animals/src/species/rabbit/regions.js +0 -48
  217. package/vendor/procedural-animals/src/species/rabbit/rig.js +0 -99
  218. package/vendor/procedural-animals/src/species/rabbit/sculpt.js +0 -148
  219. package/vendor/procedural-animals/src/species/rat/behaviour.js +0 -539
  220. package/vendor/procedural-animals/src/species/rat/coat.js +0 -341
  221. package/vendor/procedural-animals/src/species/rat/index.js +0 -111
  222. package/vendor/procedural-animals/src/species/rat/motion.js +0 -90
  223. package/vendor/procedural-animals/src/species/rat/regions.js +0 -92
  224. package/vendor/procedural-animals/src/species/rat/rig.js +0 -112
  225. package/vendor/procedural-animals/src/species/rat/sculpt.js +0 -163
  226. package/vendor/procedural-animals/src/species/rat/whiskers.js +0 -119
  227. package/vendor/procedural-animals/src/species/shark/coat.js +0 -383
  228. package/vendor/procedural-animals/src/species/shark/index.js +0 -104
  229. package/vendor/procedural-animals/src/species/shark/motion.js +0 -69
  230. package/vendor/procedural-animals/src/species/shark/regions.js +0 -34
  231. package/vendor/procedural-animals/src/species/shark/rig.js +0 -194
  232. package/vendor/procedural-animals/src/species/shark/sculpt.js +0 -343
  233. package/vendor/procedural-animals/src/species/shark/variants.js +0 -105
  234. package/vendor/procedural-animals/src/species/sheep/behaviour.js +0 -522
  235. package/vendor/procedural-animals/src/species/sheep/coat.js +0 -529
  236. package/vendor/procedural-animals/src/species/sheep/index.js +0 -152
  237. package/vendor/procedural-animals/src/species/sheep/motion.js +0 -86
  238. package/vendor/procedural-animals/src/species/sheep/neck.js +0 -41
  239. package/vendor/procedural-animals/src/species/sheep/regions.js +0 -62
  240. package/vendor/procedural-animals/src/species/sheep/rig.js +0 -163
  241. package/vendor/procedural-animals/src/species/sheep/sculpt.js +0 -542
  242. package/vendor/procedural-animals/src/species/snake/coat.js +0 -315
  243. package/vendor/procedural-animals/src/species/snake/index.js +0 -73
  244. package/vendor/procedural-animals/src/species/snake/motion.js +0 -51
  245. package/vendor/procedural-animals/src/species/snake/regions.js +0 -51
  246. package/vendor/procedural-animals/src/species/snake/rig.js +0 -108
  247. package/vendor/procedural-animals/src/species/snake/sculpt.js +0 -122
  248. package/vendor/procedural-animals/src/species/spider/coat.js +0 -279
  249. package/vendor/procedural-animals/src/species/spider/index.js +0 -78
  250. package/vendor/procedural-animals/src/species/spider/motion.js +0 -72
  251. package/vendor/procedural-animals/src/species/spider/regions.js +0 -87
  252. package/vendor/procedural-animals/src/species/spider/rig.js +0 -118
  253. package/vendor/procedural-animals/src/species/spider/sculpt.js +0 -182
  254. package/vendor/procedural-animals/src/species/wolf/behaviour.js +0 -160
  255. package/vendor/procedural-animals/src/species/wolf/coat.js +0 -749
  256. package/vendor/procedural-animals/src/species/wolf/index.js +0 -107
  257. package/vendor/procedural-animals/src/species/wolf/motion.js +0 -80
  258. package/vendor/procedural-animals/src/species/wolf/regions.js +0 -57
  259. package/vendor/procedural-animals/src/species/wolf/rig.js +0 -87
  260. package/vendor/procedural-animals/src/species/wolf/sculpt.js +0 -339
  261. package/vendor/procedural-animals/src/worker.js +0 -29
@@ -1,66 +0,0 @@
1
- // Cheetah skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
2
- // Proportions from reference photos and cheetah limb osteometry
3
- // (humerus ~0.23 m, radius ~0.22 m, femur ~0.26 m, tibia ~0.255 m, metatarsus ~0.13 m,
4
- // shoulder height ~0.76 m, head-body ~1.36 m, tail ~0.72 m).
5
- import { buildRig } from '../../core/rig/rig.js';
6
- import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
7
-
8
- export const TAIL_SEGS = 10;
9
- export const HEAD_O = [0, 0.79, 0.6]; // head-local origin (between eyes and ears)
10
-
11
- export function cheetahJoints() {
12
- const J = {
13
- nose: [0, 0.772, 0.7],
14
- occiput: [0, 0.79, 0.525],
15
- neckMid: [0, 0.716, 0.45],
16
- neckBase: [0, 0.63, 0.34],
17
- chestMid: [0, 0.648, 0.16],
18
- thoraxRear: [0, 0.668, -0.03],
19
- lumbarMid: [0, 0.68, -0.225],
20
- lumbosacral: [0, 0.668, -0.41],
21
- tailBase: [0, 0.655, -0.595],
22
- scapTopL: [0.045, 0.706, 0.286],
23
- shoulderL: [0.08, 0.536, 0.386],
24
- elbowL: [0.078, 0.346, 0.256],
25
- wristL: [0.068, 0.126, 0.276],
26
- mcpL: [0.066, 0.038, 0.306],
27
- ftoeL: [0.066, 0.016, 0.353],
28
- hipL: [0.072, 0.572, -0.46],
29
- kneeL: [0.09, 0.34, -0.345],
30
- hockL: [0.078, 0.172, -0.54],
31
- mtpL: [0.074, 0.038, -0.51],
32
- htoeL: [0.074, 0.016, -0.46],
33
- jawHinge: [0, 0.755, 0.58],
34
- jawTip: [0, 0.73, 0.66],
35
- earBaseL: [0.052, 0.83, 0.552],
36
- earTipL: [0.08, 0.853, 0.548],
37
- };
38
- // relaxed tail: droops then flicks up at the tip (J-curve seen in walking references)
39
- tailChain(J, 'tailBase', [-22, -38, -52, -60, -62, -58, -48, -32, -12, 10], [0.07, 0.074, 0.075, 0.075, 0.074, 0.073, 0.071, 0.069, 0.067, 0.065]);
40
- return J;
41
- }
42
-
43
- export function cheetahRig() {
44
- const J = cheetahJoints();
45
- return buildRig({
46
- joints: J,
47
- unit: 1,
48
- headOrigin: HEAD_O,
49
- bones: quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true }),
50
- axial: {
51
- points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
52
- bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
53
- // the skull's influence reaches well back into the nape and throat
54
- blend: { 1: [-0.035, 0.08] },
55
- },
56
- limbs: quadrupedLimbs({
57
- front: { tCore: 0.55, aCore: 0.04, aBody: -0.07, midX: 0.0 },
58
- hind: { tCore: 0.52, aCore: 0.022, aBody: -0.045, midX: 0.008 },
59
- }),
60
- appendages: [
61
- { group: 'earL', bone: 'earL', blend: [-0.003, 0.005] },
62
- { group: 'earR', bone: 'earR', blend: [-0.003, 0.005] },
63
- ],
64
- webTags: ['flankfold', 'thighfront', 'scapmuscle'],
65
- });
66
- }
@@ -1,158 +0,0 @@
1
- // The cheetah, sculpted as a signed distance field.
2
- // Every primitive is attached to a bone (for skinning) and a group (axial / limb / ear / jaw).
3
- import { HEAD_O, TAIL_SEGS } from './rig.js';
4
- import { add, sub, mul, lerp, norm, cross } from '../../core/math/vec.js';
5
- import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
6
-
7
- const hl = (v) => [v[0] + HEAD_O[0], v[1] + HEAD_O[1], v[2] + HEAD_O[2]];
8
-
9
- // Eye geometry shared by the sculpt (lids + aperture) and the eyeball shader.
10
- // c: head-local eye centre (left); r: eyeball radius; yaw: outward divergence of each eye;
11
- // lid: eyelid skin thickness; R, d: almond aperture (two circular arcs) -> 22 mm wide, 10.5 mm
12
- // tall, set 1.3 mm low (off) so the upper lid hoods the top of the iris; tilt: inner corner lower.
13
- export const EYE = { c: [0.027, 0.026, 0.024], r: 0.0122, back: 0.0025, yaw: 0.16, lid: 0.0014, R: 0.014149, d: 0.008899, off: -0.0013, tilt: (12 * Math.PI) / 180, irisZ: 0.00727, irisR: 0.0098 };
14
-
15
- const X = [1, 0, 0];
16
-
17
- export function sculptCheetah(m, rig) {
18
- const J = rig.J;
19
- const eyeFrame = (s) => eyeFrameOf(EYE, HEAD_O, s);
20
-
21
- // Ellipsoid whose local Y follows `ydir`; radii = [lateral, along ydir, third axis]
22
- const ellY = (o) => {
23
- const y = norm(o.ydir);
24
- const lat = o.lateral || X;
25
- const z = norm(cross(lat, y));
26
- return m.ell({ ...o, axis: z, up: y, r: [o.r[0], o.r[1], o.r[2]] });
27
- };
28
-
29
- // ---------------------------------------------------------------- TORSO
30
- m.ell({ tag: 'ribcage', bone: 'spine3', c: [0, 0.575, 0.13], r: [0.1, 0.18, 0.22], axis: norm([0, 0.15, -1]), k: 0 });
31
- m.ell({ tag: 'brisket', bone: 'chest', c: [0, 0.478, 0.3], r: [0.075, 0.095, 0.1], axis: norm([0, -0.35, 1]), k: 0.06 });
32
- m.ell({ tag: 'pectoral', bone: 'chest', c: [0, 0.49, 0.35], r: [0.08, 0.08, 0.075], k: 0.05 });
33
- m.ell({ tag: 'withers', bone: 'chest', c: [0, 0.705, 0.24], r: [0.055, 0.058, 0.13], axis: norm([0, -0.08, 1]), k: 0.06 });
34
- m.ell({ tag: 'back', bone: 'spine3', c: [0, 0.7, 0.0], r: [0.07, 0.05, 0.17], k: 0.06 });
35
- m.ell({ tag: 'abdomen', bone: 'spine2', c: [0, 0.628, -0.17], r: [0.076, 0.1, 0.2], axis: norm([0, 0.3, -1]), k: 0.07 });
36
- m.ell({ tag: 'loin', bone: 'spine1', c: [0, 0.695, -0.24], r: [0.064, 0.055, 0.19], k: 0.05 });
37
- m.ell({ tag: 'flank', bone: 'spine1', c: [0, 0.605, -0.31], r: [0.068, 0.07, 0.1], k: 0.05 });
38
- m.ell({ tag: 'pelvis', bone: 'pelvis', c: [0, 0.665, -0.47], r: [0.078, 0.095, 0.135], k: 0.06 });
39
- m.ell({ tag: 'croup', bone: 'pelvis', c: [0, 0.715, -0.46], r: [0.06, 0.045, 0.125], k: 0.04 });
40
- for (const s of [1, -1]) {
41
- m.ell({ tag: 'rump', bone: 'pelvis', c: [0.045 * s, 0.625, -0.575], r: [0.044, 0.075, 0.055], k: 0.04 });
42
- }
43
-
44
- // ---------------------------------------------------------------- NECK
45
- m.cone({ tag: 'neck', bone: 'neck1', a: [0, 0.61, 0.33], b: [0, 0.705, 0.455], ra: 0.088, rb: 0.064, k: 0.06 });
46
- m.cone({ tag: 'neck', bone: 'neck2', a: [0, 0.705, 0.455], b: [0, 0.772, 0.53], ra: 0.064, rb: 0.052, k: 0.04 });
47
- m.ell({ tag: 'nape', bone: 'neck1', c: [0, 0.765, 0.43], r: [0.038, 0.028, 0.12], axis: norm([0, 0.35, 1]), k: 0.04 });
48
- m.ell({ tag: 'throat', bone: 'neck1', c: [0, 0.655, 0.47], r: [0.046, 0.055, 0.09], axis: norm([0, 0.8, 0.6]), k: 0.05 });
49
- m.ell({ tag: 'throat', bone: 'neck2', c: hl([0, -0.054, -0.042]), r: [0.035, 0.028, 0.062], k: 0.03 });
50
-
51
- // ---------------------------------------------------------------- HEAD (modelled in head-local coords, see HEAD_O)
52
- // landmarks measured from profile/frontal references: nose tip (0,-0.018,0.10), eyes (+-0.029,0.026,0.021),
53
- // chin (0,-0.068,0.058), skull top 0.066, occiput -0.09
54
- const H = { bone: 'head' };
55
- m.ell({ ...H, tag: 'cranium', c: hl([0, 0.02, -0.03]), r: [0.047, 0.046, 0.062], k: 0.04 });
56
- m.ell({ ...H, tag: 'forehead', c: hl([0, 0.034, 0.018]), r: [0.021, 0.03, 0.034], axis: norm([0, -0.6, 1]), k: 0.02 });
57
- for (const s of [1, -1]) {
58
- m.ell({ ...H, tag: 'brow', c: hl([0.028 * s, 0.042, 0.022]), r: [0.014, 0.007, 0.012], k: 0.012 });
59
- m.ell({ ...H, tag: 'zygomatic', c: hl([0.047 * s, 0.006, -0.002]), r: [0.013, 0.02, 0.04], axis: norm([-0.35 * s, 0, 1]), k: 0.025 });
60
- m.ell({ ...H, tag: 'cheek', c: hl([0.035 * s, -0.027, 0.004]), r: [0.021, 0.026, 0.036], k: 0.025 });
61
- m.ell({ ...H, tag: 'lip', c: hl([0.023 * s, -0.047, 0.05]), r: [0.011, 0.009, 0.03], axis: norm([-0.45 * s, -0.15, 1]), k: 0.012 });
62
- m.ell({ ...H, tag: 'mastoid', c: hl([0.034 * s, -0.02, -0.05]), r: [0.022, 0.03, 0.03], k: 0.03 });
63
- m.ell({ ...H, tag: 'whisker', c: hl([0.0135 * s, -0.037, 0.078]), r: [0.0145, 0.0135, 0.016], k: 0.012 });
64
- }
65
- m.ell({ ...H, tag: 'muzzle', c: hl([0, -0.022, 0.058]), r: [0.024, 0.024, 0.032], axis: norm([0, -0.4, 1]), k: 0.02 });
66
- m.cone({ ...H, tag: 'nasal', a: hl([0, 0.036, 0.042]), b: hl([0, 0.002, 0.083]), ra: 0.019, rb: 0.014, k: 0.015 });
67
- m.ell({ ...H, tag: 'nose', c: hl([0, -0.012, 0.091]), r: [0.0142, 0.0086, 0.0082], axis: norm([0, 0.5, 1]), k: 0.008 });
68
- m.ell({ ...H, tag: 'philtrum', c: hl([0, -0.034, 0.088]), r: [0.01, 0.011, 0.008], k: 0.01 });
69
- for (const s of [1, -1]) {
70
- // eyelids: a thin skin shell hugging the eyeball, cut open along an almond-shaped aperture that
71
- // reaches only down to the eyeball, so the eye sits flush in its lids with no cavity around it
72
- const ef = eyeFrame(s);
73
- const at = (u, v, w) => add(add(add(ef.c, mul(ef.x, u)), mul(ef.y, v)), mul(ef.z, w));
74
- // orbit: a soft hollow around the eye so the brow, cheek and nose bridge fall away to the lids
75
- // (the inner corner opens toward the tear line instead of being buried under the bridge)
76
- ellY({ ...H, tag: 'orbit', c: at(-0.002 * s, -0.0005, 0.019), ydir: ef.y, lateral: ef.x, r: [0.018, 0.0125, 0.009], k: 0.008, carve: true });
77
- m.sphere({ ...H, tag: 'eyelid', c: ef.c, rad: EYE.r + EYE.lid, k: 0.005 });
78
- m.lens({ ...H, tag: 'eyesocket', c: add(ef.c, mul(ef.y, EYE.off)), x: ef.x, y: ef.y, z: ef.z, R: EYE.R, d: EYE.d, zMin: -0.002, zMax: 0.024, k: 0.0022, carve: true });
79
- m.sphere({ ...H, tag: 'nostril', c: hl([0.0065 * s, -0.015, 0.1]), rad: 0.003, k: 0.002, carve: true });
80
- }
81
-
82
- // ---------------------------------------------------------------- JAW (separate surface so the mouth can open)
83
- const JW = { bone: 'jaw', group: 'jaw', part: 'jaw' };
84
- m.cone({ ...JW, tag: 'mandible', a: hl([0, -0.045, -0.012]), b: hl([0, -0.052, 0.044]), ra: 0.018, rb: 0.012, k: 0 });
85
- for (const s of [1, -1]) {
86
- m.cone({ ...JW, tag: 'mandible', a: hl([0.032 * s, -0.039, -0.028]), b: hl([0.01 * s, -0.051, 0.048]), ra: 0.014, rb: 0.01, k: 0.02 });
87
- }
88
- m.ell({ ...JW, tag: 'chin', c: hl([0, -0.053, 0.05]), r: [0.015, 0.011, 0.011], k: 0.015 });
89
-
90
- // ---------------------------------------------------------------- EARS
91
- for (const S of ['L', 'R']) {
92
- const s = S === 'L' ? 1 : -1;
93
- const base = J['earBase' + S], tip = J['earTip' + S];
94
- const up = norm(sub(tip, base));
95
- const facing = norm([1.0 * s, 0.1, 1]);
96
- const c = lerp(base, tip, 0.3);
97
- const lat = norm(cross(up, facing));
98
- const ear = { bone: 'ear' + S, group: 'ear' + S };
99
- ellY({ ...ear, tag: 'ear', c, ydir: up, lateral: lat, r: [0.0165, 0.0185, 0.0062], k: 0.012 });
100
- ellY({ ...ear, tag: 'earinner', c: add(add(c, mul(facing, 0.0068)), mul(up, 0.003)), ydir: up, lateral: lat, r: [0.0112, 0.0132, 0.0044], k: 0.003, carve: true });
101
- }
102
-
103
- // ---------------------------------------------------------------- LEGS
104
- for (const S of ['L', 'R']) {
105
- const s = S === 'L' ? 1 : -1;
106
- const lat = [s, 0, 0];
107
- const sx = (v) => [v[0] * s, v[1], v[2]];
108
- // front
109
- const g = 'F' + S;
110
- const Sc = J['scapTop' + S], Sh = J['shoulder' + S], E = J['elbow' + S], W = J['wrist' + S], M = J['mcp' + S], T = J['ftoe' + S];
111
- ellY({ tag: 'scapmuscle', bone: 'scapula' + S, group: g, c: add(lerp(Sc, Sh, 0.5), sx([0.006, 0, 0])), ydir: sub(Sh, Sc), lateral: lat, r: [0.022, 0.1, 0.055], k: 0.06, bias: 0.004 });
112
- m.cone({ tag: 'upperarm', bone: 'humerus' + S, group: g, a: Sh, b: E, ra: 0.037, rb: 0.031, k: 0.06 });
113
- ellY({ tag: 'triceps', bone: 'humerus' + S, group: g, c: add(lerp(Sh, E, 0.55), [0, 0, -0.03]), ydir: sub(E, Sh), lateral: lat, r: [0.03, 0.075, 0.036], k: 0.05 });
114
- m.sphere({ tag: 'olecranon', bone: 'radius' + S, group: g, c: add(E, [0, 0.01, -0.028]), rad: 0.019, k: 0.02 });
115
- m.cone({ tag: 'forearm', bone: 'radius' + S, group: g, a: E, b: W, ra: 0.032, rb: 0.019, k: 0.025 });
116
- ellY({ tag: 'forearmmuscle', bone: 'radius' + S, group: g, c: add(lerp(E, W, 0.25), sx([0.004, 0, 0.004])), ydir: sub(W, E), lateral: lat, r: [0.03, 0.07, 0.034], k: 0.03 });
117
- m.sphere({ tag: 'wrist', bone: 'metacarpus' + S, group: g, c: add(W, [0, 0, -0.004]), rad: 0.0195, k: 0.012 });
118
- m.sphere({ tag: 'carpalpad', bone: 'metacarpus' + S, group: g, c: add(W, [0, -0.01, -0.02]), rad: 0.009, k: 0.01 });
119
- m.cone({ tag: 'pastern', bone: 'metacarpus' + S, group: g, a: W, b: M, ra: 0.018, rb: 0.017, k: 0.012 });
120
- m.sphere({ tag: 'dewclaw', bone: 'metacarpus' + S, group: g, c: add(lerp(W, M, 0.35), sx([-0.016, 0, 0.004])), rad: 0.007, k: 0.006 });
121
- const dp = norm(sub(T, M));
122
- ellY({ tag: 'paw', bone: 'fpaw' + S, group: g, c: add(add(M, mul(dp, 0.02)), [0, -0.006, 0]), ydir: dp, lateral: lat, r: [0.026, 0.036, 0.018], k: 0.014 });
123
- m.sphere({ tag: 'pad', bone: 'fpaw' + S, group: g, c: add(M, [0, -0.026, 0.012]), rad: 0.012, k: 0.01 });
124
- const toeX = [-0.019, -0.0065, 0.0065, 0.019], toeZ = [-0.009, 0, 0, -0.009];
125
- for (let i = 0; i < 4; i++) m.sphere({ tag: 'toe', bone: 'fpaw' + S, group: g, c: [T[0] + toeX[i] * s, 0.0115, T[2] - 0.008 + toeZ[i]], rad: 0.0105, k: 0.007 });
126
-
127
- // hind
128
- const h = 'H' + S;
129
- const Hp = J['hip' + S], K = J['knee' + S], Hk = J['hock' + S], Mt = J['mtp' + S], Tt = J['htoe' + S];
130
- // The thigh is a broad teardrop in side view: wide where it rises into the flank and croup,
131
- // narrowing to the stifle. Its cranial edge climbs all the way up to the iliac wing and the
132
- // flank fold webs the stifle to the belly, so there is no notch between belly and thigh.
133
- ellY({ tag: 'thigh', bone: 'femur' + S, group: h, c: add(lerp(Hp, K, 0.4), sx([0.004, 0, -0.035])), ydir: sub(K, Hp), lateral: lat, r: [0.041, 0.15, 0.1], k: 0.05, bias: 0.004 });
134
- m.cone({ tag: 'thighfront', bone: 'femur' + S, group: h, a: sx([0.04, 0.625, -0.33]), b: add(K, sx([-0.004, 0.055, 0.0])), ra: 0.04, rb: 0.025, k: 0.06 });
135
- m.cone({ tag: 'hamstring', bone: 'femur' + S, group: h, a: sx([0.046, 0.625, -0.595]), b: add(lerp(K, Hk, 0.28), [0, 0, -0.028]), ra: 0.045, rb: 0.028, k: 0.04 });
136
- ellY({ tag: 'flankfold', bone: 'femur' + S, group: h, c: sx([0.05, 0.475, -0.29]), ydir: [-0.03, 0.16, 0.1], lateral: lat, r: [0.02, 0.085, 0.04], k: 0.06 });
137
- m.sphere({ tag: 'stifle', bone: 'tibia' + S, group: h, c: add(K, sx([0.002, 0.008, 0.006])), rad: 0.0175, k: 0.04 });
138
- m.cone({ tag: 'shin', bone: 'tibia' + S, group: h, a: add(lerp(K, Hk, 0.06), sx([0.0, 0.0, 0.004])), b: Hk, ra: 0.024, rb: 0.018, k: 0.03 });
139
- ellY({ tag: 'calf', bone: 'tibia' + S, group: h, c: add(lerp(K, Hk, 0.3), sx([0.002, 0.01, -0.027])), ydir: sub(Hk, K), lateral: lat, r: [0.025, 0.065, 0.029], k: 0.035 });
140
- m.cone({ tag: 'achilles', bone: 'tibia' + S, group: h, a: add(lerp(K, Hk, 0.5), [0, 0.01, -0.035]), b: add(Hk, [0, 0.012, -0.03]), ra: 0.012, rb: 0.011, k: 0.015 });
141
- m.sphere({ tag: 'calcaneus', bone: 'metatarsus' + S, group: h, c: add(Hk, [0, 0.012, -0.026]), rad: 0.015, k: 0.012 });
142
- m.sphere({ tag: 'hock', bone: 'metatarsus' + S, group: h, c: Hk, rad: 0.021, k: 0.012 });
143
- m.cone({ tag: 'metatarsus', bone: 'metatarsus' + S, group: h, a: Hk, b: Mt, ra: 0.018, rb: 0.016, k: 0.012 });
144
- const dh = norm(sub(Tt, Mt));
145
- ellY({ tag: 'paw', bone: 'hpaw' + S, group: h, c: add(add(Mt, mul(dh, 0.02)), [0, -0.006, 0]), ydir: dh, lateral: lat, r: [0.024, 0.034, 0.017], k: 0.014 });
146
- m.sphere({ tag: 'pad', bone: 'hpaw' + S, group: h, c: add(Mt, [0, -0.026, 0.01]), rad: 0.011, k: 0.01 });
147
- for (let i = 0; i < 4; i++) m.sphere({ tag: 'toe', bone: 'hpaw' + S, group: h, c: [Tt[0] + toeX[i] * 0.95 * s, 0.011, Tt[2] - 0.008 + toeZ[i]], rad: 0.0098, k: 0.007 });
148
- }
149
-
150
- // ---------------------------------------------------------------- TAIL
151
- const tailR = (t) => (t < 0.4 ? 0.034 + (0.024 - 0.034) * (t / 0.4) : t < 0.8 ? 0.024 + (0.021 - 0.024) * ((t - 0.4) / 0.4) : 0.021 - 0.002 * ((t - 0.8) / 0.2));
152
- m.cone({ tag: 'tailroot', bone: 'tail0', a: [0, 0.672, -0.545], b: J.tail1, ra: 0.05, rb: tailR(0.1), k: 0.04 });
153
- for (let i = 0; i < TAIL_SEGS; i++) {
154
- m.cone({ tag: 'tail', bone: 'tail' + i, a: J['tail' + i], b: J['tail' + (i + 1)], ra: tailR(i / TAIL_SEGS), rb: tailR((i + 1) / TAIL_SEGS), k: 0 });
155
- }
156
-
157
- return m;
158
- }
@@ -1,313 +0,0 @@
1
- // The chicken's plumage and bare parts, baked per vertex: contour-feather shingles (material 9) coloured
2
- // by feather tract (hackle, back, wing bow, breast, fluff, saddle) with per-feather markings (shaft
3
- // streaks, bars, spangles; surf.z < 0, marking colour in patternColor), a soft down haze that is long
4
- // in the fluffy underparts and drumsticks, hair-like lanceolate hackles and saddle on roosters, bare
5
- // glossy red skin on the face, comb and wattles (material 4), red or white earlobes, a horn-yellow
6
- // keratin bill and claws, and scaled shanks and toes (material 6). Colours per breed and sex are in
7
- // palette() (sampled from the reference photos and breed standards).
8
- import { SDFModel } from '../../core/sdf/sdf.js';
9
- import { norm, sub, dot, cross, add, mul, clamp, smoothstep, mix, fbm3 } from '../../core/math/vec.js';
10
- import { srgb, mix3, MAT } from '../../core/build/coatKit.js';
11
-
12
- // feather marking modes (shader: coatMaterial.js, material 9, surf.z = -(mode + amount))
13
- export const MARK = { lace: 0, bar: 1, shaft: 2, spangle: 3 };
14
- const markZ = (mode, amt) => -(mode + clamp(amt, 0, 0.98));
15
-
16
- const C = (hex) => srgb(hex);
17
- export function palette(p = {}) {
18
- const breed = p.breed || 'red', male = p.sex === 'male', juv = p.age === 'juvenile';
19
- const skin = { comb: C(0xc41f2a), wattle: C(0xb81d24), face: C(0xcc3a42), lobe: C(0xbd2e38), lobeWhite: C(0xece6da) };
20
- const P = {
21
- red: male
22
- ? { body: C(0x7a2c12), back: C(0x9c3f16), hackle: C(0xc8741e), hackleTip: C(0xe0a040), saddle: C(0xc05a18), bow: C(0x6e2410), breast: C(0x1a1410), fluff: C(0x2a2420), tail: C(0x10171a), tailIrid: 0.7, flight: C(0x2a2018), flightEdge: C(0x8a4a22), leg: C(0xd8b04a), bill: C(0xcfae6a), lobe: 'red', marks: [] }
23
- : { body: C(0x9c5a2c), back: C(0x98562a), hackle: C(0xb67434), hackleTip: C(0xc4843e), saddle: C(0x9c5a2c), bow: C(0x8a4a24), breast: C(0xa4602e), fluff: C(0xd6bf98), tail: C(0x3e2416), tailIrid: 0.1, flight: C(0x5e3820), flightEdge: C(0xa06c3e), leg: C(0xdcb44a), bill: C(0xd8b876), lobe: 'red', marks: [{ mode: MARK.shaft, amt: 0.6, col: C(0x4e2612), where: ['hackle', 'head'] }, { mode: MARK.lace, amt: 0.4, col: C(0xc89458), where: ['back', 'wing', 'body'] }] },
24
- leghorn: { body: C(0xefede6), back: C(0xefede6), hackle: C(0xf2f0ea), hackleTip: C(0xf4f2ec), saddle: C(0xf1efe8), bow: C(0xece9e1), breast: C(0xf0eee7), fluff: C(0xf3f2ee), tail: C(0xeeece5), tailIrid: 0, flight: C(0xebe8df), flightEdge: C(0xf1efe8), leg: C(0xe6c34a), bill: C(0xe6c86a), lobe: 'white', marks: [] },
25
- australorp: { body: C(0x141619), back: C(0x131518), hackle: C(0x15171a), hackleTip: C(0x17191c), saddle: C(0x141619), bow: C(0x131518), breast: C(0x16181b), fluff: C(0x34363a), tail: C(0x101214), tailIrid: 0.8, flight: C(0x111214), flightEdge: C(0x161719), leg: C(0x2c2e32), bill: C(0x2e2e30), lobe: 'red', marks: [], irid: 0.75 },
26
- barred: { body: C(0xdcdcd4), back: C(0xd8d8d0), hackle: C(0xdedfd8), hackleTip: C(0xe2e2dc), saddle: C(0xdcdcd4), bow: C(0xd8d8d0), breast: C(0xdcdcd4), fluff: C(0xcacac2), tail: C(0xcfcfc8), tailIrid: 0, flight: C(0xb8b8b0), flightEdge: C(0xd0d0c8), leg: C(0xe2bf4c), bill: C(0xe0c262), lobe: 'red', marks: [{ mode: MARK.bar, amt: male ? 0.78 : 0.92, col: C(0x1c1c1e), where: 'all' }], barred: true },
27
- buff: { body: C(0xcf9a52), back: C(0xcb944c), hackle: C(0xd6a45c), hackleTip: C(0xdcae66), saddle: C(0xd0984e), bow: C(0xc68e48), breast: C(0xd09a54), fluff: C(0xe0c08a), tail: C(0xb67e3c), tailIrid: 0, flight: C(0xbd8743), flightEdge: C(0xd2a05a), leg: C(0xe6cfbe), bill: C(0xe0c8a2), lobe: 'red', marks: [] },
28
- speckled: { body: C(0x6a2c16), back: C(0x6a2c16), hackle: C(0x7a3518), hackleTip: C(0x8a4020), saddle: C(0x6e2e16), bow: C(0x622814), breast: C(0x6e2e16), fluff: C(0xb8a088), tail: C(0x1c1614), tailIrid: 0.4, flight: C(0x3c2014), flightEdge: C(0xe8e2d6), leg: C(0xe3cbbd), bill: C(0xd8c6a0), lobe: 'red', marks: [{ mode: MARK.spangle, amt: 0.8, col: C(0xf2eee6), where: 'all' }], spangled: true },
29
- };
30
- const out = { ...(P[breed] || P.red), ...skin, breed, male };
31
- if (!male && breed === 'red') out.tail = C(0x4a2a16);
32
- // chicks: down only (yellow, black or chipmunk-striped), pale legs and bill, no comb
33
- if (juv) {
34
- const down = {
35
- red: { body: C(0xd7b77a), back: C(0x8a6238), stripe: C(0x6b4726), fluff: C(0xeedca2) },
36
- leghorn: { body: C(0xf2e08a), back: C(0xf0dc84), fluff: C(0xf6ea9e) },
37
- buff: { body: C(0xf0d488), back: C(0xecce80), fluff: C(0xf6e4a2) },
38
- australorp: { body: C(0x1a1a1c), back: C(0x161618), fluff: C(0xd8d0b0) },
39
- barred: { body: C(0x1c1c1e), back: C(0x18181a), fluff: C(0x5a5a58), spot: C(0xf0ecd8) },
40
- speckled: { body: C(0x7a5836), back: C(0x5e3f24), stripe: C(0x4a2e1a), fluff: C(0xdcc49a) },
41
- }[breed] || { body: C(0xf2e08a), back: C(0xf0dc84), fluff: C(0xf6ea9e) };
42
- Object.assign(out, down, { hackle: down.body, hackleTip: down.body, saddle: down.back, bow: down.back, breast: down.fluff, tail: down.back, flight: mix3(down.back, down.body, 0.3), flightEdge: down.body, tailIrid: 0, marks: [], leg: C(0xe9c98a), bill: C(0xd9bc8c), juv: true });
43
- }
44
- if (p.tone) for (const k of ['body', 'back', 'hackle', 'hackleTip', 'saddle', 'bow', 'breast', 'tail', 'flight']) out[k] = out[k].map((x) => x * p.tone);
45
- return out;
46
- }
47
-
48
- export function chickenCoat(ctx) {
49
- const { model, rig, pos, nrm, regionOf, regionNames, weights, nV, params } = ctx;
50
- const { BONES, J } = rig;
51
- const form = params.form || {};
52
- const Pal = palette(params);
53
- const male = params.sex === 'male' && !Pal.juv;
54
- const comb = new Float32Array(nV * 3), tint = new Float32Array(nV * 4), surf = new Float32Array(nV * 4);
55
- const furLen = new Float32Array(nV), mark = new Float32Array(nV).fill(1), pattern = new Float32Array(nV).fill(1), patCol = new Float32Array(nV * 4);
56
- const boneName = BONES.map((b) => b.name);
57
- const tagged = (...t) => model.prims.filter((p) => t.includes(p.tag));
58
- const billP = tagged('bill'), mandP = model.forPart('jaw');
59
- const eyeP = tagged('eyesocket'), clawP = tagged('claw'), spurP = tagged('spur');
60
- const combP = tagged('comb'), wattleP = tagged('wattle'), lobeP = tagged('earlobe');
61
- const legP = tagged('tarsus', 'toe', 'pad', 'hock', 'spur', 'shank');
62
- const minD = (list, p) => { let d = 1e9; for (const q of list) d = Math.min(d, SDFModel.dist(q, p[0], p[1], p[2])); return d; };
63
- const HO = rig.headOrigin, hk = form.headK ?? 1;
64
- const axialPts = rig.AXIAL.points;
65
- const axialDir = (p) => {
66
- let best = 1e9, dir = [0, 0, -1];
67
- for (let i = 0; i < axialPts.length - 1; i++) {
68
- const a = axialPts[i], b = axialPts[i + 1], ab = sub(b, a), l2 = dot(ab, ab);
69
- const t = clamp(dot(sub(p, a), ab) / l2, 0, 1);
70
- const q = add(a, mul(ab, t)), d = Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
71
- if (d < best) { best = d; dir = norm(ab); }
72
- }
73
- return dir;
74
- };
75
- const lobeCol = Pal.lobe === 'white' ? Pal.lobeWhite : Pal.lobe;
76
- const marks = Pal.marks || [];
77
- const irid0 = Pal.irid ?? 0.1;
78
- const neckTop = J.occiput[1], neckBot = J.neckBase[1];
79
- for (let v = 0; v < nV; v++) {
80
- const p = [pos[v * 3], pos[v * 3 + 1], pos[v * 3 + 2]], n = [nrm[v * 3], nrm[v * 3 + 1], nrm[v * 3 + 2]];
81
- const bn = boneName[weights.dominant[v]] || '';
82
- const region = regionNames[regionOf[v]];
83
- let col = Pal.body, mat = MAT.FEATHER, fl = 0.004, gloss = 0.4, size = 0.022, irid = irid0 * 0.3, mz = 0;
84
- let flow = axialDir(p), mcol = null;
85
- const h = [(p[0] - HO[0]) / hk, (p[1] - HO[1]) / hk, (p[2] - HO[2]) / hk];
86
- const up = n[1];
87
- let tract = 'body';
88
- if (region === 'jaw' || bn === 'jaw') {
89
- mat = MAT.KERATIN; col = Pal.bill; fl = 0; gloss = 0.5; size = 0; irid = 0; flow = [0, 0, 1];
90
- if (minD(billP, p) < 0.0005 && h[2] < 0.035) { mat = MAT.MOUTH; col = srgb(0xc98a86); }
91
- } else if (bn === 'head' || region === 'head') {
92
- // head: feathered crown and nape, bare red face, comb, wattles, earlobes, bill
93
- // (grading into the neck's hackles toward the nape: no seam at the head / body cut)
94
- const rn = smoothstep(0.016, 0.034, Math.hypot(h[0] * 0.6, h[1], h[2]));
95
- col = mix3(Pal.hackle, Pal.hackleTip, 0.6); size = mix(0.006, male ? 0.014 : 0.016, rn); fl = mix(0.0025, male ? 0.009 : 0.005, rn); gloss = mix(0.35, male ? 0.55 : 0.4, rn); irid = irid0 * 0.35;
96
- flow = norm([0, -0.35, -1]);
97
- if (Math.abs(h[0]) > 0.006) flow = norm([h[0] * 10, -0.5, -1]);
98
- tract = 'head';
99
- const dB = minD(billP, p), dC = combP.length ? minD(combP, p) : 1, dW = wattleP.length ? minD(wattleP, p) : 1, dL = lobeP.length ? minD(lobeP, p) : 1;
100
- const cvh = fbm3(p[0] * 700, p[1] * 700, p[2] * 700, 2) - 0.5;
101
- const bare = (col2, g2) => { mat = MAT.SKIN; col = col2; fl = 0; gloss = g2; size = 0; irid = 0; tract = 'bare'; };
102
- if (dB < 0.0012 && h[2] > 0.0195 - 0.35 * Math.min(0, h[1] + 0.004)) { mat = MAT.KERATIN; col = Pal.bill; fl = 0; gloss = 0.55; irid = 0; size = 0; flow = [0, 0, 1]; tract = 'bill'; }
103
- else if (dC < 0.0012) { bare(Pal.comb, 0.55); flow = [0, 1, 0]; }
104
- else if (dW < 0.0012) { bare(Pal.wattle, 0.6); flow = [0, -1, 0]; }
105
- else if (dL < 0.0009) { bare(lobeCol, 0.5); }
106
- else if (!Pal.juv && h[2] > -0.0095 + 0.0015 * cvh && h[2] < 0.03 && h[1] < 0.0048 - 60 * Math.max(0, h[2] - 0.006) ** 2 - 40 * Math.max(0, -0.001 - h[2]) ** 2 + 0.0008 * cvh && h[1] > -0.022 && Math.abs(h[0]) > 0.0024) {
107
- // bare facial skin with sparse bristles; feathered at its rear edge
108
- bare(Pal.face, 0.45);
109
- fl = 0.0012 * smoothstep(-0.004, -0.009, h[2]);
110
- }
111
- // the eye ring: bare skin at the lid margin
112
- for (const e of eyeP) {
113
- const de = SDFModel.dist(e, p[0], p[1], p[2]);
114
- if (Math.abs(de) < 0.0011) { mat = MAT.DARK_SKIN; col = Pal.juv ? srgb(0x3a3230) : mix3(Pal.face, srgb(0x40181a), 0.5); fl = 0; tract = 'bare'; }
115
- }
116
- if (Pal.juv && tract === 'head') { mat = MAT.FUR; fl = 0.007; size = 0.004; col = mix3(Pal.body, Pal.fluff, 0.3); gloss = 0.2; }
117
- } else if (/^(tarsus|toe)/.test(bn) || (bn.startsWith('tibia') && minD(legP, p) < 0.0009)) {
118
- // scaled shank and toes: large scutes down the front, small reticulate scales behind
119
- mat = MAT.SCALES; col = Pal.leg; fl = 0; gloss = 0.4; irid = 0; tract = 'leg';
120
- const front = bn.startsWith('tarsus') ? smoothstep(-0.2, 0.6, n[2]) : 0.5;
121
- size = mix(0.0022, 0.0042, front);
122
- flow = [0, -1, 0];
123
- if (/^toe/.test(bn)) { const b = BONES[weights.dominant[v]]; flow = norm(sub(b.tail, b.head)); size = 0.0028; }
124
- if (minD(clawP, p) < 0.0005) { mat = MAT.KERATIN; col = mix3(Pal.leg, srgb(0x6a6056), 0.5); gloss = 0.6; size = 0; }
125
- if (spurP.length && minD(spurP, p) < 0.0006) { mat = MAT.KERATIN; col = mix3(Pal.leg, srgb(0x5a5048), 0.45); gloss = 0.6; size = 0; }
126
- } else if (bn.startsWith('tibia') || bn.startsWith('femur')) {
127
- // drumstick: soft fluffy feathers pointing down the leg
128
- col = mix3(Pal.fluff, Pal.body, Pal.juv ? 0.4 : 0.55); fl = Pal.juv ? 0.009 : 0.008; size = 0.016; gloss = 0.3; irid = 0; tract = 'fluff';
129
- flow = [0, -1, -0.3];
130
- } else if (/^(humerus|ulna|hand)/.test(bn)) {
131
- // wing coverts: lie toward the trailing edge; the bow (lesser coverts) is darker on red breeds
132
- const b = BONES[weights.dominant[v]];
133
- const d = norm(sub(b.tail, b.head));
134
- const sL = b.side === 'R' ? 'R' : 'L';
135
- let wn = norm(cross(sub(J['elbow' + sL], J['shoulder' + sL]), sub(J['wrist' + sL], J['elbow' + sL])));
136
- if (wn[1] < 0) wn = mul(wn, -1);
137
- const s = b.side === 'R' ? -1 : 1;
138
- flow = mul(norm(cross(wn, d)), s);
139
- if (!Pal.juv && /^(ulna|hand)/.test(bn)) {
140
- // the forearm's coverts lie back and down along the folded flight feathers, as the greater
141
- // covert cards along the shield's rim (coverts.js), not straight across the forearm
142
- const dU = norm(sub(J['wrist' + sL], J['elbow' + sL])), tU = mul(norm(cross(wn, dU)), s);
143
- flow = norm(add(mul(dU, -0.64), mul(tU, 0.77)));
144
- }
145
- size = 0.02; fl = 0.003; tract = 'wing';
146
- const top = dot(n, wn);
147
- col = top < 0 ? mix3(Pal.fluff, Pal.body, 0.5) : Pal.bow;
148
- irid = top < 0 ? 0 : irid0 * 0.8;
149
- // a chick's wing is down in the colour of the down on its bed (the folded wing lies on the flank's
150
- // brown: its pale underside and dark bow showed as a lens and a dark knob at the wrist), the
151
- // underwing a little lighter; as long as the down around it
152
- if (Pal.juv) { const L = chickWingDownLook(params); col = top < 0 ? L.under : L.top; fl = top < 0 ? L.furUnder : L.fur; mat = MAT.FUR; size = L.size / (params.size || 1); gloss = L.gloss; irid = 0; }
153
- } else {
154
- // body tracts
155
- const dorsal = smoothstep(-0.25, 0.45, up);
156
- const ny = (p[1] - neckBot) / Math.max(1e-3, neckTop - neckBot);
157
- if (bn.startsWith('neck') || (bn === 'chest' && ny > -0.25 && p[2] > J.synsacrum[2])) {
158
- // hackles: narrow feathers flowing down the neck and over the shoulders
159
- tract = 'hackle';
160
- col = mix3(Pal.hackle, Pal.hackleTip, smoothstep(0.2, 1, ny) * 0.6);
161
- size = male ? 0.014 : 0.016; fl = male ? 0.009 : 0.005; gloss = male ? 0.55 : 0.4; irid = irid0 * 0.35;
162
- // the breast below the hackles (roosters: black breast)
163
- if (up < -0.1 && p[2] > J.neckBase[2]) { col = mix3(col, Pal.breast, smoothstep(-0.1, -0.5, up)); tract = 'breast'; }
164
- } else {
165
- col = mix3(Pal.breast, Pal.back, dorsal);
166
- size = p[2] > 0.02 ? 0.02 : 0.024;
167
- fl = mix(0.007, 0.0035, dorsal); gloss = mix(0.3, 0.45, dorsal);
168
- irid = irid0 * mix(0.3, 0.9, dorsal);
169
- tract = dorsal > 0.5 ? 'back' : 'breast';
170
- // underparts: fluffy, light
171
- const under = smoothstep(0.2, -0.5, up) * smoothstep(0.175, 0.13, p[1]);
172
- col = mix3(col, Pal.fluff, under * (male && Pal.breed === 'red' ? 0.4 : 0.85));
173
- fl = mix(fl, Pal.juv ? 0.01 : 0.012, under);
174
- if (under > 0.5) tract = 'fluff';
175
- // saddle / rump: the back rising into the tail
176
- const sw = smoothstep(J.synsacrum[2] + 0.015, J.synsacrum[2] - 0.045, p[2]) * smoothstep(-0.35, 0.25, up) * (bn === 'tail' ? 0 : 1);
177
- if (sw > 0) {
178
- col = mix3(col, Pal.saddle, sw);
179
- if (male) { fl = mix(fl, 0.012, sw); size = mix(size, 0.012, sw); gloss = mix(gloss, 0.55, sw); if (sw > 0.5) tract = 'saddle'; }
180
- }
181
- if (bn === 'tail') { col = mix3(Pal.tail, Pal.saddle, 0.35); irid = Pal.tailIrid; tract = 'tail'; }
182
- // flow: along the body, bending down around the flanks and the breast
183
- if (up < 0.3) flow = norm(add(flow, [0, -0.7 * (1 - up), 0]));
184
- if (tract === 'saddle') flow = norm(add(flow, [0, -1.2, 0]));
185
- }
186
- if (Pal.juv) {
187
- // chick down: a soft ball, chipmunk stripes down the back on brown breeds, a pale belly
188
- // (in a crease whose skin turns down from the ball's radial direction - the wing's bed under the
189
- // folded wing - by the radial direction: the bed's upper wall showed as a pale band along the wing)
190
- const rd = norm(sub(p, [0, J.hipL[1] + 0.01, -0.01])), wR = 1 - smoothstep(0.6, 0.95, dot(n, rd));
191
- const upJ = Math.max(up, mix(up, rd[1], wR)), dorsalJ = smoothstep(-0.25, 0.45, upJ);
192
- col = mix3(Pal.fluff, Pal.body, smoothstep(-0.6, 0.2, upJ));
193
- if (dorsalJ > 0.4) col = mix3(col, Pal.back, 0.7);
194
- if (Pal.stripe && dorsal > 0.55) {
195
- const st = Math.abs(p[0]);
196
- const band = smoothstep(0.012, 0.006, Math.abs(st - 0.022)) + smoothstep(0.008, 0.003, st);
197
- col = mix3(col, Pal.stripe, clamp(band, 0, 1) * 0.85);
198
- }
199
- mat = MAT.FUR; fl = 0.012; size = 0.004; gloss = 0.2; irid = 0;
200
- }
201
- }
202
- // chicks: all down (fur shells), no contour feathers yet
203
- if (Pal.juv && mat === MAT.FEATHER) { mat = MAT.FUR; fl = Math.max(fl, 0.009); }
204
- // per-feather markings (shader), by tract
205
- if (mat === MAT.FEATHER && !Pal.juv) {
206
- for (const mk of marks) {
207
- if (mk.where !== 'all' && !mk.where.includes(tract)) continue;
208
- mz = markZ(mk.mode, mk.amt * (tract === 'fluff' ? 0.5 : 1));
209
- mcol = mk.col;
210
- break;
211
- }
212
- }
213
- // red roosters: hackle and saddle feathers with a dark centre stripe, black-green tail
214
- if (male && Pal.breed === 'red' && (tract === 'hackle' || tract === 'saddle')) { mz = markZ(MARK.shaft, 0.35); mcol = srgb(0x3a1a0a); }
215
- // low-frequency colour variation
216
- const cv = fbm3(p[0] * 30 + (params.seed || 0), p[1] * 30, p[2] * 30, 3) - 0.5;
217
- const kv = mat === MAT.FEATHER ? 0.22 : mat === MAT.SKIN ? 0.12 : 0.1;
218
- col = [col[0] * (1 + kv * cv), col[1] * (1 + kv * cv), col[2] * (1 + kv * 0.8 * cv)];
219
- // comb: tangent to the surface
220
- const f = sub(flow, mul(n, dot(flow, n)));
221
- const fN = norm(Math.hypot(...f) > 1e-6 ? f : cross(n, [1, 0, 0]));
222
- comb.set(fN, v * 3);
223
- tint[v * 4] = col[0]; tint[v * 4 + 1] = col[1]; tint[v * 4 + 2] = col[2]; tint[v * 4 + 3] = mat;
224
- furLen[v] = fl;
225
- surf[v * 4] = gloss; surf[v * 4 + 1] = size * (params.size || 1);
226
- surf[v * 4 + 2] = mat === MAT.FEATHER ? mz : 0;
227
- surf[v * 4 + 3] = mat === MAT.FEATHER ? irid : 0;
228
- if (mcol) { patCol[v * 4] = mcol[0]; patCol[v * 4 + 1] = mcol[1]; patCol[v * 4 + 2] = mcol[2]; patCol[v * 4 + 3] = 0; }
229
- }
230
- return { comb, tint, pattern, mark, furLen, surf, patternColor: patCol };
231
- }
232
-
233
- // flight-feather card colours per breed: primaries with a lighter outer edge on red birds, black-green
234
- // sickles and tail on red roosters, barred / spangled vanes
235
- export function chickenFeatherColour(params) {
236
- const Pal = palette(params);
237
- const male = params.sex === 'male';
238
- return (kind, i, side, t, c, layer) => {
239
- const top = layer > 0;
240
- const covert = kind.endsWith('Covert');
241
- let rgb = Pal.flight, irid = 0, gloss = 0.4;
242
- if (kind === 'rectrix' || kind === 'tailCovert') { rgb = Pal.tail; irid = Pal.tailIrid; gloss = 0.5; }
243
- // (a spangled breed's flight feathers are mahogany edged, white only at the spangled tips)
244
- if (kind === 'primary' && c < -0.3) rgb = mix3(rgb, Pal.spangled ? mix3(Pal.body, Pal.flightEdge, 0.2) : Pal.flightEdge, 0.35);
245
- if (kind === 'primary' || kind === 'secondary') gloss = 0.22;
246
- if (kind === 'secondary' && top) {
247
- // folded, the secondaries show their outer vanes as a stack of edges below the covert shield:
248
- // a lighter fringe on each outer vane reads as feathers (a flat dark panel read as one plastic
249
- // slab); the tertials (innermost) lie on top along the back and are coloured like the coverts
250
- const lace = Pal.marks?.find((m) => m.mode === MARK.lace)?.col;
251
- // (each feather darker along its shaft and lighter toward its edges: the overlapping feathers
252
- // of the panel read one by one, not as a flat slab)
253
- const ac = Math.abs(c);
254
- // (a spangled breed's secondaries are mahogany with white tips, not white-edged)
255
- const edge = Pal.spangled ? mix3(Pal.body, Pal.flightEdge, 0.2) : Pal.flightEdge;
256
- // (vanes render lighter than the shingled skin around them: a little darker than the coverts)
257
- if (i >= 7) rgb = mix3(mix3(mix3(Pal.bow, Pal.flight, 0.45), lace || edge, 0.3 * ac), Pal.flight, 0.5 * (1 - ac) * (1 - t * 0.5)).map((x) => x * 0.82);
258
- else rgb = c < 0 ? mix3(rgb, edge, 0.6) : mix3(rgb, Pal.bow, 0.2);
259
- }
260
- if (covert && kind !== 'tailCovert') rgb = mix3(Pal.bow, Pal.body, 0.3);
261
- // the greater coverts along the folded wing's shield (coverts.js): the shield's colour, a slightly
262
- // darker base, no light fringe (a row of pale edges read as a comb)
263
- if (kind === 'wingCovert') rgb = mix3(Pal.bow, Pal.back, 0.3).map((x) => x * (0.7 + 0.12 * t));
264
- if (kind === 'tailCovert' && male && Pal.breed === 'red') { rgb = Pal.tail; irid = 0.8; }
265
- if (kind === 'tailCovert' && !male) rgb = mix3(Pal.saddle, Pal.tail, 0.2);
266
- // barred: light vanes with dark bars across them, drawn in the shader (a few per-vertex bars on a
267
- // card averaged to a plain grey band)
268
- let bar = null;
269
- if (Pal.barred) { rgb = srgb(0xd8d8d0); bar = { rgb: mix3(srgb(0xd8d8d0), srgb(0x1e1e20), male ? 0.66 : 0.78), period: kind === 'primary' || kind === 'rectrix' ? 0.0075 : 0.0062 }; }
270
- // (a chick's down has no spangles: its palette keeps the breed flag but no feather marks)
271
- if (Pal.spangled && Pal.marks.length && t > 0.85) rgb = mix3(rgb, Pal.marks[0].col, kind === 'primary' || kind === 'secondary' ? smoothstep(0.85, 1, t) : 1);
272
- if (!top) rgb = mix3(rgb, srgb(0x9a948c), 0.15);
273
- const k = 1 + (kind === 'secondary' ? 0.1 : 0.06) * Math.sin(i * 12.9898 + side * 3.1 + t * 2.1);
274
- return { rgb: [rgb[0] * k, rgb[1] * k, rgb[2] * k], gloss: top ? gloss : 0.3, irid: top ? irid : irid * 0.2, bar };
275
- };
276
- }
277
-
278
- // the greater covert cards on the folded wing (coverts.js) shaded as the shield's contour feathers
279
- // (material FEATHER: big shingles, the wing tract's colour and markings except the lace, which the
280
- // shingle shader would draw across a card; matte: a glossy card caught the sky as a lavender band)
281
- export function chickenWingCovertLook(params) {
282
- const Pal = palette(params);
283
- let mz = 0, mcol = null;
284
- for (const mk of Pal.marks || []) {
285
- if (mk.mode === MARK.lace) continue;
286
- if (mk.where !== 'all' && !mk.where.includes('wing')) continue;
287
- mz = markZ(mk.mode, mk.amt); mcol = mk.col; break;
288
- }
289
- // (no fur shells on a card: darker than the shield's base colour, whose down shells darken it)
290
- // (a rooster's wing is his dark bow colour: mixed with his bright back it read as an orange patch)
291
- const base = Pal.male ? mix3(Pal.bow, Pal.flight, 0.2) : mix3(Pal.bow, Pal.back, 0.4);
292
- return { rgb: base.map((x) => x * 0.99), gloss: 0.1, size: 0.035 * (params.size || 1), mz, mcol, irid: Pal.irid ? Pal.irid * 0.35 : 0, fur: 0.003 };
293
- }
294
-
295
- // the tertials on the folded wing (index.js restyle: their top layers shaded as contour feathers with down):
296
- // the wing tract's colour and markings, lacing included (they are big enough for the shingle shader's lace)
297
- export function chickenTertialLook(params) {
298
- const Pal = palette(params), L0 = chickenWingCovertLook(params);
299
- let mz = L0.mz, mcol = L0.mcol;
300
- for (const mk of Pal.marks || []) {
301
- if (mk.where !== 'all' && !mk.where.includes('wing')) continue;
302
- mz = markZ(mk.mode, mk.amt); mcol = mk.col; break;
303
- }
304
- return { ...L0, rgb: L0.rgb.map((x) => x * 1.15), size: 0.022 * (params.size || 1), gloss: 0.3, mz, mcol };
305
- }
306
-
307
- // a chick's wing cards restyled as down (wingLook.js downyWing): the top the down of the folded wing's
308
- // bed (back over body), the underside the pale underwing
309
- export function chickWingDownLook(params) {
310
- const Pal = palette(params);
311
- const top = mix3(Pal.back, Pal.body, 0.3);
312
- return { top, under: mix3(top, Pal.fluff, 0.35), fur: 0.012, furUnder: 0.004, furTip: 0.7, size: 0.004 * (params.size || 1), gloss: 0.2 };
313
- }