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