@bitefoundry/retrieviewer 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +75 -0
- package/INSTALLING.md +8 -5
- 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 +119 -58
- package/RELEASING.md +27 -14
- package/THIRD-PARTY-NOTICES.md +5 -3
- package/braille.mjs +35 -9
- package/examples/live.mjs +2 -2
- package/integrations/desktop/platform.mjs +27 -0
- package/integrations/linux-overlay/README.md +83 -0
- package/integrations/linux-overlay/overlay.py +1094 -0
- package/integrations/macos-overlay/README.md +83 -0
- package/integrations/macos-overlay/overlay.jxa +639 -0
- 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/desktop.mjs +40 -8
- package/integrations/windows-overlay/protocol.mjs +11 -7
- package/integrations/windows-overlay/worker.mjs +13 -7
- package/package.json +41 -14
- 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-cli.mjs +10 -3
- 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,149 +0,0 @@
|
|
|
1
|
-
// Domestic goat (Capra hircus). Cloven-hoofed browser: the horse's hoof rig (pastern + hoof bone)
|
|
2
|
-
// with two claws per foot, scimitar horns (a rigid keratin surface on the skull), beard and wattles,
|
|
3
|
-
// horizontal bar pupils in pale amber irises, the short tail carried up, cud chewing, browsing on the
|
|
4
|
-
// hind legs and the rearing head clash.
|
|
5
|
-
import { goatRig, goatJoints, HEAD_O } from './rig.js';
|
|
6
|
-
import { add, sub, mul } from '../../core/math/vec.js';
|
|
7
|
-
import { sculptGoat, EYE } from './sculpt.js';
|
|
8
|
-
import { goatRegions } from './regions.js';
|
|
9
|
-
import { goatCoat } from './coat.js';
|
|
10
|
-
import { srgb } from '../../core/build/coatKit.js';
|
|
11
|
-
import { rng } from '../../core/math/vec.js';
|
|
12
|
-
import { motion } from './motion.js';
|
|
13
|
-
import { QUALITY } from '../../core/build/pipeline.js';
|
|
14
|
-
|
|
15
|
-
// a kid's short neck: the head and the upper neck move down the neck by 20 % of its length (12 % for lop ears: further,
|
|
16
|
-
// the hanging ear's tip ran into the throat), shortening the neck above its lowest 15 % (from the neck base the shift
|
|
17
|
-
// reached the scapulae, and the Nubian kid's sprint jittered at the wrist, p99 0.084 % S)
|
|
18
|
-
const J0 = goatJoints();
|
|
19
|
-
const NECK_BASE = add(J0.neckBase, mul(sub(J0.occiput, J0.neckBase), 0.15));
|
|
20
|
-
const kidNeck = (lop) => mul(sub(J0.occiput, J0.neckBase), lop ? -0.12 : -0.2);
|
|
21
|
-
|
|
22
|
-
const pick = (R, table) => {
|
|
23
|
-
let x = R() * table.reduce((s, [, w]) => s + w, 0);
|
|
24
|
-
for (const [k, w] of table) { x -= w; if (x <= 0) return k; }
|
|
25
|
-
return table[table.length - 1][0];
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Breeds (variants) and their coats (coat.js COATS). salt: the breed's own seed stream, so a seed gives
|
|
29
|
-
// a different animal in every breed (with one stream, seed N was the same individual in five coats and
|
|
30
|
-
// seeds 1-2 were kids in every breed); picked so that seed 1 is a horned adult doe (the reference
|
|
31
|
-
// individual, the tools' default) and seeds 2-4 hold a horned buck, a kid and a doe
|
|
32
|
-
const BREEDS = {
|
|
33
|
-
saanen: { salt: 158, coats: [['saanen', 1]], polled: 0.4, ear: 'erect', roman: 0, legs: 1, girth: 1, horn: 0xb4a07c },
|
|
34
|
-
alpine: { salt: 746, coats: [['chamoisee', 40], ['coublanc', 25], ['toggenburg', 20], ['britishalpine', 15]], polled: 0.35, ear: 'erect', roman: 0, legs: 1.0, girth: 0.98, horn: 0x8a7050 },
|
|
35
|
-
pied: { salt: 208, coats: [['pied', 60], ['piedbrown', 40]], polled: 0.3, ear: 'erect', roman: 0.15, legs: 0.98, girth: 1.02, horn: 0x9e8058 },
|
|
36
|
-
nubian: { salt: 398, coats: [['nubianred', 40], ['nubiantan', 35], ['nubianblack', 25]], polled: 0.5, ear: 'lop', roman: 1, legs: 1.06, girth: 0.97, horn: 0x7a6248 },
|
|
37
|
-
boer: { salt: 165, coats: [['boer', 1]], polled: 0.05, ear: 'lop', roman: 0.7, legs: 0.9, girth: 1.1, horn: 0x5e4c3a },
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export default {
|
|
41
|
-
id: 'goat',
|
|
42
|
-
name: 'Goat',
|
|
43
|
-
latin: 'Capra hircus',
|
|
44
|
-
group: 'hooves',
|
|
45
|
-
plan: 'quadruped',
|
|
46
|
-
covering: 'fur',
|
|
47
|
-
variants: Object.keys(BREEDS),
|
|
48
|
-
|
|
49
|
-
// Seeded individual. Breed (o.variant: saanen, alpine, pied, nubian, boer) sets coat colours, ears,
|
|
50
|
-
// Roman nose and build; sex: doe (udder) or buck (heavier, broader, a mane and "pants", big horns,
|
|
51
|
-
// long beard); age: adult or kid (juvenile: long legs, short body, big head, horn buds, fluffy
|
|
52
|
-
// coat). Horns (scimitar, larger in bucks) or polled; beard (bucks, many does); wattles (some).
|
|
53
|
-
variation(R0, o) {
|
|
54
|
-
// (a re-mixed stream: the early draws of neighbouring seeds were correlated, e.g. 16 of seeds 1-20
|
|
55
|
-
// came out polled)
|
|
56
|
-
const salt = BREEDS[o.variant] ? BREEDS[o.variant].salt : 0;
|
|
57
|
-
const R = rng(Math.floor(R0() * 4294967296) ^ Math.imul(o.seed ?? 1, 0x9e3779b1) ^ 0x2545f491 ^ Math.imul(salt, 0x85ebca6b));
|
|
58
|
-
const variant = BREEDS[o.variant] ? o.variant : pick(R, [['saanen', 30], ['alpine', 30], ['pied', 20], ['nubian', 15], ['boer', 5]]);
|
|
59
|
-
const Bd = BREEDS[variant];
|
|
60
|
-
const sex = o.sex || (R() < 0.45 ? 'male' : 'female');
|
|
61
|
-
const age = o.age || (R() < 0.15 ? 'juvenile' : 'adult');
|
|
62
|
-
const kid = age === 'juvenile';
|
|
63
|
-
const buck = sex === 'male' && !kid;
|
|
64
|
-
const g = () => (R() + R() + R() - 1.5) / 1.5; // ~[-1, 1], peaked
|
|
65
|
-
const coat = pick(R, Bd.coats);
|
|
66
|
-
const polled = R() < Bd.polled;
|
|
67
|
-
let horns = null;
|
|
68
|
-
if (!polled) {
|
|
69
|
-
if (kid) horns = { len: 0.02 + 0.01 * R(), base: 0.008, curve: 0.2, spread: 0.12, upright: 0.3 };
|
|
70
|
-
else if (buck) horns = { len: 0.3 + 0.18 * R(), base: 0.024 + 0.006 * R(), curve: 1.6 + 0.5 * R(), spread: 0.18 + 0.16 * R(), upright: 0.1 * R() };
|
|
71
|
-
else horns = { len: 0.14 + 0.1 * R(), base: 0.0125 + 0.0035 * R(), curve: 0.9 + 0.45 * R(), spread: 0.08 + 0.1 * R(), upright: 0.2 * R() };
|
|
72
|
-
}
|
|
73
|
-
const beardP = variant === 'nubian' || variant === 'boer' ? 0.3 : 0.65;
|
|
74
|
-
const beard = kid ? 0 : buck ? 0.12 + 0.1 * R() : R() < beardP ? 0.05 + 0.07 * R() : 0;
|
|
75
|
-
const size = (buck ? 1.12 : 1) * (1 + 0.045 * g()) * (variant === 'nubian' ? 1.04 : 1) * (kid ? 0.58 : 1);
|
|
76
|
-
return {
|
|
77
|
-
sex, age, size, variant, coat,
|
|
78
|
-
horns, beard,
|
|
79
|
-
wattles: R() < 0.3,
|
|
80
|
-
earLift: R(),
|
|
81
|
-
ear: Bd.ear,
|
|
82
|
-
// (a kid's face is straight: the Roman arch grows in with age, and on a kid's short face it swelled)
|
|
83
|
-
roman: Bd.roman * (0.75 + 0.25 * R()) * (kid ? 0.35 : 1),
|
|
84
|
-
udder: sex === 'female' && !kid ? 0.2 + 0.8 * R() : 0,
|
|
85
|
-
heavy: buck ? 0.7 + 0.3 * R() : 0,
|
|
86
|
-
mane: buck ? 0.4 + 0.6 * R() : 0,
|
|
87
|
-
// (the long-haired landrace roll only: every buck had a 0.25 share of its skirt, which made every buck's barrel
|
|
88
|
-
// a sheep's fleece; a dairy buck's body coat is as short and sleek as a doe's)
|
|
89
|
-
shaggy: (variant === 'alpine' && R() < 0.25 ? 0.4 : 0),
|
|
90
|
-
hornColor: Bd.horn,
|
|
91
|
-
coatShade: g(), coatLightness: 0.05 * g(),
|
|
92
|
-
coatSeed: Math.floor(R() * 1e6),
|
|
93
|
-
// (the quality tier's mesh scale: the horns' cells, their least thickness and their sculpted growth ridges follow it)
|
|
94
|
-
tierRes: (QUALITY[o.quality] || QUALITY.high).res,
|
|
95
|
-
minThick: 0.005, // (thin parts at the coarse tiers: at 8 mm the erect ear's floor under its cup showed pinholes at medium)
|
|
96
|
-
warps: [
|
|
97
|
-
// a kid's neck is short (kid_side, front2: the head carried forward at about the height of the withers; with
|
|
98
|
-
// the adult's neck its upright neck and high head read as a llama)
|
|
99
|
-
...(kid ? [{ type: 'shift', a: NECK_BASE, b: J0.occiput, d: kidNeck(Bd.ear === 'lop') }] : []),
|
|
100
|
-
// (the head scale next: its centre is the head origin, where the shift has moved it)
|
|
101
|
-
{ type: 'scaleAbout', c: kid ? add(HEAD_O, kidNeck(Bd.ear === 'lop')) : HEAD_O, k: (1 + 0.035 * g()) * (kid ? 1.18 : 1) * (buck ? 1.06 : 1), r0: 0.1, r1: 0.2 },
|
|
102
|
-
{ type: 'legs', k: (1 + 0.035 * g()) * Bd.legs * (kid ? 1.18 : 1), top: 0.46 },
|
|
103
|
-
{ type: 'length', k: (1 + 0.035 * g()) * (kid ? 0.84 : 1), z0: -0.32, z1: 0.32 },
|
|
104
|
-
{ type: 'girth', k: (1 + 0.04 * g()) * Bd.girth * (buck ? 1.06 : 1) * (kid ? 0.92 : 1), cy: 0.56, z0: -0.4, z1: 0.38 },
|
|
105
|
-
],
|
|
106
|
-
};
|
|
107
|
-
},
|
|
108
|
-
rig: (params) => goatRig(params),
|
|
109
|
-
sculpt: (m, rig, params) => sculptGoat(m, rig, params),
|
|
110
|
-
regions: goatRegions,
|
|
111
|
-
coat: goatCoat,
|
|
112
|
-
eyeSpecs: (params) => [1, -1].map((side) => ({ side, spec: EYE, headOrigin: HEAD_O, bone: 'head', look: eyeLook(params) })),
|
|
113
|
-
motion,
|
|
114
|
-
// (marks are the lash lines: soft brown-grey on pink-skinned white coats, dark otherwise)
|
|
115
|
-
// (clumpDensity is the density of the tufts, not the clumping strength: lower means bigger tufts. At 0.6
|
|
116
|
-
// the 9-11 mm coat broke into 6-14 mm tufts that read as astrakhan curls, and a buck's back at 0.45 as a
|
|
117
|
-
// pebbled rug; side2 / side3 / walk1 show a sleek coat of fine lengthwise hair. finWidth 0.4 gave the
|
|
118
|
-
// outline a regular zipper hem at hero)
|
|
119
|
-
// (a buck's sleek body takes the does' fine tufts, 1.5: his long mane clumps through its length anyway; 1.1 on every
|
|
120
|
-
// buck read as a fleece)
|
|
121
|
-
render: (params) => ({ markColor: srgb(pinkSkinned(params) ? 0x4a3934 : 0x241f1d), strandDensity: 1400, clumpDensity: longHair(params) ? 1.1 : params.sex === 'male' && params.age !== 'juvenile' ? 1.5 : 1.6, shellScale: 0.9, finWidth: 0.3, matBorders: true }),
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// The goat's signature eye: a strongly elongated horizontal bar pupil in a pale golden / amber iris
|
|
125
|
-
//, sclera hidden, dark lids. Some lines have blue-grey irises.
|
|
126
|
-
// (mid / hi lightened ~15 %: under the cornea they rendered darker than their hex, a dark bead)
|
|
127
|
-
const IRISES = [
|
|
128
|
-
{ inner: 0xb88f30, mid: 0xdcb24a, hi: 0xf0d284, outer: 0x6a4a18 }, // golden
|
|
129
|
-
{ inner: 0xa87f3c, mid: 0xe8d28a, hi: 0xf6e8b0, outer: 0x7a6030 }, // pale yellow
|
|
130
|
-
{ inner: 0x74501e, mid: 0xb08238, hi: 0xd49e52, outer: 0x3e2810 }, // brown-amber
|
|
131
|
-
{ inner: 0x5e7280, mid: 0xa2bccb, hi: 0xc8dae2, outer: 0x3a4650 }, // blue
|
|
132
|
-
];
|
|
133
|
-
// shaggy (long-haired landrace) goats: long coarse hair lies in bigger locks (small tight tufts read as a lamb's wool)
|
|
134
|
-
const longHair = (params) => (params.shaggy || 0) > 0.3;
|
|
135
|
-
// white-coated goats (and the white areas of pied / Boer coats) have pink skin: nose, lips, lids
|
|
136
|
-
const pinkSkinned = (params) => ['saanen', 'pied', 'piedbrown'].includes(params.coat);
|
|
137
|
-
function eyeLook(params) {
|
|
138
|
-
const s = ((params.coatSeed || 0) % 100) / 100;
|
|
139
|
-
const ir = IRISES[s < 0.45 ? 0 : s < 0.75 ? 1 : s < 0.96 ? 2 : 3];
|
|
140
|
-
return {
|
|
141
|
-
pupil: 'bar',
|
|
142
|
-
lids: 'mammal',
|
|
143
|
-
iris: { inner: srgb(ir.inner), mid: srgb(ir.mid), hi: srgb(ir.hi), outer: srgb(ir.outer) },
|
|
144
|
-
sclera: { color: [0.55, 0.5, 0.45], visible: false },
|
|
145
|
-
// (pink-grey lids on white goats: side2, face3; dark on the others)
|
|
146
|
-
lidColor: pinkSkinned(params) ? srgb(0x8a6a62) : [0.03, 0.025, 0.022],
|
|
147
|
-
pupilSize: [0.09, 0.32],
|
|
148
|
-
};
|
|
149
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// Goat motion data for the quadruped engine (schema: src/core/motion/quadruped.js).
|
|
2
|
-
// Numbers are for the reference individual (params.size = 1, a 0.78 m Saanen doe); the engine
|
|
3
|
-
// scales them by dynamic similarity for kids, pygmies and big bucks.
|
|
4
|
-
//
|
|
5
|
-
// Gaits: lateral-sequence 4-beat walk (duty 0.72 -> 0.62), 2-beat
|
|
6
|
-
// diagonal trot (hind lands ~2 % before its diagonal fore, duty 0.45 -> 0.36) and the transverse
|
|
7
|
-
// gallop (LH, RH, LF, RF). Crossovers sit at the predicted transitions: walk -> trot at Froude
|
|
8
|
-
// ~0.45 (1.85 m/s for a 0.78 m goat), trot -> gallop 4.2 m/s at ~2.5 Hz (Heglund et al. 1974:
|
|
9
|
-
// v = 1.535 M^0.24, f = 4.48 M^-0.14 for 65 kg).
|
|
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
|
-
maxSpeed: 8.5,
|
|
16
|
-
accel: [3.5, 7],
|
|
17
|
-
decel: 7,
|
|
18
|
-
turnRate: 1.7, // agile: pivots on the hind legs
|
|
19
|
-
latAccelMax: 4.5,
|
|
20
|
-
gears: { walk: 1.0, trot: 2.7, gallop: 5.6 },
|
|
21
|
-
gallopBlend: [3.8, 6.5],
|
|
22
|
-
// name v f D [FL, FR, HL, HR]
|
|
23
|
-
gaits: [
|
|
24
|
-
G('walk', 0.0, 0.85, 0.72, [0.25, 0.75, 0.0, 0.5], { liftF: 0.045, liftH: 0.04, bobF: 0.012, bobH: 0.012, flex: 0, lat: 0.02, fold: 0.7, heel: 30, tail: 0, drop: 0 }),
|
|
25
|
-
G('walk', 1.5, 1.35, 0.62, [0.25, 0.75, 0.0, 0.5], { liftF: 0.055, liftH: 0.048, bobF: 0.025, bobH: 0.025, flex: 0, lat: 0.025, fold: 0.85, heel: 40, tail: 0.1, drop: 0 }),
|
|
26
|
-
G('trot', 2.2, 2.05, 0.45, [0.52, 0.02, 0.0, 0.5], { liftF: 0.08, liftH: 0.065, bobF: 0.028, bobH: 0.028, flex: 0.01, lat: 0.0, fold: 1.05, heel: 50, tail: 0.3, drop: 0.006 }),
|
|
27
|
-
G('trot', 3.4, 2.4, 0.37, [0.52, 0.02, 0.0, 0.5], { liftF: 0.095, liftH: 0.08, bobF: 0.032, bobH: 0.032, flex: 0.015, lat: 0.0, fold: 1.15, heel: 55, tail: 0.4, drop: 0.01 }),
|
|
28
|
-
G('gallop', 4.8, 2.7, 0.3, [0.55, 0.65, 0.0, 0.1], { liftF: 0.11, liftH: 0.1, bobF: 0.022, bobH: 0.03, flex: 0.1, lat: 0, fold: 1.15, heel: 45, tail: 0.7, drop: 0.02 }),
|
|
29
|
-
G('gallop', 8.5, 3.0, 0.23, [0.56, 0.66, 0.0, 0.1], { liftF: 0.13, liftH: 0.12, bobF: 0.024, bobH: 0.034, flex: 0.14, lat: 0, fold: 1.4, heel: 40, tail: 1.0, drop: 0.035 }),
|
|
30
|
-
],
|
|
31
|
-
feet: {
|
|
32
|
-
// cloven hooves: the fetlock sinks a little under load, the digit flips in swing, breakover
|
|
33
|
-
// about the claw tips; pointed hard claws plant precisely (contact near the toe)
|
|
34
|
-
front: { type: 'unguligrade', contact: 0.9, curl: 70, flex: 4, sink: 14, hoofFlex: 20, swingBack: 0.07 },
|
|
35
|
-
hind: { type: 'unguligrade', contact: 0.9, curl: 70, flex: 4, sink: 12, hoofFlex: 20, swingBack: 0.02 },
|
|
36
|
-
},
|
|
37
|
-
stance: { width: 1, gallopWidth: 0.8, sprawl: 0, crouch: 0, scuff: [10, 20, 0] },
|
|
38
|
-
// torso cross-sections (bind pose, reference size): centre height, half height, half width
|
|
39
|
-
// (half heights include the legs folded under the chest and thighs when lying down)
|
|
40
|
-
body: {
|
|
41
|
-
// (0.28 with the pelvis's 0.36: the body lies level on its folded legs; the chest at 0.25 under the higher rump
|
|
42
|
-
// pitched forward onto the folded forelegs, a Boer buck's forearm 5 cm in the ground asleep)
|
|
43
|
-
chest: { y: 0.56, hh: 0.28, hw: 0.15 },
|
|
44
|
-
mid: { y: 0.55, hh: 0.23, hw: 0.17 },
|
|
45
|
-
// (the hindquarters rest on the folded hind legs: lying at 0.3 the stifles folded in against the belly and the skin
|
|
46
|
-
// between the thigh and the flank crumpled into a pocket in front of the stifle, a light torn knob from the side)
|
|
47
|
-
pelvis: { y: 0.63, hh: 0.36, hw: 0.16 },
|
|
48
|
-
back: 0.06,
|
|
49
|
-
},
|
|
50
|
-
head: {
|
|
51
|
-
// [speed, raise (m), reach (m), pitch (rad, + = nose down)]: head high and alert at rest, a
|
|
52
|
-
// little lower and forward at the walk, stretched forward in the gallop
|
|
53
|
-
carriage: [[0, 0.03, -0.015, -0.05], [1.0, 0.0, 0.01, 0.02], [2.7, -0.01, 0.03, 0.02], [5, -0.06, 0.06, 0.1], [8, -0.1, 0.09, 0.14]],
|
|
54
|
-
stab: [[0, 0], [1.0, 0.15], [2.7, 0.45], [5, 0.35], [8, 0.4]],
|
|
55
|
-
neckBend: 34, neckPivot: 0.55, yaw: 0.9, pitchUp: 0.7, pitchDown: 0.9, mouth: 'jawTip',
|
|
56
|
-
},
|
|
57
|
-
tail: {
|
|
58
|
-
// [speed, pitch per segment from horizontal (deg), base -> tip]: carried up, higher when running
|
|
59
|
-
carriage: [
|
|
60
|
-
[0.0, [28, 42, 55, 62, 66]],
|
|
61
|
-
[1.5, [30, 45, 58, 64, 68]],
|
|
62
|
-
[3.5, [36, 52, 64, 70, 72]],
|
|
63
|
-
[7, [42, 58, 70, 74, 76]],
|
|
64
|
-
],
|
|
65
|
-
stiffness: 1.2, sway: 4, flick: 1, wag: 0, swish: 0, curl: 0, balance: 0,
|
|
66
|
-
radius: [0.03, 0.02],
|
|
67
|
-
},
|
|
68
|
-
ears: { rest: [0, 0], mobility: 1.3, speedFlatten: 0.3, twitch: 1.6, prick: 0.5 },
|
|
69
|
-
breath: { rate: 0.32, amp: 0.006, pant: false, pantRate: 2, pantAmp: 0.015, heatSpeed: 6 },
|
|
70
|
-
actions: {
|
|
71
|
-
// grazing: the long face already hangs 60 deg nose-down in the bind pose
|
|
72
|
-
// (the face nearly vertical, 77 deg nose-down: at 1.1 rad the head was cocked back against the lowered neck, the
|
|
73
|
-
// poll extended 120 deg from its standing angle and the nape's skin folded to 0.65 of its length, its hair standing
|
|
74
|
-
// apart in a frayed band; the throat stretched more too: > 3x 1.37 -> 0.98 % of the kid's mesh in eat and drink)
|
|
75
|
-
eat: { style: 'graze', dropF: 0.1, dropH: 0, pitch: 1.35, ahead: 0.5 },
|
|
76
|
-
drink: { dropF: 0.1, dropH: 0, pitch: 1.3, ahead: 0.5 },
|
|
77
|
-
// sure-footed: a high standing jump, landing on four feet close together (opts.target lands
|
|
78
|
-
// exactly there)
|
|
79
|
-
jump: { height: 0.75, distance: 1.3, land: [0.16, 0.14] },
|
|
80
|
-
sit: { dropH: 0.8 },
|
|
81
|
-
// kneels on the carpi first, then drops the hindquarters; rises hind end first
|
|
82
|
-
lie: { down: 'front', up: 'hind' },
|
|
83
|
-
sleep: { down: 'front', up: 'hind' },
|
|
84
|
-
// lying sternal: forelegs folded under the chest (carpus flexed, cannons back along the ground)
|
|
85
|
-
fold: { front: { z: -0.2, k: 1.45, beta: 0.9 } },
|
|
86
|
-
},
|
|
87
|
-
hooks,
|
|
88
|
-
// the long lop ears of Nubians and Boers hang and swing with the head; they barely prick or twist
|
|
89
|
-
// (the engine swivels a pinna about its own long axis toward what the goat looks at: a hanging ear
|
|
90
|
-
// twisted 25 deg about its root)
|
|
91
|
-
variants: {
|
|
92
|
-
nubian: { ears: { mobility: 0.5, speedFlatten: 0.15, twitch: 0.4, prick: 0.06 } },
|
|
93
|
-
boer: { ears: { mobility: 0.5, speedFlatten: 0.15, twitch: 0.4, prick: 0.06 } },
|
|
94
|
-
},
|
|
95
|
-
};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// Meshing plan: body at 5.4 mm (0.7 % of the withers height, like the cheetah), head at 2.6 mm
|
|
2
|
-
// overlapping the body across the upper neck and cross-faded, eyelid patches at 0.9 mm, the lower
|
|
3
|
-
// lip / chin / beard as its own rigid surface (the mouth opens) and the horns as a rigid keratin
|
|
4
|
-
// surface on the skull.
|
|
5
|
-
import { EYE, hornPath, hornCell, hornSplit, hornTipCell } from './sculpt.js';
|
|
6
|
-
import { HEAD_O, hqOf, goatJoints } from './rig.js';
|
|
7
|
-
import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
|
|
8
|
-
import { norm, smoothstep, clamp } from '../../core/math/vec.js';
|
|
9
|
-
|
|
10
|
-
const J = goatJoints();
|
|
11
|
-
// The head mesh takes over across a plane through the upper neck, 30 % of the way from the mid neck
|
|
12
|
-
// to the occiput, its normal the upper neck axis turned 45 deg forward (toward the head): it crosses
|
|
13
|
-
// the nape ~6 cm behind the poll and the throat ~9 cm below the jaw angle, both where the neck is a
|
|
14
|
-
// smooth tube and the fine and coarse meshes agree. (The first cut ran behind the poll and into the
|
|
15
|
-
// concave jaw angle / throat junction, where they did not: a crack from the poll to the throat. A
|
|
16
|
-
// plane square to the upright neck cut through the lower face, which hangs forward below the throat.)
|
|
17
|
-
const NECK_U = norm([0, J.occiput[1] - J.neckMid[1], J.occiput[2] - J.neckMid[2]]);
|
|
18
|
-
const NECK_A = Math.atan2(NECK_U[1], NECK_U[2]) - Math.PI / 4;
|
|
19
|
-
export const NECK_CUT = {
|
|
20
|
-
c: [0, J.neckMid[1] + 0.3 * (J.occiput[1] - J.neckMid[1]), J.neckMid[2] + 0.3 * (J.occiput[2] - J.neckMid[2])],
|
|
21
|
-
d: [0, Math.sin(NECK_A), Math.cos(NECK_A)], band: 0.014,
|
|
22
|
-
};
|
|
23
|
-
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];
|
|
24
|
-
|
|
25
|
-
export const EYE_PATCH = { R: 0.024, B: 0.004, h: 0.0011, centres: [1, -1].map((s) => eyeFrameOf(EYE, HEAD_O, s).c) };
|
|
26
|
-
export function eyePatchWeight(x, y, z) {
|
|
27
|
-
let dmin = 1e9;
|
|
28
|
-
for (const c of EYE_PATCH.centres) dmin = Math.min(dmin, Math.hypot(x - c[0], y - c[1], z - c[2]));
|
|
29
|
-
return 1 - smoothstep(EYE_PATCH.R - EYE_PATCH.B, EYE_PATCH.R + EYE_PATCH.B, dmin);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function goatRegions(rig, params, Q) {
|
|
33
|
-
// (the band: wider than a body cell, so the body's cut edge, which lies up to a cell into the band,
|
|
34
|
-
// stays in its hidden half: at the crowd tier a 25 mm cell left it on the visible side of a 14 mm band,
|
|
35
|
-
// at the low tier 0.95 of a cell left one edge of a buck's neck uncovered)
|
|
36
|
-
const r = Q.res, B = Math.max(NECK_CUT.band, 0.0059 * r * 1.2);
|
|
37
|
-
const Ho = HEAD_O;
|
|
38
|
-
// eyelid patches at hero, high and medium (what Safari and phones show): without them the 24 x 16 mm aperture's lid
|
|
39
|
-
// margin fell on the medium tier's 5.6 mm face cells and tore into pale and dark flakes round every eye
|
|
40
|
-
// (the full 24 mm patch: the face mesh stops a cell inside it, and at 21.5 mm that cut reached the lid margin, 19-22
|
|
41
|
-
// exposed edges round the eyes at medium)
|
|
42
|
-
const patches = (Q.eyePatches || r <= 2) ? EYE_PATCH.centres.map((c) => ({ c, R: EYE_PATCH.R, B: EYE_PATCH.B, h: EYE_PATCH.h * Math.max(1, r) })) : [];
|
|
43
|
-
const head = [
|
|
44
|
-
// (the long, broad lop ears of Nubians and Boers are meshed with the head: its cells 6 % coarser keep a
|
|
45
|
-
// lop-eared buck inside the hero budget, 133k -> 128k vertices)
|
|
46
|
-
{ name: 'head', part: 'body', bmin: [-0.3, 0.6, 0.33], bmax: [0.3, Ho[1] + 0.14, Ho[2] + 0.24], h: 0.0028 * r * (params.ear === 'lop' ? (params.sex === 'male' && params.age !== 'juvenile' ? (r === 2 ? 1.13 : 1.12) : 1.06) : 1), F: 6, clip: (x, y, z) => neckS(x, y, z) > -B, patches },
|
|
47
|
-
{ name: 'jaw', part: 'jaw', bmin: [-0.06, Ho[1] - 0.27, Ho[2] - 0.09], bmax: [0.06, Ho[1] - 0.03, Ho[2] + 0.22], h: 0.0028 * r, F: 6, rigidBone: 'jaw' },
|
|
48
|
-
];
|
|
49
|
-
// (the beard's locks are 7-12 mm thick: at the medium tier's 6.8 mm cells their tips folded over, back faces showing;
|
|
50
|
-
// 5.4 mm there)
|
|
51
|
-
if ((params.beard || 0) > 0.01) head.push({ name: 'beard', part: 'beard', bmin: [-0.07, Ho[1] - 0.46, Ho[2] - 0.16], bmax: [0.07, Ho[1] - 0.06, Ho[2] + 0.18], h: 0.0034 * (r === 2 ? 1.6 : r), F: 6, rigidBone: 'beard' });
|
|
52
|
-
if (params.wattles) head.push({ name: 'wattle', part: 'wattle', bmin: [-0.06, Ho[1] - 0.2, Ho[2] - 0.18], bmax: [0.06, Ho[1] + 0.03, Ho[2] + 0.02], h: 0.0022 * r, F: 6, rigidBone: 'neck2' });
|
|
53
|
-
// the udder / a buck's scrotum: its own closed surface, rigid on the udder bone (sculpt.js) (the scrotum
|
|
54
|
-
// coarser: a horned, bearded lop-eared buck was 200 vertices over the hero budget)
|
|
55
|
-
const adult = params.age !== 'juvenile', male = params.sex === 'male', HQ = hqOf(params);
|
|
56
|
-
if (adult && (male || (params.udder ?? 0.5) > 0.05)) head.push({ name: 'udder', part: 'udder', bmin: [-0.11, 0.17, -0.44 + HQ], bmax: [0.11, male ? 0.62 : 0.56, -0.2 + HQ], h: (male ? 0.005 : 0.0042) * r, F: 6, rigidBone: 'udder' });
|
|
57
|
-
if (params.horns && params.horns.len > 0) {
|
|
58
|
-
// the box from the horn centre lines (both sides) plus the horn radius and two cells: a fixed box
|
|
59
|
-
// cut the horn bases off (they start at the poll, z 0.65, and a doe's horns reach z 0.68)
|
|
60
|
-
// (cells with the horn's girth: a buck's longest, thickest horns took 18k vertices at 3.2 mm, and a
|
|
61
|
-
// lop-eared buck with them and a long beard came to 137k at hero, over the 130k budget)
|
|
62
|
-
// (at most the low tier's cells at the crowd tier too: 16 mm cells left a buck's horn a chain of ragged lumps;
|
|
63
|
-
// the horn is also kept ~0.45 of a cell thick there, sculpt.js hornPath)
|
|
64
|
-
// (at the low and crowd tiers the tapering outer part is its own solid at the medium tier's cells, sculpt.js hornSplit)
|
|
65
|
-
const h = hornCell(params, r), hT = hornTipCell(params);
|
|
66
|
-
const box = (part, hh, from, to) => {
|
|
67
|
-
const bmin = [1e9, 1e9, 1e9], bmax = [-1e9, -1e9, -1e9];
|
|
68
|
-
for (const s of [1, -1]) {
|
|
69
|
-
const pth = hornPath(params, s), J = hornSplit(params, pth);
|
|
70
|
-
pth.forEach((q, i) => {
|
|
71
|
-
if (J >= 0 && (i < from(J) || i > to(J, pth.length))) return;
|
|
72
|
-
const m = q.r * 1.25 + 2 * hh + 0.004;
|
|
73
|
-
for (let k = 0; k < 3; k++) { bmin[k] = Math.min(bmin[k], q.p[k] - m); bmax[k] = Math.max(bmax[k], q.p[k] + m); }
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
head.push({ name: part, part, bmin, bmax, h: hh, F: 6, rigidBone: 'head' });
|
|
77
|
-
};
|
|
78
|
-
const split = hornSplit(params, hornPath(params, 1)) >= 0;
|
|
79
|
-
box('horn', h, () => 0, (J, n) => (split ? J : n));
|
|
80
|
-
if (split) box('horntip', hT, (J) => J - 2, (J, n) => n);
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
jobs: [
|
|
84
|
-
[{ name: 'body', part: 'body', bmin: [-0.26, -0.01, -0.66], bmax: [0.26, 1.0, 0.7], h: 0.0059 * r, F: 4, clip: (x, y, z) => neckS(x, y, z) < B }],
|
|
85
|
-
head,
|
|
86
|
-
],
|
|
87
|
-
fade(x, y, z, name, patch) {
|
|
88
|
-
const sN = neckS(x, y, z);
|
|
89
|
-
if (name === 'body') return 1 - smoothstep(-B, B, sN);
|
|
90
|
-
if (name === 'head') {
|
|
91
|
-
let f = smoothstep(-B, B, sN);
|
|
92
|
-
if (patches.length) { const ew = eyePatchWeight(x, y, z); f *= patch ? ew : 1 - ew; }
|
|
93
|
-
return f;
|
|
94
|
-
}
|
|
95
|
-
return 1;
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
// Goat skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
|
|
2
|
-
// Reference individual: a Saanen-type dairy doe, 0.78 m at the withers, ~65 kg (ADGA standard). Landmarks measured on side3.jpg (4x grid, 1 px = 1.39 mm) and side2.jpg
|
|
3
|
-
// (1 px = 1.84 mm), limb segments from published goat osteometry.
|
|
4
|
-
//
|
|
5
|
-
// Hooves: the standard quadruped bones plus a hoof bone per leg, exactly like the horse:
|
|
6
|
-
// fpaw / hpaw = pastern (fetlock -> coffin joint), fhoof / hhoof = the cloven hoof (coffin joint ->
|
|
7
|
-
// toe), so the engine keeps the claws flat while the fetlock sinks under load.
|
|
8
|
-
//
|
|
9
|
-
// The rig depends on the individual only through the ears (erect / lateral in Swiss breeds, long and
|
|
10
|
-
// pendulous in the Nubian: params.ear).
|
|
11
|
-
import { buildRig } from '../../core/rig/rig.js';
|
|
12
|
-
import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
|
|
13
|
-
|
|
14
|
-
export const TAIL_SEGS = 5;
|
|
15
|
-
// a lop ear's root blend: the ear takes the skin up to 3 cm onto the head and down to 5 cm along the ear (it hangs with
|
|
16
|
-
// gravity, turning up to 25 deg about its root against the skull: at [-0.006, 0.02] the root and the web between the
|
|
17
|
-
// blade and the cheek stretched 3x on 1 % more of the mesh when grazing)
|
|
18
|
-
export const LOPBL = [-0.03, 0.05];
|
|
19
|
-
|
|
20
|
-
// Head frame: modelled along its own axis (poll -> muzzle), pitched 42 degrees nose-down in the
|
|
21
|
-
// bind pose. Head-local coordinates: x lateral, y dorsal (forehead side), z along the nasal line toward
|
|
22
|
-
// the muzzle; origin on the axis 0.07 m in front of the poll, level with the eyes.
|
|
23
|
-
// (side2 and walk1: the eye -> nose-tip line runs 33-34 deg below the horizontal and the forehead
|
|
24
|
-
// 51-60 deg; the poll stands ~0.3 SH above the withers, the neck rises at ~55-64 deg. The head was
|
|
25
|
-
// carried at 54 deg with the forehead profile at 68 deg, 5-7 cm low: a grazing horse's carriage)
|
|
26
|
-
export const HEAD_PITCH = (42 * Math.PI) / 180;
|
|
27
|
-
export const HZ = [0, -Math.sin(HEAD_PITCH), Math.cos(HEAD_PITCH)];
|
|
28
|
-
export const HY = [0, Math.cos(HEAD_PITCH), Math.sin(HEAD_PITCH)];
|
|
29
|
-
const POLL = [0, 0.975, 0.59]; // top of the poll (skin), bind
|
|
30
|
-
export const HEAD_O = [0, POLL[1] + 0.07 * HZ[1], POLL[2] + 0.07 * HZ[2]];
|
|
31
|
-
export const hl = (v) => [HEAD_O[0] + v[0], HEAD_O[1] + v[1] * HY[1] + v[2] * HZ[1], HEAD_O[2] + v[1] * HY[2] + v[2] * HZ[2]];
|
|
32
|
-
// a kid's face is short: in front of the eyes the head-local z (along the nasal line) is compressed by
|
|
33
|
-
// KID_FACE (front2, kid_side: a big braincase and eyes over a short, small muzzle; the whole head scaled
|
|
34
|
-
// up gave a kid an adult's bulbous muzzle). faceZ maps an adult head-local z to the kid's, unFaceZ back.
|
|
35
|
-
export const KID_FACE = 0.78;
|
|
36
|
-
export const faceZ = (z, kid) => (kid && z > 0.02 ? 0.02 + (z - 0.02) * KID_FACE : z);
|
|
37
|
-
export const unFaceZ = (z, kid) => (kid && z > 0.02 ? 0.02 + (z - 0.02) / KID_FACE : z);
|
|
38
|
-
// head-local point (adult coordinates) -> world, with the kid's short face
|
|
39
|
-
export const hlk = (v, kid) => hl([v[0], v[1], faceZ(v[2], kid)]);
|
|
40
|
-
// head-local direction -> world
|
|
41
|
-
export const hdir = (v) => [v[0], v[1] * HY[1] + v[2] * HZ[1], v[1] * HY[2] + v[2] * HZ[2]];
|
|
42
|
-
// world point -> head-local
|
|
43
|
-
export const toHL = (p) => { const d = [p[0] - HEAD_O[0], p[1] - HEAD_O[1], p[2] - HEAD_O[2]]; return [d[0], d[1] * HY[1] + d[2] * HY[2], d[1] * HZ[1] + d[2] * HZ[2]]; };
|
|
44
|
-
|
|
45
|
-
// ear tips (head-local, left): Swiss erect / lateral ears point out, a little up and forward;
|
|
46
|
-
// Nubian / Boer lop ears hang straight down beside the face (their tip is placed in world space
|
|
47
|
-
// below the base, clear of the cheek: see goatJoints)
|
|
48
|
-
export const EAR_BASE = [0.048, 0.026, -0.06];
|
|
49
|
-
export const EAR_TIP = {
|
|
50
|
-
erect: [0.2, 0.015, -0.02],
|
|
51
|
-
};
|
|
52
|
-
// the hindquarters (hip joint, hind limb, pelvis, tail root, udder) sit this far further forward than
|
|
53
|
-
// the first model: side1 / side2 give a body (point of shoulder -> point of buttock) of 1.06-1.09 SH,
|
|
54
|
-
// the model had 1.24 SH, its hip points, tail head and buttock 10-18 cm behind side2's
|
|
55
|
-
// (adults 0.07, not 0.095: the hind hooves stood 0.17 SH ahead of the rump's outline at the toe, against
|
|
56
|
-
// 0.06-0.12 in side2 / side3; now 0.14 at the toe, 0.05 at the heel, the cannons under the pin bones. Kids keep
|
|
57
|
-
// 0.095: their hind legs stand under the short body, kid_side, and with them further back the Nubian kid's
|
|
58
|
-
// sprint jittered at the wrist, p99 0.086 % S)
|
|
59
|
-
export const hqOf = (params = {}) => (params.age === 'juvenile' ? 0.095 : 0.07);
|
|
60
|
-
|
|
61
|
-
export function goatJoints(params = {}) {
|
|
62
|
-
// (erect ears: carried from level-lateral (face3) to up-and-out (face1), params.earLift 0..1)
|
|
63
|
-
const lop = params.ear === 'lop';
|
|
64
|
-
const kid = params.age === 'juvenile';
|
|
65
|
-
// (kids carry their big ears up and out: front2, kid_side)
|
|
66
|
-
const lift = kid ? Math.max(0.6, params.earLift ?? 0.5) : (params.earLift ?? 0.5);
|
|
67
|
-
const HQ = hqOf(params);
|
|
68
|
-
const J = {
|
|
69
|
-
nose: hlk([0, -0.024, 0.205], kid), // (the front of the nose pad and upper lip: the engine keeps it off the ground)
|
|
70
|
-
occiput: hl([0, -0.045, -0.1]), // (behind the poll and the horn bases: the skull top is all 'head')
|
|
71
|
-
neckMid: [0, 0.8, 0.472],
|
|
72
|
-
neckBase: [0, 0.64, 0.35],
|
|
73
|
-
chestMid: [0, 0.668, 0.17],
|
|
74
|
-
thoraxRear: [0, 0.692, 0.015],
|
|
75
|
-
lumbarMid: [0, 0.702, -0.1],
|
|
76
|
-
lumbosacral: [0, 0.707, -0.215],
|
|
77
|
-
tailBase: [0, 0.71, -0.4],
|
|
78
|
-
// fore: scapula sloping ~65 deg, humerus down and back (45 deg from vertical), radius and cannon
|
|
79
|
-
// vertical, pastern ~50 deg (cloven hoof)
|
|
80
|
-
// (the elbow 1.7 cm further back: with the humerus 40 deg from vertical the shoulder -> wrist span was
|
|
81
|
-
// 93 % of humerus + radius, the engine's reach limit left the foreleg a 0.45 m stance sweep against
|
|
82
|
-
// the hind leg's 0.75 m, and it cut the fore stances short: duty 0.53 / 0.34 / 0.20 at the walk,
|
|
83
|
-
// trot and gallop against the table's 0.65 / 0.42 / 0.29, a high hackney flick and pacing walk)
|
|
84
|
-
scapTopL: [0.055, 0.745, 0.265],
|
|
85
|
-
shoulderL: [0.088, 0.53, 0.372],
|
|
86
|
-
elbowL: [0.083, 0.405, 0.245],
|
|
87
|
-
wristL: [0.07, 0.21, 0.252],
|
|
88
|
-
mcpL: [0.064, 0.07, 0.256],
|
|
89
|
-
fcoffinL: [0.064, 0.03, 0.279],
|
|
90
|
-
ftoeL: [0.064, 0.002, 0.323],
|
|
91
|
-
// hind: hip joint, stifle, hock, fetlock, coffin joint, toe (the cannon vertical: it stood 6 deg
|
|
92
|
-
// forward, sickle-hocked)
|
|
93
|
-
hipL: [0.078, 0.63, -0.36 + HQ],
|
|
94
|
-
kneeL: [0.093, 0.45, -0.24 + HQ],
|
|
95
|
-
hockL: [0.066, 0.25, -0.44 + HQ],
|
|
96
|
-
mtpL: [0.06, 0.075, -0.442 + HQ],
|
|
97
|
-
hcoffinL: [0.06, 0.031, -0.419 + HQ],
|
|
98
|
-
htoeL: [0.06, 0.002, -0.374 + HQ],
|
|
99
|
-
jawHinge: hl([0, -0.045, -0.02]),
|
|
100
|
-
jawTip: hlk([0, -0.078, 0.185], kid),
|
|
101
|
-
// (a lop ear's root sits further back on the skull: hanging from the erect ear's root, the broad blade
|
|
102
|
-
// covered the eye)
|
|
103
|
-
earBaseL: hl(lop ? [EAR_BASE[0], EAR_BASE[1] - 0.006, EAR_BASE[2] - 0.01] : EAR_BASE),
|
|
104
|
-
// udder (does): its own rigid bone below the pelvis, so it can fold up out of the ground when the
|
|
105
|
-
// doe lies down (hooks.pose)
|
|
106
|
-
// beard: its own bone below the chin (hangs from the jaw; hooks.pose swings it out of the ground)
|
|
107
|
-
beardTop: hlk([0, -0.094, 0.115], kid),
|
|
108
|
-
udderTop: [0, 0.44, -0.34 + HQ],
|
|
109
|
-
udderBot: [0, 0.3, -0.325 + HQ],
|
|
110
|
-
};
|
|
111
|
-
// lop ears (Nubian, Boer): long and broad, hanging down beside the face and jaw from the base, flaring out
|
|
112
|
-
// to 9 cm from the root at the tip and a little back of vertical, so the blade stays behind the eye (side_boer,
|
|
113
|
-
// the Nubian standard; hanging straight down with the face pitched 42 deg nose-down it covered the eye) and
|
|
114
|
-
// clear of the throat (within the 2 cm blend of the throat skin it took neck weights and stretched)
|
|
115
|
-
const eb = J.earBaseL;
|
|
116
|
-
// (a kid's lop ears are shorter: its head is scaled up as a whole, and full-length ears hung below its knees)
|
|
117
|
-
// (Nubian ears ~25 cm, reaching below the jaw; a Boer's a little shorter: at 21 cm they ended at the
|
|
118
|
-
// mouth corner, short paddles)
|
|
119
|
-
const le = (kid ? 0.82 : 1) * (params.variant === 'boer' ? 0.9 : 1);
|
|
120
|
-
J.earTipL = lop ? [eb[0] + 0.1 * le, eb[1] - 0.225 * le, eb[2] - 0.05 * le]
|
|
121
|
-
: hl([EAR_TIP.erect[0] - 0.02 * lift, EAR_TIP.erect[1] - 0.03 + 0.11 * lift, EAR_TIP.erect[2] + 0.02 * lift]);
|
|
122
|
-
// (a kid's erect ears are long for its head: as long as its face, front2)
|
|
123
|
-
if (kid && !lop) for (let i = 0; i < 3; i++) J.earTipL[i] = eb[i] + (J.earTipL[i] - eb[i]) * 1.15;
|
|
124
|
-
J.beardTip = [J.beardTop[0], J.beardTop[1] - Math.max(0.03, params.beard || 0), J.beardTop[2] - 0.01];
|
|
125
|
-
// the short flat tail is carried up (research: erect most of the time)
|
|
126
|
-
tailChain(J, 'tailBase', [28, 42, 55, 62, 66], [0.035, 0.032, 0.03, 0.028, 0.026]);
|
|
127
|
-
return J;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function goatBones() {
|
|
131
|
-
const b = quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true });
|
|
132
|
-
for (const d of b) {
|
|
133
|
-
if (d[0] === 'fpaw{S}') { d[2] = 'fcoffin{S}'; d[4] = { region: 'limb', group: 'F{S}' }; }
|
|
134
|
-
if (d[0] === 'hpaw{S}') { d[2] = 'hcoffin{S}'; d[4] = { region: 'limb', group: 'H{S}' }; }
|
|
135
|
-
}
|
|
136
|
-
b.push(['udder', 'udderTop', 'udderBot', 'pelvis', { region: 'torso', group: 'udder' }]);
|
|
137
|
-
b.push(['beard', 'beardTop', 'beardTip', 'jaw', { region: 'jaw', group: 'jaw' }]);
|
|
138
|
-
b.push(
|
|
139
|
-
['fhoof{S}', 'fcoffin{S}', 'ftoe{S}', 'fpaw{S}', { region: 'foot', group: 'F{S}' }],
|
|
140
|
-
['hhoof{S}', 'hcoffin{S}', 'htoe{S}', 'hpaw{S}', { region: 'foot', group: 'H{S}' }],
|
|
141
|
-
);
|
|
142
|
-
return b;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function goatRig(params = {}, J = goatJoints(params)) {
|
|
146
|
-
const limbs = quadrupedLimbs({
|
|
147
|
-
front: { tCore: 0.5, aCore: 0.05, aBody: -0.15, midX: 0.0 },
|
|
148
|
-
hind: { tCore: 0.45, aCore: 0.022, aBody: -0.11, midX: 0.008 },
|
|
149
|
-
});
|
|
150
|
-
for (const L of Object.values(limbs)) { L.bones.push((L.front ? 'fhoof' : 'hhoof') + L.S); L.distal.push((L.front ? 'fhoof' : 'hhoof') + L.S); }
|
|
151
|
-
return buildRig({
|
|
152
|
-
joints: J,
|
|
153
|
-
unit: 1.03,
|
|
154
|
-
headOrigin: HEAD_O,
|
|
155
|
-
bones: goatBones(),
|
|
156
|
-
axial: {
|
|
157
|
-
points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
|
|
158
|
-
bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
|
|
159
|
-
// the skull's influence reaches back into the throat (widening with the depth below the axis)
|
|
160
|
-
// (a narrower lever, 0.5, kept the cheek out of the blend but gathered the stretch at the jaw angle:
|
|
161
|
-
// fewer triangles over 2x, more over 3x; the throat stretch is cured in the poses instead, the grazing
|
|
162
|
-
// head pitch and a kid's short face, see motion.js and rig.js faceZ)
|
|
163
|
-
// (the neck base blends over 8 cm each side: the skin over the withers stretched 3x when the head went
|
|
164
|
-
// down or round to the flank)
|
|
165
|
-
// (15 cm: at 8 cm the skin over the withers bent over a ridge when the neck went down to graze; the Boer
|
|
166
|
-
// keeps 11 cm: wider, its broad chest front took neck weights, and lying dead it rested 11 mm in the
|
|
167
|
-
// ground, and its red / white border across the lower neck stretched)
|
|
168
|
-
blend: { 1: [-0.05, 0.14, 4.5], 3: params.variant === 'boer' ? [-0.11, 0.11, 0] : [-0.15, 0.15, 0] },
|
|
169
|
-
bodyTail: 0, // (the rump and buttocks do not blend into the tail: they tore when the thighs folded to lie down)
|
|
170
|
-
},
|
|
171
|
-
limbs,
|
|
172
|
-
appendages: [
|
|
173
|
-
// (a long lop ear swings about its root as the head moves: its root blends over 2.6 cm, where an
|
|
174
|
-
// erect ear's took 6 mm and tore; reaching 1 cm onto the head it dragged the skin behind the root)
|
|
175
|
-
{ group: 'earL', bone: 'earL', blend: params.ear === 'lop' ? LOPBL : [-0.002, 0.004] },
|
|
176
|
-
{ group: 'earR', bone: 'earR', blend: params.ear === 'lop' ? LOPBL : [-0.002, 0.004] },
|
|
177
|
-
{ group: 'udder', bone: 'udder', blend: [-0.004, 0.02] },
|
|
178
|
-
],
|
|
179
|
-
webTags: ['flankfold', 'thighfront', 'scapmuscle', 'pectoral', 'forearmweb'],
|
|
180
|
-
});
|
|
181
|
-
}
|