@bitefoundry/retrieviewer 0.0.3 → 0.0.5
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.
- package/ASSET-PROVENANCE.md +11 -0
- package/ASSETS-LICENSE.md +2 -1
- package/ATTRIBUTION.md +6 -1
- package/COMFORT-ART.md +95 -0
- package/DESKTOP-PLATFORMS.md +6 -1
- package/INSTALLING.md +4 -0
- package/PLUGIN.md +13 -10
- package/PREREQUISITES.md +95 -0
- package/PUPPY-MEMORY.md +102 -1
- package/README.ko.md +116 -0
- package/README.md +121 -59
- package/RELEASING.md +33 -13
- package/THIRD-PARTY-NOTICES.md +5 -3
- package/braille.mjs +35 -9
- package/examples/live.mjs +2 -2
- package/integrations/linux-overlay/overlay.py +8 -2
- package/integrations/macos-overlay/overlay.jxa +9 -7
- package/integrations/opencode/runtime.mjs +4 -4
- package/integrations/opencode/tui.tsx +1 -1
- package/integrations/windows-overlay/Overlay.cs +7 -6
- package/integrations/windows-overlay/desktop.mjs +2 -1
- package/integrations/windows-overlay/protocol.mjs +13 -7
- package/integrations/windows-overlay/worker.mjs +1 -1
- package/package.json +34 -13
- package/puppy-comfort-sprites.mjs +33 -0
- package/puppy-companion-comfort-q5.bin.gz +0 -0
- package/puppy-companion-comfort.json +140 -0
- package/puppy-companion-life.mjs +58 -18
- package/puppy-companion-objects.mjs +12 -0
- package/puppy-companion-sprites.mjs +4 -2
- package/puppy-frame-predictive.mjs +15 -9
- package/puppy-frame-store.mjs +2 -2
- package/puppy-paper-actions.mjs +4 -2
- package/puppy-paper-behaviors.mjs +1 -1
- package/puppy-paper-contact.mjs +4 -2
- package/puppy-paper-seat.mjs +4 -2
- package/puppy-paper-world.mjs +14 -0
- package/puppy-paper.mjs +79 -21
- package/retrieviewer-cli.mjs +8 -6
- package/retrieviewer-plugin.d.mts +1 -1
- package/retrieviewer-plugin.mjs +1 -1
- package/retrieviewer.d.mts +12 -4
- package/retrieviewer.mjs +20 -14
- package/locomotion-core.mjs +0 -21
- package/locomotion-puppy.animal +0 -0
- package/vendor/procedural-animals/package.json +0 -40
- package/vendor/procedural-animals/src/animal.js +0 -146
- package/vendor/procedural-animals/src/bake.js +0 -51
- package/vendor/procedural-animals/src/build.js +0 -81
- package/vendor/procedural-animals/src/core/build/coatKit.js +0 -121
- package/vendor/procedural-animals/src/core/build/featherCards.js +0 -189
- package/vendor/procedural-animals/src/core/build/finEdges.js +0 -85
- package/vendor/procedural-animals/src/core/build/furSlope.js +0 -115
- package/vendor/procedural-animals/src/core/build/mesh.js +0 -67
- package/vendor/procedural-animals/src/core/build/pipeline.js +0 -272
- package/vendor/procedural-animals/src/core/build/seams.js +0 -183
- package/vendor/procedural-animals/src/core/build/warp.js +0 -112
- package/vendor/procedural-animals/src/core/build/weights.js +0 -393
- package/vendor/procedural-animals/src/core/math/vec.js +0 -81
- package/vendor/procedural-animals/src/core/motion/actions.js +0 -800
- package/vendor/procedural-animals/src/core/motion/bird.js +0 -3063
- package/vendor/procedural-animals/src/core/motion/birdActions.js +0 -1059
- package/vendor/procedural-animals/src/core/motion/common.js +0 -158
- package/vendor/procedural-animals/src/core/motion/index.js +0 -22
- package/vendor/procedural-animals/src/core/motion/quadruped.js +0 -2875
- package/vendor/procedural-animals/src/core/motion/snake.js +0 -1594
- package/vendor/procedural-animals/src/core/motion/spider.js +0 -1810
- package/vendor/procedural-animals/src/core/motion/swimmer.js +0 -1047
- package/vendor/procedural-animals/src/core/motion/swimmerActions.js +0 -613
- package/vendor/procedural-animals/src/core/render/animalObject.js +0 -262
- package/vendor/procedural-animals/src/core/render/coatMaterial.js +0 -1301
- package/vendor/procedural-animals/src/core/render/dqs.js +0 -159
- package/vendor/procedural-animals/src/core/render/eyes.js +0 -676
- package/vendor/procedural-animals/src/core/render/membranes.js +0 -77
- package/vendor/procedural-animals/src/core/render/skeleton.js +0 -41
- package/vendor/procedural-animals/src/core/rig/bird.js +0 -327
- package/vendor/procedural-animals/src/core/rig/quadruped.js +0 -76
- package/vendor/procedural-animals/src/core/rig/rig.js +0 -79
- package/vendor/procedural-animals/src/core/rig/snake.js +0 -76
- package/vendor/procedural-animals/src/core/rig/spider.js +0 -110
- package/vendor/procedural-animals/src/core/rig/swimmer.js +0 -181
- package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +0 -53
- package/vendor/procedural-animals/src/core/sdf/mesher.js +0 -238
- package/vendor/procedural-animals/src/core/sdf/sdf.js +0 -263
- package/vendor/procedural-animals/src/index.d.ts +0 -98
- package/vendor/procedural-animals/src/index.js +0 -29
- package/vendor/procedural-animals/src/registry.js +0 -48
- package/vendor/procedural-animals/src/species/bear/behaviour.js +0 -463
- package/vendor/procedural-animals/src/species/bear/claws.js +0 -147
- package/vendor/procedural-animals/src/species/bear/coat.js +0 -726
- package/vendor/procedural-animals/src/species/bear/index.js +0 -139
- package/vendor/procedural-animals/src/species/bear/motion.js +0 -112
- package/vendor/procedural-animals/src/species/bear/regions.js +0 -78
- package/vendor/procedural-animals/src/species/bear/rig.js +0 -112
- package/vendor/procedural-animals/src/species/bear/sculpt.js +0 -272
- package/vendor/procedural-animals/src/species/boar/behaviour.js +0 -335
- package/vendor/procedural-animals/src/species/boar/coat.js +0 -372
- package/vendor/procedural-animals/src/species/boar/index.js +0 -110
- package/vendor/procedural-animals/src/species/boar/motion.js +0 -85
- package/vendor/procedural-animals/src/species/boar/regions.js +0 -88
- package/vendor/procedural-animals/src/species/boar/rig.js +0 -111
- package/vendor/procedural-animals/src/species/boar/sculpt.js +0 -285
- package/vendor/procedural-animals/src/species/cat/behaviour.js +0 -559
- package/vendor/procedural-animals/src/species/cat/coat.js +0 -841
- package/vendor/procedural-animals/src/species/cat/index.js +0 -211
- package/vendor/procedural-animals/src/species/cat/motion.js +0 -101
- package/vendor/procedural-animals/src/species/cat/regions.js +0 -82
- package/vendor/procedural-animals/src/species/cat/rig.js +0 -100
- package/vendor/procedural-animals/src/species/cat/sculpt.js +0 -266
- package/vendor/procedural-animals/src/species/cat/whiskers.js +0 -110
- package/vendor/procedural-animals/src/species/cheetah/coat.js +0 -427
- package/vendor/procedural-animals/src/species/cheetah/index.js +0 -51
- package/vendor/procedural-animals/src/species/cheetah/joints.js +0 -3
- package/vendor/procedural-animals/src/species/cheetah/motion.js +0 -77
- package/vendor/procedural-animals/src/species/cheetah/regions.js +0 -95
- package/vendor/procedural-animals/src/species/cheetah/rig.js +0 -66
- package/vendor/procedural-animals/src/species/cheetah/sculpt.js +0 -158
- package/vendor/procedural-animals/src/species/chicken/coat.js +0 -313
- package/vendor/procedural-animals/src/species/chicken/coverts.js +0 -320
- package/vendor/procedural-animals/src/species/chicken/index.js +0 -110
- package/vendor/procedural-animals/src/species/chicken/motion.js +0 -177
- package/vendor/procedural-animals/src/species/chicken/regions.js +0 -66
- package/vendor/procedural-animals/src/species/chicken/rig.js +0 -144
- package/vendor/procedural-animals/src/species/chicken/sculpt.js +0 -389
- package/vendor/procedural-animals/src/species/chicken/wingLook.js +0 -66
- package/vendor/procedural-animals/src/species/chicken/wingStack.js +0 -124
- package/vendor/procedural-animals/src/species/cow/behaviour.js +0 -521
- package/vendor/procedural-animals/src/species/cow/coat.js +0 -465
- package/vendor/procedural-animals/src/species/cow/index.js +0 -118
- package/vendor/procedural-animals/src/species/cow/motion.js +0 -81
- package/vendor/procedural-animals/src/species/cow/regions.js +0 -98
- package/vendor/procedural-animals/src/species/cow/rig.js +0 -116
- package/vendor/procedural-animals/src/species/cow/sculpt.js +0 -339
- package/vendor/procedural-animals/src/species/crow/coat.js +0 -145
- package/vendor/procedural-animals/src/species/crow/index.js +0 -70
- package/vendor/procedural-animals/src/species/crow/joints.js +0 -3
- package/vendor/procedural-animals/src/species/crow/motion.js +0 -101
- package/vendor/procedural-animals/src/species/crow/regions.js +0 -50
- package/vendor/procedural-animals/src/species/crow/rig.js +0 -83
- package/vendor/procedural-animals/src/species/crow/sculpt.js +0 -118
- package/vendor/procedural-animals/src/species/deer/behaviour.js +0 -513
- package/vendor/procedural-animals/src/species/deer/coat.js +0 -391
- package/vendor/procedural-animals/src/species/deer/index.js +0 -106
- package/vendor/procedural-animals/src/species/deer/motion.js +0 -97
- package/vendor/procedural-animals/src/species/deer/regions.js +0 -60
- package/vendor/procedural-animals/src/species/deer/rig.js +0 -124
- package/vendor/procedural-animals/src/species/deer/sculpt.js +0 -297
- package/vendor/procedural-animals/src/species/dog/behaviour.js +0 -521
- package/vendor/procedural-animals/src/species/dog/coat.js +0 -495
- package/vendor/procedural-animals/src/species/dog/index.js +0 -144
- package/vendor/procedural-animals/src/species/dog/motion.js +0 -118
- package/vendor/procedural-animals/src/species/dog/regions.js +0 -61
- package/vendor/procedural-animals/src/species/dog/rig.js +0 -129
- package/vendor/procedural-animals/src/species/dog/sculpt.js +0 -246
- package/vendor/procedural-animals/src/species/eagle/coat.js +0 -250
- package/vendor/procedural-animals/src/species/eagle/index.js +0 -76
- package/vendor/procedural-animals/src/species/eagle/joints.js +0 -3
- package/vendor/procedural-animals/src/species/eagle/motion.js +0 -137
- package/vendor/procedural-animals/src/species/eagle/regions.js +0 -57
- package/vendor/procedural-animals/src/species/eagle/rig.js +0 -107
- package/vendor/procedural-animals/src/species/eagle/sculpt.js +0 -137
- package/vendor/procedural-animals/src/species/fish/coat.js +0 -271
- package/vendor/procedural-animals/src/species/fish/index.js +0 -88
- package/vendor/procedural-animals/src/species/fish/motion.js +0 -92
- package/vendor/procedural-animals/src/species/fish/regions.js +0 -27
- package/vendor/procedural-animals/src/species/fish/rig.js +0 -143
- package/vendor/procedural-animals/src/species/fish/sculpt.js +0 -214
- package/vendor/procedural-animals/src/species/fish/variants.js +0 -126
- package/vendor/procedural-animals/src/species/fox/behaviour.js +0 -314
- package/vendor/procedural-animals/src/species/fox/coat.js +0 -444
- package/vendor/procedural-animals/src/species/fox/index.js +0 -120
- package/vendor/procedural-animals/src/species/fox/motion.js +0 -81
- package/vendor/procedural-animals/src/species/fox/regions.js +0 -59
- package/vendor/procedural-animals/src/species/fox/rig.js +0 -91
- package/vendor/procedural-animals/src/species/fox/sculpt.js +0 -202
- package/vendor/procedural-animals/src/species/frog/behaviour.js +0 -590
- package/vendor/procedural-animals/src/species/frog/coat.js +0 -305
- package/vendor/procedural-animals/src/species/frog/index.js +0 -97
- package/vendor/procedural-animals/src/species/frog/motion.js +0 -69
- package/vendor/procedural-animals/src/species/frog/regions.js +0 -46
- package/vendor/procedural-animals/src/species/frog/rig.js +0 -156
- package/vendor/procedural-animals/src/species/frog/sculpt.js +0 -240
- package/vendor/procedural-animals/src/species/goat/behaviour.js +0 -509
- package/vendor/procedural-animals/src/species/goat/coat.js +0 -590
- package/vendor/procedural-animals/src/species/goat/index.js +0 -149
- package/vendor/procedural-animals/src/species/goat/motion.js +0 -95
- package/vendor/procedural-animals/src/species/goat/regions.js +0 -98
- package/vendor/procedural-animals/src/species/goat/rig.js +0 -181
- package/vendor/procedural-animals/src/species/goat/sculpt.js +0 -547
- package/vendor/procedural-animals/src/species/horse/coat.js +0 -361
- package/vendor/procedural-animals/src/species/horse/coatSeam.js +0 -122
- package/vendor/procedural-animals/src/species/horse/index.js +0 -80
- package/vendor/procedural-animals/src/species/horse/motion.js +0 -245
- package/vendor/procedural-animals/src/species/horse/regions.js +0 -60
- package/vendor/procedural-animals/src/species/horse/rig.js +0 -117
- package/vendor/procedural-animals/src/species/horse/sculpt.js +0 -316
- package/vendor/procedural-animals/src/species/horse/seamWeights.js +0 -272
- package/vendor/procedural-animals/src/species/lion/behaviour.js +0 -509
- package/vendor/procedural-animals/src/species/lion/coat.js +0 -1016
- package/vendor/procedural-animals/src/species/lion/index.js +0 -111
- package/vendor/procedural-animals/src/species/lion/motion.js +0 -87
- package/vendor/procedural-animals/src/species/lion/regions.js +0 -106
- package/vendor/procedural-animals/src/species/lion/rig.js +0 -110
- package/vendor/procedural-animals/src/species/lion/sculpt.js +0 -384
- package/vendor/procedural-animals/src/species/lion/whiskers.js +0 -132
- package/vendor/procedural-animals/src/species/pig/behaviour.js +0 -575
- package/vendor/procedural-animals/src/species/pig/coat.js +0 -730
- package/vendor/procedural-animals/src/species/pig/ears.js +0 -242
- package/vendor/procedural-animals/src/species/pig/index.js +0 -161
- package/vendor/procedural-animals/src/species/pig/motion.js +0 -105
- package/vendor/procedural-animals/src/species/pig/regions.js +0 -100
- package/vendor/procedural-animals/src/species/pig/rig.js +0 -152
- package/vendor/procedural-animals/src/species/pig/sculpt.js +0 -382
- package/vendor/procedural-animals/src/species/rabbit/behaviour.js +0 -605
- package/vendor/procedural-animals/src/species/rabbit/coat.js +0 -285
- package/vendor/procedural-animals/src/species/rabbit/index.js +0 -85
- package/vendor/procedural-animals/src/species/rabbit/motion.js +0 -85
- package/vendor/procedural-animals/src/species/rabbit/regions.js +0 -48
- package/vendor/procedural-animals/src/species/rabbit/rig.js +0 -99
- package/vendor/procedural-animals/src/species/rabbit/sculpt.js +0 -148
- package/vendor/procedural-animals/src/species/rat/behaviour.js +0 -539
- package/vendor/procedural-animals/src/species/rat/coat.js +0 -341
- package/vendor/procedural-animals/src/species/rat/index.js +0 -111
- package/vendor/procedural-animals/src/species/rat/motion.js +0 -90
- package/vendor/procedural-animals/src/species/rat/regions.js +0 -92
- package/vendor/procedural-animals/src/species/rat/rig.js +0 -112
- package/vendor/procedural-animals/src/species/rat/sculpt.js +0 -163
- package/vendor/procedural-animals/src/species/rat/whiskers.js +0 -119
- package/vendor/procedural-animals/src/species/shark/coat.js +0 -383
- package/vendor/procedural-animals/src/species/shark/index.js +0 -104
- package/vendor/procedural-animals/src/species/shark/motion.js +0 -69
- package/vendor/procedural-animals/src/species/shark/regions.js +0 -34
- package/vendor/procedural-animals/src/species/shark/rig.js +0 -194
- package/vendor/procedural-animals/src/species/shark/sculpt.js +0 -343
- package/vendor/procedural-animals/src/species/shark/variants.js +0 -105
- package/vendor/procedural-animals/src/species/sheep/behaviour.js +0 -522
- package/vendor/procedural-animals/src/species/sheep/coat.js +0 -529
- package/vendor/procedural-animals/src/species/sheep/index.js +0 -152
- package/vendor/procedural-animals/src/species/sheep/motion.js +0 -86
- package/vendor/procedural-animals/src/species/sheep/neck.js +0 -41
- package/vendor/procedural-animals/src/species/sheep/regions.js +0 -62
- package/vendor/procedural-animals/src/species/sheep/rig.js +0 -163
- package/vendor/procedural-animals/src/species/sheep/sculpt.js +0 -542
- package/vendor/procedural-animals/src/species/snake/coat.js +0 -315
- package/vendor/procedural-animals/src/species/snake/index.js +0 -73
- package/vendor/procedural-animals/src/species/snake/motion.js +0 -51
- package/vendor/procedural-animals/src/species/snake/regions.js +0 -51
- package/vendor/procedural-animals/src/species/snake/rig.js +0 -108
- package/vendor/procedural-animals/src/species/snake/sculpt.js +0 -122
- package/vendor/procedural-animals/src/species/spider/coat.js +0 -279
- package/vendor/procedural-animals/src/species/spider/index.js +0 -78
- package/vendor/procedural-animals/src/species/spider/motion.js +0 -72
- package/vendor/procedural-animals/src/species/spider/regions.js +0 -87
- package/vendor/procedural-animals/src/species/spider/rig.js +0 -118
- package/vendor/procedural-animals/src/species/spider/sculpt.js +0 -182
- package/vendor/procedural-animals/src/species/wolf/behaviour.js +0 -160
- package/vendor/procedural-animals/src/species/wolf/coat.js +0 -749
- package/vendor/procedural-animals/src/species/wolf/index.js +0 -107
- package/vendor/procedural-animals/src/species/wolf/motion.js +0 -80
- package/vendor/procedural-animals/src/species/wolf/regions.js +0 -57
- package/vendor/procedural-animals/src/species/wolf/rig.js +0 -87
- package/vendor/procedural-animals/src/species/wolf/sculpt.js +0 -339
- 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
|
-
}
|