@bitefoundry/retrieviewer 0.0.0-stage → 0.0.2
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 +43 -0
- package/ASSETS-LICENSE.md +58 -0
- package/ATTRIBUTION.md +54 -0
- package/EMBEDDING.md +96 -0
- package/INSTALLING.md +126 -0
- package/LICENSE +16 -0
- package/LICENSE-CODE +21 -0
- package/PLUGIN.md +110 -0
- package/PUPPY-MEMORY.md +57 -0
- package/PUPPY-Q5-COMPARISON.md +73 -0
- package/README.md +86 -2
- package/RELEASING.md +70 -0
- package/THIRD-PARTY-NOTICES.md +17 -0
- package/TRADEMARKS.md +21 -0
- package/WINDOWS-COMPANION.md +113 -0
- package/braille.mjs +45 -0
- package/examples/bridge.py +62 -0
- package/examples/embed.mjs +15 -0
- package/examples/live.mjs +40 -0
- package/examples/plugin.mjs +21 -0
- package/integrations/opencode/runtime.mjs +195 -0
- package/integrations/opencode/tui.tsx +59 -0
- package/integrations/windows-overlay/Overlay.cs +259 -0
- package/integrations/windows-overlay/desktop.mjs +87 -0
- package/integrations/windows-overlay/protocol.mjs +39 -0
- package/integrations/windows-overlay/worker.mjs +60 -0
- package/locomotion-core.mjs +21 -0
- package/locomotion-puppy.animal +0 -0
- package/package.json +131 -4
- package/pet-q5-manifest.json +118 -0
- package/puppy-clean.mjs +51 -0
- package/puppy-companion-interactions-v3-q5.bin.gz +0 -0
- package/puppy-companion-interactions-v3.json +1 -0
- package/puppy-companion-life.mjs +182 -0
- package/puppy-companion-objects.mjs +30 -0
- package/puppy-companion-sprites.mjs +14 -0
- package/puppy-continuous.mjs +57 -0
- package/puppy-face.mjs +46 -0
- package/puppy-frame-predictive.mjs +147 -0
- package/puppy-frame-store.mjs +108 -0
- package/puppy-mouth-anchor.json +1 -0
- package/puppy-mouth-anchor.mjs +33 -0
- package/puppy-paper-actions-v9-q5.bin.gz +0 -0
- package/puppy-paper-actions-v9.json +1 -0
- package/puppy-paper-actions.mjs +48 -0
- package/puppy-paper-approach-q5.bin.gz +0 -0
- package/puppy-paper-approach.json +1 -0
- package/puppy-paper-area.mjs +15 -0
- package/puppy-paper-arrival-seat-q5.bin.gz +0 -0
- package/puppy-paper-arrival-seat.json +1 -0
- package/puppy-paper-behaviors-q5.bin.gz +0 -0
- package/puppy-paper-behaviors.json +1 -0
- package/puppy-paper-behaviors.mjs +8 -0
- package/puppy-paper-contact.mjs +103 -0
- package/puppy-paper-director.mjs +21 -0
- package/puppy-paper-paw-transport.mjs +76 -0
- package/puppy-paper-rear-gallop-q5.bin.gz +0 -0
- package/puppy-paper-rear-gallop.json +1 -0
- package/puppy-paper-seat-q5.bin.gz +0 -0
- package/puppy-paper-seat.json +14 -0
- package/puppy-paper-seat.mjs +13 -0
- package/puppy-paper-trick-timing.mjs +58 -0
- package/puppy-paper-world.mjs +108 -0
- package/puppy-paper.mjs +271 -0
- package/puppy-stable-meta.json +1606 -0
- package/puppy-stable.mjs +72 -0
- package/puppy-stride-meta.json +343 -0
- package/puppy-stride-tweens-q5.bin.gz +0 -0
- package/puppy-zoomies.mjs +27 -0
- package/puppy-zoomies30.mjs +12 -0
- package/retrieviewer-cli.mjs +94 -0
- package/retrieviewer-config.mjs +49 -0
- package/retrieviewer-install.mjs +157 -0
- package/retrieviewer-plugin.d.mts +44 -0
- package/retrieviewer-plugin.mjs +97 -0
- package/retrieviewer-stdio.mjs +38 -0
- package/retrieviewer.d.mts +85 -0
- package/retrieviewer.mjs +142 -0
- package/vendor/procedural-animals/LICENSE +21 -0
- package/vendor/procedural-animals/package.json +40 -0
- package/vendor/procedural-animals/src/animal.js +146 -0
- package/vendor/procedural-animals/src/bake.js +51 -0
- package/vendor/procedural-animals/src/build.js +81 -0
- package/vendor/procedural-animals/src/core/build/coatKit.js +121 -0
- package/vendor/procedural-animals/src/core/build/featherCards.js +189 -0
- package/vendor/procedural-animals/src/core/build/finEdges.js +85 -0
- package/vendor/procedural-animals/src/core/build/furSlope.js +115 -0
- package/vendor/procedural-animals/src/core/build/mesh.js +67 -0
- package/vendor/procedural-animals/src/core/build/pipeline.js +272 -0
- package/vendor/procedural-animals/src/core/build/seams.js +183 -0
- package/vendor/procedural-animals/src/core/build/warp.js +112 -0
- package/vendor/procedural-animals/src/core/build/weights.js +393 -0
- package/vendor/procedural-animals/src/core/math/vec.js +81 -0
- package/vendor/procedural-animals/src/core/motion/actions.js +800 -0
- package/vendor/procedural-animals/src/core/motion/bird.js +3063 -0
- package/vendor/procedural-animals/src/core/motion/birdActions.js +1059 -0
- package/vendor/procedural-animals/src/core/motion/common.js +158 -0
- package/vendor/procedural-animals/src/core/motion/index.js +22 -0
- package/vendor/procedural-animals/src/core/motion/quadruped.js +2875 -0
- package/vendor/procedural-animals/src/core/motion/snake.js +1594 -0
- package/vendor/procedural-animals/src/core/motion/spider.js +1810 -0
- package/vendor/procedural-animals/src/core/motion/swimmer.js +1047 -0
- package/vendor/procedural-animals/src/core/motion/swimmerActions.js +613 -0
- package/vendor/procedural-animals/src/core/render/animalObject.js +262 -0
- package/vendor/procedural-animals/src/core/render/coatMaterial.js +1301 -0
- package/vendor/procedural-animals/src/core/render/dqs.js +159 -0
- package/vendor/procedural-animals/src/core/render/eyes.js +676 -0
- package/vendor/procedural-animals/src/core/render/membranes.js +77 -0
- package/vendor/procedural-animals/src/core/render/skeleton.js +41 -0
- package/vendor/procedural-animals/src/core/rig/bird.js +327 -0
- package/vendor/procedural-animals/src/core/rig/quadruped.js +76 -0
- package/vendor/procedural-animals/src/core/rig/rig.js +79 -0
- package/vendor/procedural-animals/src/core/rig/snake.js +76 -0
- package/vendor/procedural-animals/src/core/rig/spider.js +110 -0
- package/vendor/procedural-animals/src/core/rig/swimmer.js +181 -0
- package/vendor/procedural-animals/src/core/sdf/eyeSocket.js +53 -0
- package/vendor/procedural-animals/src/core/sdf/mesher.js +238 -0
- package/vendor/procedural-animals/src/core/sdf/sdf.js +263 -0
- package/vendor/procedural-animals/src/index.d.ts +98 -0
- package/vendor/procedural-animals/src/index.js +29 -0
- package/vendor/procedural-animals/src/registry.js +48 -0
- package/vendor/procedural-animals/src/species/bear/behaviour.js +463 -0
- package/vendor/procedural-animals/src/species/bear/claws.js +147 -0
- package/vendor/procedural-animals/src/species/bear/coat.js +726 -0
- package/vendor/procedural-animals/src/species/bear/index.js +139 -0
- package/vendor/procedural-animals/src/species/bear/motion.js +112 -0
- package/vendor/procedural-animals/src/species/bear/regions.js +78 -0
- package/vendor/procedural-animals/src/species/bear/rig.js +112 -0
- package/vendor/procedural-animals/src/species/bear/sculpt.js +272 -0
- package/vendor/procedural-animals/src/species/boar/behaviour.js +335 -0
- package/vendor/procedural-animals/src/species/boar/coat.js +372 -0
- package/vendor/procedural-animals/src/species/boar/index.js +110 -0
- package/vendor/procedural-animals/src/species/boar/motion.js +85 -0
- package/vendor/procedural-animals/src/species/boar/regions.js +88 -0
- package/vendor/procedural-animals/src/species/boar/rig.js +111 -0
- package/vendor/procedural-animals/src/species/boar/sculpt.js +285 -0
- package/vendor/procedural-animals/src/species/cat/behaviour.js +559 -0
- package/vendor/procedural-animals/src/species/cat/coat.js +841 -0
- package/vendor/procedural-animals/src/species/cat/index.js +211 -0
- package/vendor/procedural-animals/src/species/cat/motion.js +101 -0
- package/vendor/procedural-animals/src/species/cat/regions.js +82 -0
- package/vendor/procedural-animals/src/species/cat/rig.js +100 -0
- package/vendor/procedural-animals/src/species/cat/sculpt.js +266 -0
- package/vendor/procedural-animals/src/species/cat/whiskers.js +110 -0
- package/vendor/procedural-animals/src/species/cheetah/coat.js +427 -0
- package/vendor/procedural-animals/src/species/cheetah/index.js +51 -0
- package/vendor/procedural-animals/src/species/cheetah/joints.js +3 -0
- package/vendor/procedural-animals/src/species/cheetah/motion.js +77 -0
- package/vendor/procedural-animals/src/species/cheetah/regions.js +95 -0
- package/vendor/procedural-animals/src/species/cheetah/rig.js +66 -0
- package/vendor/procedural-animals/src/species/cheetah/sculpt.js +158 -0
- package/vendor/procedural-animals/src/species/chicken/coat.js +313 -0
- package/vendor/procedural-animals/src/species/chicken/coverts.js +320 -0
- package/vendor/procedural-animals/src/species/chicken/index.js +110 -0
- package/vendor/procedural-animals/src/species/chicken/motion.js +177 -0
- package/vendor/procedural-animals/src/species/chicken/regions.js +66 -0
- package/vendor/procedural-animals/src/species/chicken/rig.js +144 -0
- package/vendor/procedural-animals/src/species/chicken/sculpt.js +389 -0
- package/vendor/procedural-animals/src/species/chicken/wingLook.js +66 -0
- package/vendor/procedural-animals/src/species/chicken/wingStack.js +124 -0
- package/vendor/procedural-animals/src/species/cow/behaviour.js +521 -0
- package/vendor/procedural-animals/src/species/cow/coat.js +465 -0
- package/vendor/procedural-animals/src/species/cow/index.js +118 -0
- package/vendor/procedural-animals/src/species/cow/motion.js +81 -0
- package/vendor/procedural-animals/src/species/cow/regions.js +98 -0
- package/vendor/procedural-animals/src/species/cow/rig.js +116 -0
- package/vendor/procedural-animals/src/species/cow/sculpt.js +339 -0
- package/vendor/procedural-animals/src/species/crow/coat.js +145 -0
- package/vendor/procedural-animals/src/species/crow/index.js +70 -0
- package/vendor/procedural-animals/src/species/crow/joints.js +3 -0
- package/vendor/procedural-animals/src/species/crow/motion.js +101 -0
- package/vendor/procedural-animals/src/species/crow/regions.js +50 -0
- package/vendor/procedural-animals/src/species/crow/rig.js +83 -0
- package/vendor/procedural-animals/src/species/crow/sculpt.js +118 -0
- package/vendor/procedural-animals/src/species/deer/behaviour.js +513 -0
- package/vendor/procedural-animals/src/species/deer/coat.js +391 -0
- package/vendor/procedural-animals/src/species/deer/index.js +106 -0
- package/vendor/procedural-animals/src/species/deer/motion.js +97 -0
- package/vendor/procedural-animals/src/species/deer/regions.js +60 -0
- package/vendor/procedural-animals/src/species/deer/rig.js +124 -0
- package/vendor/procedural-animals/src/species/deer/sculpt.js +297 -0
- package/vendor/procedural-animals/src/species/dog/behaviour.js +521 -0
- package/vendor/procedural-animals/src/species/dog/coat.js +495 -0
- package/vendor/procedural-animals/src/species/dog/index.js +144 -0
- package/vendor/procedural-animals/src/species/dog/motion.js +118 -0
- package/vendor/procedural-animals/src/species/dog/regions.js +61 -0
- package/vendor/procedural-animals/src/species/dog/rig.js +129 -0
- package/vendor/procedural-animals/src/species/dog/sculpt.js +246 -0
- package/vendor/procedural-animals/src/species/eagle/coat.js +250 -0
- package/vendor/procedural-animals/src/species/eagle/index.js +76 -0
- package/vendor/procedural-animals/src/species/eagle/joints.js +3 -0
- package/vendor/procedural-animals/src/species/eagle/motion.js +137 -0
- package/vendor/procedural-animals/src/species/eagle/regions.js +57 -0
- package/vendor/procedural-animals/src/species/eagle/rig.js +107 -0
- package/vendor/procedural-animals/src/species/eagle/sculpt.js +137 -0
- package/vendor/procedural-animals/src/species/fish/coat.js +271 -0
- package/vendor/procedural-animals/src/species/fish/index.js +88 -0
- package/vendor/procedural-animals/src/species/fish/motion.js +92 -0
- package/vendor/procedural-animals/src/species/fish/regions.js +27 -0
- package/vendor/procedural-animals/src/species/fish/rig.js +143 -0
- package/vendor/procedural-animals/src/species/fish/sculpt.js +214 -0
- package/vendor/procedural-animals/src/species/fish/variants.js +126 -0
- package/vendor/procedural-animals/src/species/fox/behaviour.js +314 -0
- package/vendor/procedural-animals/src/species/fox/coat.js +444 -0
- package/vendor/procedural-animals/src/species/fox/index.js +120 -0
- package/vendor/procedural-animals/src/species/fox/motion.js +81 -0
- package/vendor/procedural-animals/src/species/fox/regions.js +59 -0
- package/vendor/procedural-animals/src/species/fox/rig.js +91 -0
- package/vendor/procedural-animals/src/species/fox/sculpt.js +202 -0
- package/vendor/procedural-animals/src/species/frog/behaviour.js +590 -0
- package/vendor/procedural-animals/src/species/frog/coat.js +305 -0
- package/vendor/procedural-animals/src/species/frog/index.js +97 -0
- package/vendor/procedural-animals/src/species/frog/motion.js +69 -0
- package/vendor/procedural-animals/src/species/frog/regions.js +46 -0
- package/vendor/procedural-animals/src/species/frog/rig.js +156 -0
- package/vendor/procedural-animals/src/species/frog/sculpt.js +240 -0
- package/vendor/procedural-animals/src/species/goat/behaviour.js +509 -0
- package/vendor/procedural-animals/src/species/goat/coat.js +590 -0
- package/vendor/procedural-animals/src/species/goat/index.js +149 -0
- package/vendor/procedural-animals/src/species/goat/motion.js +95 -0
- package/vendor/procedural-animals/src/species/goat/regions.js +98 -0
- package/vendor/procedural-animals/src/species/goat/rig.js +181 -0
- package/vendor/procedural-animals/src/species/goat/sculpt.js +547 -0
- package/vendor/procedural-animals/src/species/horse/coat.js +361 -0
- package/vendor/procedural-animals/src/species/horse/coatSeam.js +122 -0
- package/vendor/procedural-animals/src/species/horse/index.js +80 -0
- package/vendor/procedural-animals/src/species/horse/motion.js +245 -0
- package/vendor/procedural-animals/src/species/horse/regions.js +60 -0
- package/vendor/procedural-animals/src/species/horse/rig.js +117 -0
- package/vendor/procedural-animals/src/species/horse/sculpt.js +316 -0
- package/vendor/procedural-animals/src/species/horse/seamWeights.js +272 -0
- package/vendor/procedural-animals/src/species/lion/behaviour.js +509 -0
- package/vendor/procedural-animals/src/species/lion/coat.js +1016 -0
- package/vendor/procedural-animals/src/species/lion/index.js +111 -0
- package/vendor/procedural-animals/src/species/lion/motion.js +87 -0
- package/vendor/procedural-animals/src/species/lion/regions.js +106 -0
- package/vendor/procedural-animals/src/species/lion/rig.js +110 -0
- package/vendor/procedural-animals/src/species/lion/sculpt.js +384 -0
- package/vendor/procedural-animals/src/species/lion/whiskers.js +132 -0
- package/vendor/procedural-animals/src/species/pig/behaviour.js +575 -0
- package/vendor/procedural-animals/src/species/pig/coat.js +730 -0
- package/vendor/procedural-animals/src/species/pig/ears.js +242 -0
- package/vendor/procedural-animals/src/species/pig/index.js +161 -0
- package/vendor/procedural-animals/src/species/pig/motion.js +105 -0
- package/vendor/procedural-animals/src/species/pig/regions.js +100 -0
- package/vendor/procedural-animals/src/species/pig/rig.js +152 -0
- package/vendor/procedural-animals/src/species/pig/sculpt.js +382 -0
- package/vendor/procedural-animals/src/species/rabbit/behaviour.js +605 -0
- package/vendor/procedural-animals/src/species/rabbit/coat.js +285 -0
- package/vendor/procedural-animals/src/species/rabbit/index.js +85 -0
- package/vendor/procedural-animals/src/species/rabbit/motion.js +85 -0
- package/vendor/procedural-animals/src/species/rabbit/regions.js +48 -0
- package/vendor/procedural-animals/src/species/rabbit/rig.js +99 -0
- package/vendor/procedural-animals/src/species/rabbit/sculpt.js +148 -0
- package/vendor/procedural-animals/src/species/rat/behaviour.js +539 -0
- package/vendor/procedural-animals/src/species/rat/coat.js +341 -0
- package/vendor/procedural-animals/src/species/rat/index.js +111 -0
- package/vendor/procedural-animals/src/species/rat/motion.js +90 -0
- package/vendor/procedural-animals/src/species/rat/regions.js +92 -0
- package/vendor/procedural-animals/src/species/rat/rig.js +112 -0
- package/vendor/procedural-animals/src/species/rat/sculpt.js +163 -0
- package/vendor/procedural-animals/src/species/rat/whiskers.js +119 -0
- package/vendor/procedural-animals/src/species/shark/coat.js +383 -0
- package/vendor/procedural-animals/src/species/shark/index.js +104 -0
- package/vendor/procedural-animals/src/species/shark/motion.js +69 -0
- package/vendor/procedural-animals/src/species/shark/regions.js +34 -0
- package/vendor/procedural-animals/src/species/shark/rig.js +194 -0
- package/vendor/procedural-animals/src/species/shark/sculpt.js +343 -0
- package/vendor/procedural-animals/src/species/shark/variants.js +105 -0
- package/vendor/procedural-animals/src/species/sheep/behaviour.js +522 -0
- package/vendor/procedural-animals/src/species/sheep/coat.js +529 -0
- package/vendor/procedural-animals/src/species/sheep/index.js +152 -0
- package/vendor/procedural-animals/src/species/sheep/motion.js +86 -0
- package/vendor/procedural-animals/src/species/sheep/neck.js +41 -0
- package/vendor/procedural-animals/src/species/sheep/regions.js +62 -0
- package/vendor/procedural-animals/src/species/sheep/rig.js +163 -0
- package/vendor/procedural-animals/src/species/sheep/sculpt.js +542 -0
- package/vendor/procedural-animals/src/species/snake/coat.js +315 -0
- package/vendor/procedural-animals/src/species/snake/index.js +73 -0
- package/vendor/procedural-animals/src/species/snake/motion.js +51 -0
- package/vendor/procedural-animals/src/species/snake/regions.js +51 -0
- package/vendor/procedural-animals/src/species/snake/rig.js +108 -0
- package/vendor/procedural-animals/src/species/snake/sculpt.js +122 -0
- package/vendor/procedural-animals/src/species/spider/coat.js +279 -0
- package/vendor/procedural-animals/src/species/spider/index.js +78 -0
- package/vendor/procedural-animals/src/species/spider/motion.js +72 -0
- package/vendor/procedural-animals/src/species/spider/regions.js +87 -0
- package/vendor/procedural-animals/src/species/spider/rig.js +118 -0
- package/vendor/procedural-animals/src/species/spider/sculpt.js +182 -0
- package/vendor/procedural-animals/src/species/wolf/behaviour.js +160 -0
- package/vendor/procedural-animals/src/species/wolf/coat.js +749 -0
- package/vendor/procedural-animals/src/species/wolf/index.js +107 -0
- package/vendor/procedural-animals/src/species/wolf/motion.js +80 -0
- package/vendor/procedural-animals/src/species/wolf/regions.js +57 -0
- package/vendor/procedural-animals/src/species/wolf/rig.js +87 -0
- package/vendor/procedural-animals/src/species/wolf/sculpt.js +339 -0
- package/vendor/procedural-animals/src/worker.js +29 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Domestic sheep (Ovis aries). Cloven-hoofed grazer in wool: the fleece is a sculpted volume broken
|
|
2
|
+
// into locks (sculpt.js) under short, tightly clumped, matte shells (the crimped staple tips), with a
|
|
3
|
+
// clean short-haired face and legs; horizontal bar pupils in amber irises; spiral horns in Merino
|
|
4
|
+
// rams; the flock animal's alarm, constant chewing while grazing, bleating, the ram's charge and the
|
|
5
|
+
// ewe's foot stamp (behaviour.js).
|
|
6
|
+
import { sheepRig, HEAD_O } from './rig.js';
|
|
7
|
+
import { sculptSheep, EYE } from './sculpt.js';
|
|
8
|
+
import { sheepRegions } from './regions.js';
|
|
9
|
+
import { sheepCoat } 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
|
+
|
|
14
|
+
const pick = (R, table) => {
|
|
15
|
+
let x = R() * table.reduce((s, [, w]) => s + w, 0);
|
|
16
|
+
for (const [k, w] of table) { x -= w; if (x <= 0) return k; }
|
|
17
|
+
return table[table.length - 1][0];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Breeds / morphs (variants). fleece: [min, max] total fleece length (m, a year's growth);
|
|
21
|
+
// horned: share of rams with horns; docked: share of docked tails; ear: carriage (rig.js EAR_SET)
|
|
22
|
+
const BREEDS = {
|
|
23
|
+
whiteface: { coats: [['white', 1]], fleece: [0.05, 0.12], horned: 0, docked: 0.6, ear: 'lateral', roman: [0, 0.2], topknot: 0.25, size: 1, legs: 1, girth: 1 },
|
|
24
|
+
suffolk: { coats: [['suffolk', 1]], fleece: [0.04, 0.09], horned: 0, docked: 0.65, ear: 'droop', roman: [0.7, 1], topknot: 0, size: 1.08, legs: 1.03, girth: 1.03 },
|
|
25
|
+
merino: { coats: [['merino', 1]], fleece: [0.06, 0.1], horned: 0.95, docked: 0.85, ear: 'small', roman: [0.2, 0.5], topknot: 1, size: 0.94, legs: 0.97, girth: 1 },
|
|
26
|
+
black: { coats: [['black', 75], ['brown', 25]], fleece: [0.05, 0.12], horned: 0.3, docked: 0.4, ear: 'lateral', roman: [0, 0.3], topknot: 0.15, size: 0.98, legs: 1, girth: 1 },
|
|
27
|
+
shorn: { coats: [['white', 60], ['texel', 40]], fleece: [0.004, 0.015], horned: 0, docked: 0.7, ear: 'lateral', roman: [0, 0.2], topknot: 0, size: 1, legs: 1, girth: 1 },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default {
|
|
31
|
+
id: 'sheep',
|
|
32
|
+
name: 'Sheep',
|
|
33
|
+
latin: 'Ovis aries',
|
|
34
|
+
group: 'hooves',
|
|
35
|
+
plan: 'quadruped',
|
|
36
|
+
covering: 'fur',
|
|
37
|
+
variants: [
|
|
38
|
+
{ id: 'whiteface', name: 'White-faced sheep', latin: 'Ovis aries' },
|
|
39
|
+
{ id: 'suffolk', name: 'Suffolk', latin: 'Ovis aries' },
|
|
40
|
+
{ id: 'merino', name: 'Merino', latin: 'Ovis aries' },
|
|
41
|
+
{ id: 'black', name: 'Black sheep', latin: 'Ovis aries' },
|
|
42
|
+
{ id: 'shorn', name: 'Shorn sheep', latin: 'Ovis aries' },
|
|
43
|
+
],
|
|
44
|
+
|
|
45
|
+
// Seeded individual. Breed / morph (o.variant: whiteface (default type), suffolk, merino, black,
|
|
46
|
+
// shorn) sets the colours, ears, Roman nose, horns and fleece; sex: ewe or ram (heavier, broader,
|
|
47
|
+
// thick neck, curled horns in horned breeds); age: adult or lamb (juvenile: long legs, short body,
|
|
48
|
+
// big head and ears, short tight curly fleece, long tail). The fleece length (params.fleece,
|
|
49
|
+
// 0 = shorn .. 0.15 m) is seeded within the breed's range (overrides: { fleece }).
|
|
50
|
+
variation(R0, o) {
|
|
51
|
+
// (the pipeline's stream is correlated between neighbouring seeds: re-mix it through an integer hash)
|
|
52
|
+
let h = (Math.floor(R0() * 4294967296) ^ Math.imul((o.seed ?? 1) + 0x632be5ab, 0x9e3779b1)) >>> 0;
|
|
53
|
+
h = Math.imul(h ^ (h >>> 16), 0x85ebca6b); h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35); h = (h ^ (h >>> 16)) >>> 0;
|
|
54
|
+
const R = rng(h);
|
|
55
|
+
for (let i = 0; i < 3; i++) R();
|
|
56
|
+
const variant = BREEDS[o.variant] ? o.variant : pick(R, [['whiteface', 40], ['suffolk', 24], ['merino', 16], ['black', 10], ['shorn', 10]]);
|
|
57
|
+
const Bd = BREEDS[variant];
|
|
58
|
+
const sex = o.sex || (R() < 0.4 ? 'male' : 'female');
|
|
59
|
+
const age = o.age || (R() < 0.18 ? 'juvenile' : 'adult');
|
|
60
|
+
const lamb = age === 'juvenile';
|
|
61
|
+
const ram = sex === 'male' && !lamb;
|
|
62
|
+
const g = () => (R() + R() + R() - 1.5) / 1.5; // ~[-1, 1], peaked
|
|
63
|
+
const coat = pick(R, Bd.coats);
|
|
64
|
+
// fleece length: a year's growth for adults, 10-20 mm tight curls for lambs
|
|
65
|
+
const u = 0.5 + 0.5 * g();
|
|
66
|
+
let fleece = lamb ? 0.012 + 0.01 * R() : Bd.fleece[0] + (Bd.fleece[1] - Bd.fleece[0]) * u;
|
|
67
|
+
if (o.overrides && o.overrides.fleece !== undefined) fleece = o.overrides.fleece;
|
|
68
|
+
fleece = Math.max(0, Math.min(0.15, fleece));
|
|
69
|
+
// the outer staple tips are shells; the rest of the fleece is sculpted volume
|
|
70
|
+
const staple = Math.max(0.005, Math.min(0.018, 0.25 * fleece + 0.004)) * (lamb ? 1.1 : 1);
|
|
71
|
+
const wool = fleece > 0.035 ? fleece - staple : 0; // (short fleeces: shells over the body skin only)
|
|
72
|
+
let horns = null;
|
|
73
|
+
if (ram && R() < Bd.horned) horns = { turns: (variant === 'merino' ? 1.0 : 0.75) + 0.35 * R(), base: 0.03 + 0.009 * R(), r0: 0.95 + 0.1 * R(), flare: 0.8 + 0.4 * R() };
|
|
74
|
+
else if (lamb && sex === 'male' && R() < Bd.horned) horns = { turns: 0.12 + 0.06 * R(), base: 0.012, r0: 0.75, flare: 0.5 };
|
|
75
|
+
const docked = !lamb ? R() < Bd.docked : R() < Bd.docked * 0.5;
|
|
76
|
+
const tailLen = docked ? 0.06 + 0.04 * R() : 0.3 + 0.08 * R();
|
|
77
|
+
const size = (ram ? 1.13 + 0.05 * R() : 1) * (1 + 0.045 * g()) * Bd.size * (lamb ? 0.62 : 1);
|
|
78
|
+
return {
|
|
79
|
+
sex, age, size, variant, coat,
|
|
80
|
+
fleece, staple, wool,
|
|
81
|
+
horns,
|
|
82
|
+
tailLen,
|
|
83
|
+
ear: Bd.ear,
|
|
84
|
+
earLift: R(),
|
|
85
|
+
roman: (Bd.roman[0] + (Bd.roman[1] - Bd.roman[0]) * R()) + (ram ? 0.2 : 0),
|
|
86
|
+
topknot: R() < Bd.topknot ? 0.4 + 0.6 * R() : 0,
|
|
87
|
+
folds: variant === 'merino' && !lamb ? (ram ? 0.7 : 0.4) + 0.3 * R() : 0,
|
|
88
|
+
muscle: coat === 'texel' ? 0.6 + 0.4 * R() : 0.3 * R(),
|
|
89
|
+
udder: sex === 'female' && !lamb ? 0.1 + 0.6 * R() : 0,
|
|
90
|
+
heavy: ram ? 0.6 + 0.4 * R() : 0,
|
|
91
|
+
hoofStripe: R(),
|
|
92
|
+
hornColor: variant === 'black' ? 0x6a5846 : 0xb09a78,
|
|
93
|
+
coatShade: g(), coatLightness: 0.05 * g(),
|
|
94
|
+
coatSeed: Math.floor(R() * 1e6),
|
|
95
|
+
minThick: 0.004,
|
|
96
|
+
warps: [
|
|
97
|
+
// (the head scale first: its centre is the unwarped head origin)
|
|
98
|
+
{ type: 'scaleAbout', c: HEAD_O, k: (1 + 0.035 * g()) * (lamb ? 1.22 : 1) * (ram ? 1.06 : 1), r0: 0.1, r1: 0.2 },
|
|
99
|
+
{ type: 'legs', k: (1 + 0.035 * g()) * Bd.legs * (lamb ? 1.24 : 1), top: 0.36 },
|
|
100
|
+
{ type: 'length', k: (1 + 0.035 * g()) * (lamb ? 0.84 : 1), z0: -0.4, z1: 0.3 },
|
|
101
|
+
{ type: 'girth', k: (1 + 0.04 * g()) * Bd.girth * (ram ? 1.05 : 1) * (lamb ? 0.9 : 1), cy: 0.47, z0: -0.5, z1: 0.36 },
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
rig: (params) => sheepRig(params),
|
|
106
|
+
sculpt: (m, rig, params) => sculptSheep(m, rig, params),
|
|
107
|
+
regions: sheepRegions,
|
|
108
|
+
coat: sheepCoat,
|
|
109
|
+
eyeSpecs: (params) => [1, -1].map((side) => ({ side, spec: EYE, headOrigin: HEAD_O, bone: 'head', look: eyeLook(params) })),
|
|
110
|
+
motion,
|
|
111
|
+
// wool: fine, dense strands in small tight clumps (crimped staple tips); matte
|
|
112
|
+
render: (params) => ({
|
|
113
|
+
markColor: srgb(['suffolk', 'black'].includes(params.variant) ? 0x141212 : 0x5c4a46),
|
|
114
|
+
strandDensity: params.variant === 'merino' ? 1500 : 1150,
|
|
115
|
+
clumpDensity: (params.fleece || 0) > 0.02 ? 1.9 : 1.3,
|
|
116
|
+
shellScale: 1,
|
|
117
|
+
finWidth: 0.35,
|
|
118
|
+
// (the short face and leg hair forms small tufts too, each leaning its own way: the face reads as short
|
|
119
|
+
// hair rather than a smooth rubber skin, and the highlight on a black face breaks up instead of running
|
|
120
|
+
// in glossy streaks; the default [0.0055, 0.016] left 4-6 mm hair untufted)
|
|
121
|
+
clumpLen: [0.0015, 0.009],
|
|
122
|
+
// (no silhouette fins: over a sculpted fleece they drew the lock bumps' contours as dark seams across
|
|
123
|
+
// the back and the rump, and on short coats (shorn, lambs) they traced the head / body mesh hand-over
|
|
124
|
+
// down the neck as a dotted line; the shells alone give the short coat's soft edge)
|
|
125
|
+
fins: false,
|
|
126
|
+
// (core render hint: the wool's shells slide down the staple as they rise; where the neck creases (the
|
|
127
|
+
// throat when grazing, the side of the neck toward which the head turns) they dove under the skin of the
|
|
128
|
+
// fold and it showed as a jagged bald line. Taken ~5 mm nearer the camera they stay on top; face and leg
|
|
129
|
+
// hair shorter than 8 mm is untouched)
|
|
130
|
+
shellDepthBias: [0.6, 0.008],
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// The sheep's eye: a horizontal bar pupil (rectangular, 2.5-3 : 1 when constricted) in a golden to
|
|
135
|
+
// amber-brown iris, sclera hardly visible, dark lids; lambs paler.
|
|
136
|
+
const IRISES = [
|
|
137
|
+
{ inner: 0x9c7a34, mid: 0xb8913f, hi: 0xd4b066, outer: 0x5e4418 }, // amber (default)
|
|
138
|
+
{ inner: 0x6e5020, mid: 0x8a6a30, hi: 0xa8864a, outer: 0x3e2a10 }, // darker amber-brown
|
|
139
|
+
{ inner: 0xa88a48, mid: 0xc8a85a, hi: 0xe0c888, outer: 0x6a5020 }, // pale golden
|
|
140
|
+
];
|
|
141
|
+
function eyeLook(params) {
|
|
142
|
+
const s = ((params.coatSeed || 0) % 100) / 100;
|
|
143
|
+
const ir = IRISES[params.age === 'juvenile' ? 2 : s < 0.6 ? 0 : s < 0.9 ? 1 : 2];
|
|
144
|
+
return {
|
|
145
|
+
pupil: 'bar',
|
|
146
|
+
lids: 'mammal',
|
|
147
|
+
iris: { inner: srgb(ir.inner), mid: srgb(ir.mid), hi: srgb(ir.hi), outer: srgb(ir.outer) },
|
|
148
|
+
sclera: { color: [0.45, 0.38, 0.32], visible: false },
|
|
149
|
+
lidColor: [0.03, 0.025, 0.022],
|
|
150
|
+
pupilSize: [0.1, 0.34],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Sheep motion data for the quadruped engine (schema: src/core/motion/quadruped.js).
|
|
2
|
+
// Numbers are for the reference individual (params.size = 1, a 0.70 m, 70 kg ewe); the engine
|
|
3
|
+
// scales them by dynamic similarity for lambs and big rams.
|
|
4
|
+
//
|
|
5
|
+
// Gaits: lateral-sequence 4-beat walk (0.9-1.3 m/s: 0.96-1.25 Hz,
|
|
6
|
+
// duty 0.66 -> 0.60, hoof swing height 49 mm fore / 55 mm hind, Kim & Breur 2008, treadmill studies),
|
|
7
|
+
// 2-beat diagonal trot (1.8-2.4 Hz, duty 0.45 -> 0.37), a 3-beat canter (right lead) in flock flight
|
|
8
|
+
// and the transverse gallop (2.5-3 Hz). Crossovers: walk -> trot at Froude ~0.45 (1.8 m/s for a
|
|
9
|
+
// 0.72 m hip height), trot -> canter / gallop 4.3 m/s at ~2.5 Hz (Heglund et al. 1974: v = 1.535
|
|
10
|
+
// M^0.24, f = 4.48 M^-0.14 for 70 kg).
|
|
11
|
+
import { hooks } from './behaviour.js';
|
|
12
|
+
|
|
13
|
+
const G = (name, v, f, D, off, o) => ({ name, v, f, D, off, ...o });
|
|
14
|
+
|
|
15
|
+
export const motion = {
|
|
16
|
+
maxSpeed: 8.5,
|
|
17
|
+
accel: [3, 6.5],
|
|
18
|
+
decel: 7,
|
|
19
|
+
turnRate: 3.0,
|
|
20
|
+
latAccelMax: 8,
|
|
21
|
+
gears: { walk: 0.95, trot: 2.8, canter: 4.7, gallop: 6.8 },
|
|
22
|
+
gallopBlend: [4.0, 6.5],
|
|
23
|
+
// name v f D [FL, FR, HL, HR]
|
|
24
|
+
gaits: [
|
|
25
|
+
G('walk', 0.0, 0.75, 0.7, [0.25, 0.75, 0.0, 0.5], { liftF: 0.042, liftH: 0.046, bobF: 0.01, bobH: 0.01, flex: 0, lat: 0.02, fold: 0.65, heel: 18, tail: 0, drop: 0 }),
|
|
26
|
+
G('walk', 1.5, 1.28, 0.6, [0.27, 0.77, 0.0, 0.5], { liftF: 0.05, liftH: 0.055, bobF: 0.022, bobH: 0.022, flex: 0, lat: 0.025, fold: 0.85, heel: 26, tail: 0.1, drop: 0 }),
|
|
27
|
+
G('trot', 2.05, 1.9, 0.45, [0.52, 0.02, 0.0, 0.5], { liftF: 0.075, liftH: 0.062, bobF: 0.026, bobH: 0.026, flex: 0.01, lat: 0.0, fold: 1.05, heel: 36, tail: 0.12, drop: 0.006 }),
|
|
28
|
+
G('trot', 3.8, 2.3, 0.36, [0.52, 0.02, 0.0, 0.5], { liftF: 0.09, liftH: 0.075, bobF: 0.03, bobH: 0.03, flex: 0.015, lat: 0.0, fold: 1.15, heel: 52, tail: 0.16, drop: 0.01 }),
|
|
29
|
+
G('canter', 4.4, 2.35, 0.35, [0.3, 0.55, 0.0, 0.27], { liftF: 0.1, liftH: 0.085, bobF: 0.024, bobH: 0.032, flex: 0.06, lat: 0, fold: 1.2, heel: 38, tail: 0.20, drop: 0.015 }),
|
|
30
|
+
G('canter', 5.1, 2.45, 0.32, [0.3, 0.55, 0.0, 0.26], { liftF: 0.105, liftH: 0.09, bobF: 0.025, bobH: 0.034, flex: 0.08, lat: 0, fold: 1.25, heel: 48, tail: 0.24, drop: 0.02 }),
|
|
31
|
+
G('gallop', 6.0, 2.6, 0.28, [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.3, heel: 45, tail: 0.28, drop: 0.022 }),
|
|
32
|
+
G('gallop', 8.5, 2.85, 0.24, [0.56, 0.66, 0.0, 0.1], { liftF: 0.115, liftH: 0.11, bobF: 0.024, bobH: 0.034, flex: 0.12, lat: 0, fold: 1.25, heel: 40, tail: 0.40, drop: 0.035 }),
|
|
33
|
+
],
|
|
34
|
+
feet: {
|
|
35
|
+
// cloven hooves on fairly upright pasterns: the fetlock sinks a little under load, the claws flip
|
|
36
|
+
// in swing, breakover about the claw tips
|
|
37
|
+
front: { type: 'unguligrade', contact: 1.0, curl: 62, flex: 4, sink: 6, hoofFlex: 15, swingBack: 0.06, liftBehind: 0.95 },
|
|
38
|
+
hind: { type: 'unguligrade', contact: 0.92, curl: 60, flex: 4, sink: 8, hoofFlex: 15, swingBack: 0.02 },
|
|
39
|
+
},
|
|
40
|
+
stance: { width: 1, gallopWidth: 0.8, sprawl: 0, crouch: 0, scuff: [10, 20, 0] },
|
|
41
|
+
// torso cross-sections of the shorn body (bind pose, reference size): centre height, half height,
|
|
42
|
+
// half width (half heights include the legs folded under the chest and thighs when lying down);
|
|
43
|
+
// behaviour.js adds the fleece of the individual
|
|
44
|
+
body: {
|
|
45
|
+
chest: { y: 0.47, hh: 0.25, hw: 0.165 },
|
|
46
|
+
mid: { y: 0.47, hh: 0.24, hw: 0.18 },
|
|
47
|
+
pelvis: { y: 0.53, hh: 0.3, hw: 0.17 },
|
|
48
|
+
rump: { z: -0.43, y: 0.53, hh: 0.3, hw: 0.14 },
|
|
49
|
+
back: 0.06,
|
|
50
|
+
},
|
|
51
|
+
head: {
|
|
52
|
+
// [speed, raise (m), reach (m), pitch (rad, + = nose down)]: head up and alert at rest, lower and
|
|
53
|
+
// forward at the walk (following the flock), stretched forward in flight
|
|
54
|
+
carriage: [[0, 0.02, -0.01, -0.04], [0.95, -0.02, 0.01, 0.03], [2.5, -0.02, 0.03, 0.03], [4.2, -0.05, 0.05, 0.08], [8, -0.08, 0.08, 0.12]],
|
|
55
|
+
stab: [[0, 0], [0.95, 0.15], [2.5, 0.45], [4.2, 0.35], [8, 0.4]],
|
|
56
|
+
neckBend: 34, neckPivot: 0.75, yaw: 0.85, pitchUp: 0.65, pitchDown: 0.9, mouth: 'jawTip',
|
|
57
|
+
},
|
|
58
|
+
tail: {
|
|
59
|
+
// [speed, pitch per segment from horizontal (deg), base -> tip]: hangs straight down (the docked
|
|
60
|
+
// stump too), lifts a little when running
|
|
61
|
+
carriage: [
|
|
62
|
+
[0.0, [-38, -64, -76, -82, -86, -88]],
|
|
63
|
+
[1.4, [-34, -60, -74, -80, -84, -86]],
|
|
64
|
+
[3.5, [-32, -58, -72, -79, -83, -85]],
|
|
65
|
+
[7, [-28, -52, -66, -74, -78, -80]],
|
|
66
|
+
],
|
|
67
|
+
stiffness: 0.9, sway: 5, flick: 0.4, wag: 0, swish: 0, curl: 0, balance: 0,
|
|
68
|
+
radius: [0.035, 0.025],
|
|
69
|
+
},
|
|
70
|
+
ears: { rest: [0, 0], mobility: 0.9, speedFlatten: 0.25, twitch: 1.5, prick: 0.25 },
|
|
71
|
+
breath: { rate: 0.3, amp: 0.006, pant: false, pantRate: 2.2, pantAmp: 0.014, heatSpeed: 6 },
|
|
72
|
+
actions: {
|
|
73
|
+
// grazing: muzzle on the sward, the forefeet a little spread
|
|
74
|
+
eat: { style: 'graze', dropF: 0.1, dropH: 0, pitch: 0.9, ahead: 0.6 },
|
|
75
|
+
drink: { dropF: 0.1, dropH: 0, pitch: 0.9, ahead: 0.6 },
|
|
76
|
+
// a low jump with the forelegs tucked (0.5-1 m obstacles)
|
|
77
|
+
jump: { height: 0.6, distance: 1.4, land: [0.16, 0.14] },
|
|
78
|
+
sit: { dropH: 0.8 },
|
|
79
|
+
// kneels on both carpi first, then drops the hindquarters; rises hind end first (ruminant)
|
|
80
|
+
lie: { down: 'front', up: 'hind' },
|
|
81
|
+
sleep: { down: 'front', up: 'hind' },
|
|
82
|
+
// lying sternal: forelegs folded under the chest (carpus flexed, cannons back along the ground)
|
|
83
|
+
fold: { front: { z: -0.2, k: 1.45, beta: 0.9 } },
|
|
84
|
+
},
|
|
85
|
+
hooks,
|
|
86
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// The head / body meshing boundary across the upper neck (regions.js), also used by the sculpt and
|
|
2
|
+
// the coat.
|
|
3
|
+
import { HZ, hl, EAR_BASE, EAR_SET, earTip } from './rig.js';
|
|
4
|
+
import { norm } from '../../core/math/vec.js';
|
|
5
|
+
|
|
6
|
+
// cut across the neck just behind the ears, perpendicular to the head's axis (the dense head mesh
|
|
7
|
+
// stops where the neck wool starts: the head emerges from the fleece)
|
|
8
|
+
// (two planes: one across the head's axis behind the ears, one tilted through the throat behind the
|
|
9
|
+
// jaw so the lower neck and the breast stay in the body)
|
|
10
|
+
const C1 = hl([0, 0, -0.078]), C2 = [0, 0.76, 0.5], D2 = norm([0, 0.45, 1]);
|
|
11
|
+
export const NECK_CUT = { c: C1, d: HZ, band: 0.012 };
|
|
12
|
+
// ... and the ears, swept back past that plane, stay in the head mesh: a zone round every ear any
|
|
13
|
+
// individual can carry (each carriage, ear lift and the horned ram's base), left side; mirrored by |x|
|
|
14
|
+
const EAR_SEGS = [];
|
|
15
|
+
for (const ear of Object.keys(EAR_SET)) {
|
|
16
|
+
for (const earLift of [0, 0.5, 1]) {
|
|
17
|
+
for (const horns of [null, { turns: 1 }]) {
|
|
18
|
+
const base = horns ? [0.05, 0.002, -0.066] : EAR_BASE;
|
|
19
|
+
EAR_SEGS.push([hl(base), hl(earTip({ ear, earLift, horns }, base))]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const EAR_R = 0.038;
|
|
24
|
+
function earDist(x, y, z) {
|
|
25
|
+
let dm = 1e9;
|
|
26
|
+
for (const [a, b] of EAR_SEGS) {
|
|
27
|
+
const dx = b[0] - a[0], dy = b[1] - a[1], dz = b[2] - a[2];
|
|
28
|
+
const px = Math.abs(x) - a[0], py = y - a[1], pz = z - a[2];
|
|
29
|
+
const t = Math.max(0, Math.min(1, (px * dx + py * dy + pz * dz) / (dx * dx + dy * dy + dz * dz)));
|
|
30
|
+
const d = Math.hypot(px - dx * t, py - dy * t, pz - dz * t);
|
|
31
|
+
if (d < dm) dm = d;
|
|
32
|
+
}
|
|
33
|
+
return dm;
|
|
34
|
+
}
|
|
35
|
+
export const neckS = (x, y, z) => {
|
|
36
|
+
const s = Math.min(
|
|
37
|
+
(x - C1[0]) * HZ[0] + (y - C1[1]) * HZ[1] + (z - C1[2]) * HZ[2],
|
|
38
|
+
(y - C2[1]) * D2[1] + (z - C2[2]) * D2[2],
|
|
39
|
+
);
|
|
40
|
+
return s > EAR_R ? s : Math.max(s, EAR_R - earDist(x, y, z));
|
|
41
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Meshing plan: body at 5.6 mm (0.8 % of the withers height; the fleece makes a large surface),
|
|
2
|
+
// head at 2.6 mm overlapping the body across the upper neck and cross-faded, eyelid patches at
|
|
3
|
+
// 0.9 mm, the lower lip / chin as its own rigid surface (the mouth opens) and the horns as a rigid
|
|
4
|
+
// keratin surface on the skull.
|
|
5
|
+
import { EYE } from './sculpt.js';
|
|
6
|
+
import { HEAD_O, hl } from './rig.js';
|
|
7
|
+
import { eyeFrameOf } from '../../core/sdf/eyeSocket.js';
|
|
8
|
+
import { smoothstep } from '../../core/math/vec.js';
|
|
9
|
+
|
|
10
|
+
export { NECK_CUT, neckS } from './neck.js';
|
|
11
|
+
import { NECK_CUT, neckS } from './neck.js';
|
|
12
|
+
|
|
13
|
+
export const EYE_PATCH = { R: 0.024, B: 0.004, h: 0.0011, centres: [1, -1].map((s) => eyeFrameOf(EYE, HEAD_O, s).c) };
|
|
14
|
+
// the front of the nose re-meshed finer too: the nostril slits (7 x 20 mm carves) and the philtrum came out of
|
|
15
|
+
// the 4-5 mm face cells as ragged dark blotches; ~1.2 mm cells (2.4 at medium) give clean slits
|
|
16
|
+
export const NOSE_PATCH = { R: 0.024, B: 0.004, h: 0.0012, centres: [hl([0, -0.022, 0.195])] };
|
|
17
|
+
const ballWeight = (P, x, y, z) => {
|
|
18
|
+
let dmin = 1e9;
|
|
19
|
+
for (const c of P.centres) dmin = Math.min(dmin, Math.hypot(x - c[0], y - c[1], z - c[2]));
|
|
20
|
+
return 1 - smoothstep(P.R - P.B, P.R + P.B, dmin);
|
|
21
|
+
};
|
|
22
|
+
export const eyePatchWeight = (x, y, z) => ballWeight(EYE_PATCH, x, y, z);
|
|
23
|
+
// (the patches lie far apart: a point is in one at most)
|
|
24
|
+
export const patchWeight = (x, y, z) => Math.max(ballWeight(EYE_PATCH, x, y, z), ballWeight(NOSE_PATCH, x, y, z));
|
|
25
|
+
|
|
26
|
+
export function sheepRegions(rig, params, Q) {
|
|
27
|
+
const r = Q.res;
|
|
28
|
+
const W = 0.2 + (params.wool || 0) * 1.3;
|
|
29
|
+
const hBody = 0.0065 * (1 + 1.6 * (params.wool || 0)) * r;
|
|
30
|
+
// (the band is wider than a body cell, so the body's cut edge, which lies up to a cell into the band,
|
|
31
|
+
// stays in its hidden half: at the low and crowd tiers a 12 mm band left it on show, an open seam
|
|
32
|
+
// across the top of the neck)
|
|
33
|
+
const B = Math.max(NECK_CUT.band, hBody * 1.2);
|
|
34
|
+
// (eyelid patches at medium too: Safari and phones show medium, and the coarse face cut the almond into a
|
|
35
|
+
// ragged notch)
|
|
36
|
+
const patches = (Q.eyePatches || r <= 2) ? [EYE_PATCH, NOSE_PATCH].flatMap((P) => P.centres.map((c) => ({ c, R: P.R, B: P.B, h: P.h * Math.max(1, r) }))) : [];
|
|
37
|
+
// (the face a little finer at medium: the nostril slits and the lip line came out ragged)
|
|
38
|
+
const hm = r === 2 ? 0.78 : 1;
|
|
39
|
+
const head = [
|
|
40
|
+
{ name: 'head', part: 'body', bmin: [-0.3, 0.5, 0.3], bmax: [0.3, 1.05, 0.8], h: 0.0031 * r * hm, F: 6, clip: (x, y, z) => neckS(x, y, z) > -B, patches },
|
|
41
|
+
{ name: 'jaw', part: 'jaw', bmin: [-0.05, 0.5, 0.45], bmax: [0.05, 0.8, 0.8], h: 0.0027 * r * hm, F: 6, rigidBone: 'jaw' },
|
|
42
|
+
];
|
|
43
|
+
if (params.horns && params.horns.turns > 0) {
|
|
44
|
+
head.push({ name: 'horn', part: 'horn', bmin: [-0.36, 0.5, 0.2], bmax: [0.36, 1.12, 0.8], h: (params.horns.base > 0.025 ? 0.0042 : 0.003) * r, F: 6, rigidBone: 'head' });
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
jobs: [
|
|
48
|
+
[{ name: 'body', part: 'body', bmin: [-W - 0.02, -0.01, -0.62 - W], bmax: [W + 0.02, 1.02, 0.72], h: hBody, F: 4, clip: (x, y, z) => neckS(x, y, z) < B }],
|
|
49
|
+
head,
|
|
50
|
+
],
|
|
51
|
+
fade(x, y, z, name, patch) {
|
|
52
|
+
const sN = neckS(x, y, z);
|
|
53
|
+
if (name === 'body') return 1 - smoothstep(-B, B, sN);
|
|
54
|
+
if (name === 'head') {
|
|
55
|
+
let f = smoothstep(-B, B, sN);
|
|
56
|
+
if (patches.length) { const ew = patchWeight(x, y, z); f *= patch ? ew : 1 - ew; }
|
|
57
|
+
return f;
|
|
58
|
+
}
|
|
59
|
+
return 1;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// Sheep skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
|
|
2
|
+
// Reference individual: a white-faced medium-wool ewe (Dorset / Cheviot / Texel type), 0.70 m at the
|
|
3
|
+
// withers (skeleton, without the fleece), ~70 kg. Landmarks measured on
|
|
4
|
+
// side2.jpg (1 px = 1.67 mm), side3_texel.jpg (shorn: nose -> buttock 1.73 SH, belly 0.39 SH, head
|
|
5
|
+
// 0.37 SH) and the research limb table (sheep have long cannons, short forearms).
|
|
6
|
+
//
|
|
7
|
+
// Hooves: the standard quadruped bones plus a hoof bone per leg, exactly like the horse and the goat:
|
|
8
|
+
// fpaw / hpaw = pastern (fetlock -> coffin joint), fhoof / hhoof = the cloven hoof (coffin joint ->
|
|
9
|
+
// toe), so the engine keeps the claws flat while the fetlock sinks under load.
|
|
10
|
+
//
|
|
11
|
+
// The rig depends on the individual through the ears (lateral and horizontal; long and drooping in
|
|
12
|
+
// the Suffolk: params.ear) and the tail (long, hanging to the hocks, or docked: params.tail).
|
|
13
|
+
import { buildRig } from '../../core/rig/rig.js';
|
|
14
|
+
import { quadrupedBones, quadrupedLimbs, tailChain } from '../../core/rig/quadruped.js';
|
|
15
|
+
|
|
16
|
+
export const TAIL_SEGS = 6;
|
|
17
|
+
|
|
18
|
+
// Head frame: modelled along its own axis (poll -> muzzle), pitched 37 degrees nose-down in the
|
|
19
|
+
// bind pose; the dorsal line falls a further 11 degrees from the axis toward the nose (sculpt.js topY),
|
|
20
|
+
// so the nasal line stands 48 degrees to the ground (side2: 46 deg). (At 48 degrees for the axis, the
|
|
21
|
+
// nasal line stood at 59: a face hanging straight down from a high dome, the "boot".) Head-local
|
|
22
|
+
// coordinates: x lateral, y dorsal (forehead side), z along the axis toward the muzzle; origin on the
|
|
23
|
+
// axis 0.07 m in front of the poll, level with the eyes.
|
|
24
|
+
export const HEAD_PITCH = (33 * Math.PI) / 180;
|
|
25
|
+
export const HZ = [0, -Math.sin(HEAD_PITCH), Math.cos(HEAD_PITCH)];
|
|
26
|
+
export const HY = [0, Math.cos(HEAD_PITCH), Math.sin(HEAD_PITCH)];
|
|
27
|
+
const POLL = [0, 0.895, 0.54]; // top of the poll (skin), bind
|
|
28
|
+
export const HEAD_O = [0, POLL[1] + 0.07 * HZ[1], POLL[2] + 0.07 * HZ[2]];
|
|
29
|
+
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]];
|
|
30
|
+
// head-local direction -> world
|
|
31
|
+
export const hdir = (v) => [v[0], v[1] * HY[1] + v[2] * HZ[1], v[1] * HY[2] + v[2] * HZ[2]];
|
|
32
|
+
|
|
33
|
+
// ears (head-local, left): carried out to the sides and swept back, so the leaf reads from the side as well
|
|
34
|
+
// as from the front (front1, face1, side4_suffolk, extra/Suffolk_sheep_20790901685, Tete_de_brebie_Suffolk:
|
|
35
|
+
// "aeroplane" ears seen from the front, a long blade reaching back past the poll seen from the side). Given
|
|
36
|
+
// as a world direction in the bind pose (back = degrees swept back from straight out, down = degrees below
|
|
37
|
+
// level) and a length; the Suffolk's are longer and hang a little; the Merino's smaller. (Straight out to
|
|
38
|
+
// the sides, an ear seen from the side was only its foreshortened stalk: a stub against the poll.)
|
|
39
|
+
// (At 40-46 deg back with the blade on edge, the ear read as a pink cup standing up from the side and a
|
|
40
|
+
// paddle behind the poll. At 32-36 deg back the near ear, seen from the side, was still a short
|
|
41
|
+
// pink cup over the poll (its length foreshortened) and the far ear a paddle; now 46-48 deg back (Suffolk 40)
|
|
42
|
+
// and 20 deg below level (side2: the ear a leaf held level, pointing back, its inside showing), the blade's
|
|
43
|
+
// turn in sculpt.js.)
|
|
44
|
+
export const EAR_BASE = [0.056, 0.006, -0.058]; // (at the top corners of the head, behind the eyes)
|
|
45
|
+
export const EAR_SET = {
|
|
46
|
+
lateral: { back: 46, down: 20, len: 0.135 },
|
|
47
|
+
droop: { back: 40, down: 28, len: 0.152 },
|
|
48
|
+
small: { back: 48, down: 14, len: 0.112 },
|
|
49
|
+
};
|
|
50
|
+
// world direction (bind) -> head-local
|
|
51
|
+
const toLocal = (d) => [d[0], d[1] * HY[1] + d[2] * HY[2], d[1] * HZ[1] + d[2] * HZ[2]];
|
|
52
|
+
export function earTip(params = {}, base = EAR_BASE) {
|
|
53
|
+
const E = EAR_SET[params.ear] || EAR_SET.lateral;
|
|
54
|
+
// (a horned ram's ear comes out under the horn's sweep: less swept back, or it runs into the coil)
|
|
55
|
+
const back = (params.horns && params.horns.turns > 0.3 ? 0.35 : 1) * E.back * Math.PI / 180;
|
|
56
|
+
const down = (E.down + 14 * ((params.earLift ?? 0.5) - 0.5)) * Math.PI / 180;
|
|
57
|
+
const d = toLocal([Math.cos(down) * Math.cos(back), -Math.sin(down), -Math.cos(down) * Math.sin(back)]);
|
|
58
|
+
const L = E.len;
|
|
59
|
+
return [base[0] + d[0] * L, base[1] + d[1] * L, base[2] + d[2] * L];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// tail: long (undocked, to the hocks) or docked (a short stump)
|
|
63
|
+
export function tailSpec(params = {}) {
|
|
64
|
+
const L = params.tailLen ?? 0.34;
|
|
65
|
+
const w = [0.2, 0.19, 0.17, 0.16, 0.14, 0.14];
|
|
66
|
+
const long = L > 0.15;
|
|
67
|
+
return {
|
|
68
|
+
len: L,
|
|
69
|
+
lens: w.map((f) => f * L),
|
|
70
|
+
pitch: long ? [-38, -64, -76, -82, -86, -88] : [-28, -45, -55, -60, -62, -64],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function sheepJoints(params = {}) {
|
|
75
|
+
const earB = params.horns && params.horns.turns > 0.3 ? [0.05, 0.002, -0.066] : EAR_BASE;
|
|
76
|
+
const J = {
|
|
77
|
+
nose: hl([0, -0.014, 0.195]), // (the front of the nose pad and upper lip: the engine keeps it off the ground)
|
|
78
|
+
occiput: hl([0, -0.045, -0.1]), // (behind the poll and horn bases: the skull top is all 'head')
|
|
79
|
+
neckMid: [0, 0.715, 0.425],
|
|
80
|
+
neckBase: [0, 0.555, 0.285],
|
|
81
|
+
chestMid: [0, 0.585, 0.13],
|
|
82
|
+
thoraxRear: [0, 0.61, -0.03],
|
|
83
|
+
lumbarMid: [0, 0.622, -0.17],
|
|
84
|
+
lumbosacral: [0, 0.625, -0.3],
|
|
85
|
+
tailBase: [0, 0.612, -0.47],
|
|
86
|
+
// fore: scapula sloping ~60 deg, humerus down and back, forearm and cannon vertical, pastern ~50
|
|
87
|
+
// deg (research: humerus 0.17, radius 0.18, cannon 0.13)
|
|
88
|
+
scapTopL: [0.056, 0.668, 0.21],
|
|
89
|
+
shoulderL: [0.086, 0.49, 0.305],
|
|
90
|
+
elbowL: [0.08, 0.345, 0.215],
|
|
91
|
+
wristL: [0.068, 0.185, 0.232],
|
|
92
|
+
mcpL: [0.062, 0.064, 0.238],
|
|
93
|
+
fcoffinL: [0.062, 0.028, 0.258],
|
|
94
|
+
ftoeL: [0.062, 0.002, 0.3],
|
|
95
|
+
// hind: hip joint, stifle, hock, fetlock, coffin joint, toe (femur 0.20, tibia 0.23, cannon 0.15)
|
|
96
|
+
hipL: [0.076, 0.555, -0.33],
|
|
97
|
+
kneeL: [0.09, 0.385, -0.215],
|
|
98
|
+
hockL: [0.064, 0.215, -0.385],
|
|
99
|
+
mtpL: [0.058, 0.066, -0.365],
|
|
100
|
+
hcoffinL: [0.058, 0.029, -0.343],
|
|
101
|
+
htoeL: [0.058, 0.002, -0.3],
|
|
102
|
+
jawHinge: hl([0, -0.045, -0.02]),
|
|
103
|
+
jawTip: hl([0, -0.064, 0.189]), // (the front of the lower lip: the mouth the engine puts on the ground)
|
|
104
|
+
// (horned rams: the ears come out below and behind the horn bases)
|
|
105
|
+
earBaseL: hl(earB),
|
|
106
|
+
earTipL: hl(earTip(params, earB)),
|
|
107
|
+
// udder (ewes) / scrotum (rams): its own rigid bone below the pelvis, so it can fold up out of the
|
|
108
|
+
// ground when the sheep lies down (hooks.pose)
|
|
109
|
+
udderTop: [0, 0.4, -0.3],
|
|
110
|
+
udderBot: [0, 0.27, -0.29],
|
|
111
|
+
};
|
|
112
|
+
const T = tailSpec(params);
|
|
113
|
+
tailChain(J, 'tailBase', T.pitch, T.lens);
|
|
114
|
+
return J;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function sheepBones() {
|
|
118
|
+
const b = quadrupedBones({ tailSegs: TAIL_SEGS, ears: true, jaw: true });
|
|
119
|
+
for (const d of b) {
|
|
120
|
+
if (d[0] === 'fpaw{S}') { d[2] = 'fcoffin{S}'; d[4] = { region: 'limb', group: 'F{S}' }; }
|
|
121
|
+
if (d[0] === 'hpaw{S}') { d[2] = 'hcoffin{S}'; d[4] = { region: 'limb', group: 'H{S}' }; }
|
|
122
|
+
}
|
|
123
|
+
b.push(['udder', 'udderTop', 'udderBot', 'pelvis', { region: 'torso', group: 'udder' }]);
|
|
124
|
+
b.push(
|
|
125
|
+
['fhoof{S}', 'fcoffin{S}', 'ftoe{S}', 'fpaw{S}', { region: 'foot', group: 'F{S}' }],
|
|
126
|
+
['hhoof{S}', 'hcoffin{S}', 'htoe{S}', 'hpaw{S}', { region: 'foot', group: 'H{S}' }],
|
|
127
|
+
);
|
|
128
|
+
return b;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function sheepRig(params = {}, J = sheepJoints(params)) {
|
|
132
|
+
const limbs = quadrupedLimbs({
|
|
133
|
+
front: { tCore: 0.5, aCore: 0.05, aBody: -0.15, midX: 0.0 },
|
|
134
|
+
hind: { tCore: 0.45, aCore: 0.022, aBody: -0.2, midX: 0.008 },
|
|
135
|
+
});
|
|
136
|
+
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); }
|
|
137
|
+
return buildRig({
|
|
138
|
+
joints: J,
|
|
139
|
+
unit: 0.92,
|
|
140
|
+
headOrigin: HEAD_O,
|
|
141
|
+
bones: sheepBones(),
|
|
142
|
+
axial: {
|
|
143
|
+
points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + (i + 1))],
|
|
144
|
+
bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis', ...Array.from({ length: TAIL_SEGS }, (_, i) => 'tail' + i)],
|
|
145
|
+
// the skull's influence reaches back into the throat (widening with the depth below the axis)
|
|
146
|
+
blend: { 1: [-0.01, 0.17, 7], 2: [-0.19, 0.22, 0], 3: [-0.22, 0.17, 0] },
|
|
147
|
+
bodyTail: 0, // (the britch wool does not blend into the tail: it tore when the thighs folded to lie down)
|
|
148
|
+
// (core weights.js `cascade`: the occiput's throat lever reaches past the mid-neck joint, where the default
|
|
149
|
+
// chain weighting cut the skull's share from 0.2-0.4 to 0 within 2 cm of coarse neck: the neck wool creased
|
|
150
|
+
// along that line, a jagged crack, whenever the head dropped or turned. It now fades out over the 7 cm past
|
|
151
|
+
// the joint. Not in the Merino: the fade stretches the neck wool a little more when grazing and sleeping
|
|
152
|
+
// (pattern edges > 1.5x 29.8 -> 31.0 % of 30), and its crease is left to the shells' depth bias, index.js)
|
|
153
|
+
cascade: params.variant === 'merino' ? false : { 1: 0.07 },
|
|
154
|
+
},
|
|
155
|
+
limbs,
|
|
156
|
+
appendages: [
|
|
157
|
+
{ group: 'earL', bone: 'earL', blend: [-0.002, 0.004] },
|
|
158
|
+
{ group: 'earR', bone: 'earR', blend: [-0.002, 0.004] },
|
|
159
|
+
{ group: 'udder', bone: 'udder', blend: [-0.004, 0.02] },
|
|
160
|
+
],
|
|
161
|
+
webTags: ['flankfold', 'thighfront', 'scapmuscle', 'pectoral', 'forearmweb', 'woolarm', 'woolthigh', 'woolweb'],
|
|
162
|
+
});
|
|
163
|
+
}
|