@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,156 +0,0 @@
|
|
|
1
|
-
// True frog (Ranidae) skeleton in bind pose (metres). Forward = +Z, up = +Y, the animal's left = +X.
|
|
2
|
-
//
|
|
3
|
-
// Reference individual: adult female American bullfrog (Lithobates catesbeianus), snout-vent length
|
|
4
|
-
// (SVL) 140 mm. The bind pose IS the classic sitting frog (the resting stance of the
|
|
5
|
-
// quadruped engine): forelegs upright on flat hands, hind legs folded in a Z beside the body (femur
|
|
6
|
-
// forward and out, tibiofibula back alongside it, tarsus and the long webbed foot flat on the ground
|
|
7
|
-
// pointing forward and out), the trunk rising from the vent to the sacral hump and on to the flat
|
|
8
|
-
// head. No neck: the neck joints sit packed behind the skull. No tail (the urostyle is the pelvis
|
|
9
|
-
// bone, lumbosacral -> tailBase).
|
|
10
|
-
//
|
|
11
|
-
// Frog bones mapped onto the standard quadruped set (core/rig/quadruped.js):
|
|
12
|
-
// pelvis (lumbosacral -> tailBase) ilia + urostyle: the ilio-sacral hinge is the sacral hump
|
|
13
|
-
// femur / tibia femur / tibiofibula
|
|
14
|
-
// metatarsus (hock -> mtp) the elongated tarsus (astragalus + calcaneum)
|
|
15
|
-
// hpaw (mtp -> htoe) metatarsals + toes (toe IV), webbed
|
|
16
|
-
// humerus / radius humerus / radio-ulna
|
|
17
|
-
// metacarpus / fpaw palm / fingers (4)
|
|
18
|
-
// Extra bones: eyeL / eyeR (the eyes retract into the head to blink and swallow), throat (buccal
|
|
19
|
-
// floor and vocal sac: pumping and croaking), tongue (attached at the front of the lower jaw, flips
|
|
20
|
-
// out forward).
|
|
21
|
-
import { buildRig } from '../../core/rig/rig.js';
|
|
22
|
-
import { quadrupedBones, quadrupedLimbs } from '../../core/rig/quadruped.js';
|
|
23
|
-
import { sub, add, mul, norm, cross, dot, len } from '../../core/math/vec.js';
|
|
24
|
-
|
|
25
|
-
// head-local origin: on the midline, level with the eye centres
|
|
26
|
-
export const HEAD_O = [0, 0.06, 0.049];
|
|
27
|
-
export const hl = (v) => [v[0] + HEAD_O[0], v[1] + HEAD_O[1], v[2] + HEAD_O[2]];
|
|
28
|
-
|
|
29
|
-
// limb segment lengths at SVL 140 mm (ranid ratios)
|
|
30
|
-
export const SEG = { hum: 0.026, rad: 0.022, fem: 0.064, tib: 0.071 };
|
|
31
|
-
// stance.sprawl of motion.js: the engine places the feet sprawl x leg length x 0.35 further out than
|
|
32
|
-
// the bind, and bends knees / elbows toward poles turned out by sprawl x 1.6; the bind is built with
|
|
33
|
-
// the same poles and its feet that much further in, so the resting stance reproduces it
|
|
34
|
-
export const SPRAWL = 0.25;
|
|
35
|
-
|
|
36
|
-
// Knee / elbow of a two-bone chain a -> c (lengths l1, l2) bent toward the pole direction (the
|
|
37
|
-
// engine's IK solve, so the bind limb lies in the plane the engine bends it in)
|
|
38
|
-
export function solve2(a, c, l1, l2, pole) {
|
|
39
|
-
const d = sub(c, a), D = len(d), e1 = norm(d);
|
|
40
|
-
let e2 = sub(pole, mul(e1, dot(pole, e1)));
|
|
41
|
-
e2 = norm(e2);
|
|
42
|
-
const cosA = Math.max(-1, Math.min(1, (l1 * l1 + D * D - l2 * l2) / (2 * l1 * D)));
|
|
43
|
-
return add(a, add(mul(e1, cosA * l1), mul(e2, Math.sqrt(1 - cosA * cosA) * l1)));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// the sitting foot (left): heel beside the vent, tarsus and foot forward (tarsus pitched ~4.4 deg)
|
|
47
|
-
const FOOT = { x: 0.035, hockBack: 0.0175, tilt: 4.4 };
|
|
48
|
-
|
|
49
|
-
// the eye centre (the eye bone's head) of the left eye, see sculpt.js EYE
|
|
50
|
-
export const EYE_C = [0.0152, 0.0012, -0.0002];
|
|
51
|
-
|
|
52
|
-
export function frogJoints(params = {}) {
|
|
53
|
-
const J = {
|
|
54
|
-
// axial: vent -> sacral hump -> back -> skull
|
|
55
|
-
tailBase: [0, 0.021, -0.052],
|
|
56
|
-
lumbosacral: [0, 0.037, -0.03],
|
|
57
|
-
lumbarMid: [0, 0.042, -0.017],
|
|
58
|
-
thoraxRear: [0, 0.045, -0.004],
|
|
59
|
-
chestMid: [0, 0.047, 0.009],
|
|
60
|
-
neckBase: [0, 0.049, 0.018],
|
|
61
|
-
neckMid: [0, 0.0505, 0.023],
|
|
62
|
-
occiput: [0, 0.052, 0.028],
|
|
63
|
-
nose: [0, 0.0505, 0.088],
|
|
64
|
-
jawHinge: [0, 0.0395, 0.03],
|
|
65
|
-
jawTip: [0, 0.0405, 0.086],
|
|
66
|
-
// forelimb: shoulder behind the jaw angle, humerus back and down along the flank, radio-ulna
|
|
67
|
-
// nearly upright, palm flat, fingers pointing forward and in
|
|
68
|
-
scapTopL: [0.013, 0.054, 0.012],
|
|
69
|
-
shoulderL: [0.0175, 0.034, 0.016],
|
|
70
|
-
wristL: [0.025, 0.0055, 0.011],
|
|
71
|
-
mcpL: [0.025, 0.0036, 0.0225],
|
|
72
|
-
ftoeL: [0.025, 0.0011, 0.0395],
|
|
73
|
-
// hind limb: the Z-fold of the sit: femur forward and out, tibiofibula back alongside it, the heel
|
|
74
|
-
// beside the vent, tarsus and the long foot forward on the ground
|
|
75
|
-
hipL: [0.0105, 0.028, -0.044],
|
|
76
|
-
};
|
|
77
|
-
// (the engine keeps a foot in the plane of its forward axis and places it by its joints' y / z only:
|
|
78
|
-
// the bind hands and feet run straight ahead, the fingers and toes fan out from them in the sculpt:
|
|
79
|
-
// fingers turned in, the long toes turned out)
|
|
80
|
-
const tt = (FOOT.tilt * Math.PI) / 180;
|
|
81
|
-
J.hockL = [FOOT.x, 0.0056 + 0.0377 * Math.sin(tt), J.hipL[2] - FOOT.hockBack];
|
|
82
|
-
J.mtpL = [FOOT.x, 0.0056, J.hockL[2] + 0.0377 * Math.cos(tt)];
|
|
83
|
-
J.htoeL = [FOOT.x, 0.0012, J.mtpL[2] + 0.0606];
|
|
84
|
-
// knee and elbow from the engine's poles (sprawl)
|
|
85
|
-
J.kneeL = solve2(J.hipL, J.hockL, SEG.fem, SEG.tib, [0.12 + SPRAWL * 1.6, 0, 1]);
|
|
86
|
-
J.elbowL = solve2(J.shoulderL, J.wristL, SEG.hum, SEG.rad, [0.08 + SPRAWL * 1.6, 0, -1]);
|
|
87
|
-
// extra bones
|
|
88
|
-
const ec = hl(EYE_C);
|
|
89
|
-
J.eyeBaseL = ec;
|
|
90
|
-
J.eyeTopL = [ec[0], ec[1] + 0.008, ec[2]];
|
|
91
|
-
J.throatBase = [0, 0.044, 0.036];
|
|
92
|
-
J.throatTip = [0, 0.03, 0.046];
|
|
93
|
-
J.tongueBase = [0, 0.0425, 0.079];
|
|
94
|
-
J.tongueTip = [0, 0.0435, 0.046];
|
|
95
|
-
void params;
|
|
96
|
-
return J;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// rig.unit: the frog is short at the shoulder (0.054 m / 0.76 m = 0.07 of the cheetah) but its limbs are
|
|
100
|
-
// long (hind limb 0.17 m, ~0.3 of the cheetah's). The core scales its skin-blend widths by the unit, and
|
|
101
|
-
// the knee and ankle of the Z-folded hind leg swing ~150 deg between the sit and a leap: they need
|
|
102
|
-
// blends as wide as the limb's scale, so the limb scale is used. The species' own blend distances
|
|
103
|
-
// below are given in metres (u()).
|
|
104
|
-
export const UNIT = 0.3;
|
|
105
|
-
const u = (m) => m / UNIT;
|
|
106
|
-
|
|
107
|
-
export function frogRig(params = {}) {
|
|
108
|
-
const J = frogJoints(params);
|
|
109
|
-
const rig = buildRig({
|
|
110
|
-
joints: J,
|
|
111
|
-
// characteristic length relative to the cheetah: shoulder (scapula top) height 0.054 m / 0.76 m
|
|
112
|
-
unit: UNIT,
|
|
113
|
-
headOrigin: HEAD_O,
|
|
114
|
-
bones: quadrupedBones({
|
|
115
|
-
tailSegs: 0, ears: false, jaw: true,
|
|
116
|
-
extra: [
|
|
117
|
-
['eye{S}', 'eyeBase{S}', 'eyeTop{S}', 'head', { region: 'head', group: 'eye{S}' }],
|
|
118
|
-
['throat', 'throatBase', 'throatTip', 'head', { region: 'head', group: 'throat' }],
|
|
119
|
-
['tongue', 'tongueBase', 'tongueTip', 'jaw', { region: 'jaw', group: 'tongue' }],
|
|
120
|
-
],
|
|
121
|
-
}),
|
|
122
|
-
axial: {
|
|
123
|
-
points: ['nose', 'occiput', 'neckMid', 'neckBase', 'chestMid', 'thoraxRear', 'lumbarMid', 'lumbosacral', 'tailBase'],
|
|
124
|
-
bones: ['head', 'neck2', 'neck1', 'chest', 'spine3', 'spine2', 'spine1', 'pelvis'],
|
|
125
|
-
// no neck: the skull's skin blends into the shoulders over a wide band
|
|
126
|
-
blend: { 1: [u(-0.0084), u(0.0084), 0.5], 2: [u(-0.0042), u(0.0042)], 3: [u(-0.0042), u(0.0042)] },
|
|
127
|
-
},
|
|
128
|
-
limbs: frogLimbs(params),
|
|
129
|
-
appendages: [
|
|
130
|
-
{ group: 'eyeL', bone: 'eyeL', blend: [u(-0.0014), u(0.0021)] },
|
|
131
|
-
{ group: 'eyeR', bone: 'eyeR', blend: [u(-0.0014), u(0.0021)] },
|
|
132
|
-
{ group: 'throat', bone: 'throat', blend: [u(-0.00105), u(0.0021)] },
|
|
133
|
-
],
|
|
134
|
-
webTags: ['groin', 'thighweb', 'armpit'],
|
|
135
|
-
});
|
|
136
|
-
return rig;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Skin-weight limbs: the standard ones; in the hind limb only the rigid webbed foot is 'distal' (the
|
|
140
|
-
// ankle of the frog's Z-folded leg swings as far as its knee and blends as widely).
|
|
141
|
-
export function frogLimbs(params = {}) {
|
|
142
|
-
const L = quadrupedLimbs({ front: { tCore: 0.75, aCore: u(0.0035), aBody: u(0.0021), midX: u(0.00028) }, hind: {} });
|
|
143
|
-
const hf = params.hindField || { tCore: 0.15, aCore: u(0.0035), aBody: u(0.0007), midX: u(0.00028) };
|
|
144
|
-
const seg = params.segField || { tCore: 0, aCore: u(0.003), aBody: u(0.0005), midX: u(0.00028) };
|
|
145
|
-
for (const S of ['L', 'R']) {
|
|
146
|
-
const side = S === 'L' ? 1 : -1;
|
|
147
|
-
if (params.splitHind !== true) {
|
|
148
|
-
L['H' + S] = { side, S, front: false, bones: ['femur' + S, 'tibia' + S, 'metatarsus' + S, 'hpaw' + S], proximal: ['femur' + S], distal: ['hpaw' + S], field: { a: 'hip' + S, b: 'knee' + S, top: 'femur' + S, ...hf } };
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
L['H' + S] = { side, S, front: false, bones: ['femur' + S], proximal: ['femur' + S], distal: [], field: { a: 'hip' + S, b: 'knee' + S, top: 'femur' + S, ...hf } };
|
|
152
|
-
L['H' + S + 's'] = { side, S, front: false, bones: ['tibia' + S], proximal: ['tibia' + S], distal: [], field: { a: 'knee' + S, b: 'hock' + S, top: 'tibia' + S, ...seg } };
|
|
153
|
-
L['H' + S + 'f'] = { side, S, front: false, bones: ['metatarsus' + S, 'hpaw' + S], proximal: ['metatarsus' + S], distal: ['hpaw' + S], field: { a: 'hock' + S, b: 'mtp' + S, top: 'metatarsus' + S, ...seg } };
|
|
154
|
-
}
|
|
155
|
-
return L;
|
|
156
|
-
}
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
// The frog, sculpted as a signed distance field around the sitting bind pose (rig.js).
|
|
2
|
-
// Every primitive is attached to a bone (skinning) and a group (axial / limb / eye / throat / jaw /
|
|
3
|
-
// tongue). Head primitives are placed in head-local coordinates (HEAD_O: midline, level with the eye
|
|
4
|
-
// centres), measured from the profile, front and dorsal reference photos.
|
|
5
|
-
//
|
|
6
|
-
// Anatomy: no neck; a broad flat head wider than long with a huge mouth line running back to below
|
|
7
|
-
// the tympanum; large bulging eyes on top of the head; a big round tympanum behind each eye (larger
|
|
8
|
-
// than the eye in males) under the supratympanic fold; a plump trunk rising from the vent to the
|
|
9
|
-
// sacral hump; short forelimbs with four slender fingers; very long hind limbs (heavy thigh,
|
|
10
|
-
// tibiofibula, elongated tarsus, long foot with five webbed toes). Common frog variant: dorsolateral
|
|
11
|
-
// folds along the back.
|
|
12
|
-
import { HEAD_O, hl, EYE_C } from './rig.js';
|
|
13
|
-
import { add, sub, mul, lerp, norm, cross, dot } from '../../core/math/vec.js';
|
|
14
|
-
import { sculptEyeSocket } from '../../core/sdf/eyeSocket.js';
|
|
15
|
-
import { SDFModel } from '../../core/sdf/sdf.js';
|
|
16
|
-
|
|
17
|
-
// Large bulging eye: globe radius 7.2 mm (visible eye ~14-15 mm at SVL 140 mm), looking out ~57 deg
|
|
18
|
-
// and up ~24 deg; a wide, nearly round aperture (no sclera), thick upper lid.
|
|
19
|
-
export const EYE = {
|
|
20
|
-
c: EYE_C, r: 0.0079, back: 0, yaw: 1.0, pitch: 0.42, lid: 0.0013,
|
|
21
|
-
R: 0.0081, d: 0.0009, off: 0.0006, tilt: (6 * Math.PI) / 180, irisZ: 0.0052, irisR: 0.0071,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const X = [1, 0, 0];
|
|
25
|
-
|
|
26
|
-
// A carved slot in the fold of a joint J between the segments toward A and toward B: a thin slab in
|
|
27
|
-
// the plane of the joint's hinge axis and the bisector of the two segments, from `start` (m from the
|
|
28
|
-
// joint) out to `len`.
|
|
29
|
-
function foldSlot(m, Jt, A, Bp, start, len, tag, bone, group) {
|
|
30
|
-
const a = norm(sub(A, Jt)), b = norm(sub(Bp, Jt));
|
|
31
|
-
const bis = norm(add(a, b)), axis = norm(cross(a, b));
|
|
32
|
-
m.fin({ tag, bone, group, o: add(Jt, mul(bis, start)), u: bis, v: axis, poly: [[0, -0.02], [len, -0.02], [len, 0.02], [0, 0.02]], t: 0.0026, round: 0.0012, k: 0.0006, carve: true });
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// point where the ray p + t dir (t in -2..2 cm) crosses the body surface sculpted so far
|
|
36
|
-
function surfaceAlong(m, p, dir) {
|
|
37
|
-
const prims = m.prims.filter((q) => q.part === 'body');
|
|
38
|
-
const f = (t) => SDFModel.evalList(prims, p[0] + dir[0] * t, p[1] + dir[1] * t, p[2] + dir[2] * t);
|
|
39
|
-
let lo = -0.02, hi = 0.02;
|
|
40
|
-
for (let i = 0; i < 40; i++) { const mid = 0.5 * (lo + hi); if (f(mid) < 0) lo = mid; else hi = mid; }
|
|
41
|
-
return add(p, mul(dir, 0.5 * (lo + hi)));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// tympanum (head-local, left): centre, outward normal, radius by sex
|
|
45
|
-
export function tympanum(params = {}) {
|
|
46
|
-
const male = params.sex === 'male';
|
|
47
|
-
const r = (params.tympanum || (male ? 0.0105 : 0.0074)) * (params.variant === 'common-frog' ? 0.78 : 1);
|
|
48
|
-
return { c: [0.0262, -0.0085, -0.0235], n: norm([1, 0.12, -0.25]), r };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function sculptFrog(m, rig, params = {}) {
|
|
52
|
-
const J = rig.J;
|
|
53
|
-
const male = params.sex === 'male';
|
|
54
|
-
const temporaria = params.variant === 'common-frog';
|
|
55
|
-
const plump = params.plump || 1;
|
|
56
|
-
|
|
57
|
-
// Ellipsoid whose local Y follows `ydir`; radii = [lateral, along ydir, third axis]
|
|
58
|
-
const ellY = (o) => {
|
|
59
|
-
const y = norm(o.ydir);
|
|
60
|
-
const lat = o.lateral || X;
|
|
61
|
-
const z = norm(cross(lat, y));
|
|
62
|
-
return m.ell({ ...o, axis: z, up: y, r: [o.r[0], o.r[1], o.r[2]] });
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// ---------------------------------------------------------------- TRUNK (vent low, sacral hump, plump belly)
|
|
66
|
-
const bodyAx = norm([0, 0.22, 1]);
|
|
67
|
-
m.ell({ tag: 'trunk', bone: 'spine2', c: ([0, 0.0375, -0.012]), r: [0.032 * plump, 0.0205, 0.037], axis: bodyAx, k: 0 });
|
|
68
|
-
m.ell({ tag: 'chest', bone: 'chest', c: [0, 0.041, 0.012], r: [0.026 * plump, 0.0185, 0.02], axis: bodyAx, k: 0.012 });
|
|
69
|
-
m.ell({ tag: 'shoulders', bone: 'chest', c: [0, 0.049, 0.015], r: [0.024, 0.012, 0.016], k: 0.012 });
|
|
70
|
-
m.ell({ tag: 'belly', bone: 'spine2', c: ([0, 0.027, -0.016]), r: [0.031 * plump, 0.0135, 0.03], axis: norm([0, 0.3, 1]), k: 0.014 });
|
|
71
|
-
m.ell({ tag: 'hump', bone: 'pelvis', c: ([0, 0.041, -0.033]), r: [0.022, 0.0165, 0.017], k: 0.012 });
|
|
72
|
-
m.ell({ tag: 'rump', bone: 'pelvis', c: ([0, 0.027, -0.046]), r: [0.0175, 0.0155, 0.0135], axis: norm([0, 0.5, 1]), k: 0.012 });
|
|
73
|
-
// the vent: a slight crease at the back of the rump
|
|
74
|
-
m.ell({ tag: 'vent', bone: 'pelvis', c: ([0, 0.016, -0.059]), r: [0.004, 0.0022, 0.004], k: 0.002, carve: true });
|
|
75
|
-
|
|
76
|
-
// ---------------------------------------------------------------- HEAD (head-local, see HEAD_O)
|
|
77
|
-
const H = { bone: 'head' };
|
|
78
|
-
const hw = params.headWidth || 1;
|
|
79
|
-
m.ell({ ...H, tag: 'cranium', c: hl([0, -0.01, -0.008]), r: [0.0268 * hw, 0.0105, 0.03], k: 0.012 });
|
|
80
|
-
m.ell({ ...H, tag: 'snout', c: hl([0, -0.0115, 0.013]), r: [0.019 * hw, 0.0088, 0.027], k: 0.01 });
|
|
81
|
-
// the canthus: a soft ridge from the eye to the nostril, the flat loreal region below it
|
|
82
|
-
for (const s of [1, -1]) {
|
|
83
|
-
m.cone({ ...H, tag: 'canthus', a: hl([0.0105 * s, -0.0028, 0.006]), b: hl([0.0052 * s, -0.0045, 0.0305]), ra: 0.0028, rb: 0.0018, k: 0.005 });
|
|
84
|
-
// cheeks and the corners of the jaw (the head is widest here)
|
|
85
|
-
m.ell({ ...H, tag: 'cheek', c: hl([0.0205 * s * hw, -0.0145, -0.017]), r: [0.0095, 0.0092, 0.0145], k: 0.009 });
|
|
86
|
-
m.ell({ ...H, tag: 'lipwall', c: hl([0.0165 * s * hw, -0.0142, 0.002]), r: [0.0075, 0.0048, 0.028], axis: norm([-0.32 * s, 0, 1]), k: 0.008 });
|
|
87
|
-
m.ell({ ...H, tag: 'temple', c: hl([0.02 * s * hw, -0.0065, -0.028]), r: [0.009, 0.008, 0.011], k: 0.008 });
|
|
88
|
-
// nostrils: small raised rims with the opening carved
|
|
89
|
-
m.sphere({ ...H, tag: 'naris', c: hl([0.0056 * s, -0.0048, 0.0318]), rad: 0.0019, k: 0.0025 });
|
|
90
|
-
m.sphere({ ...H, tag: 'nostril', c: hl([0.0058 * s, -0.0035, 0.0322]), rad: 0.0009, k: 0.0006, carve: true });
|
|
91
|
-
// tympanum: a flat disc set a little into the side of the head, with a low rim
|
|
92
|
-
const T = tympanum(params);
|
|
93
|
-
const tc = [T.c[0] * s, T.c[1], T.c[2]], tn = [T.n[0] * s, T.n[1], T.n[2]];
|
|
94
|
-
// (placed on the surface sculpted so far: a flat disc 0.35 mm below it at its centre)
|
|
95
|
-
const ts = surfaceAlong(m, hl(tc), tn);
|
|
96
|
-
m.ell({ ...H, tag: 'tympanum', c: add(ts, mul(tn, 0.0019 - 0.00035)), r: [T.r, T.r, 0.0019], axis: tn, k: 0.0012, carve: true });
|
|
97
|
-
// supratympanic fold: from behind the eye over the tympanum and down behind it to the shoulder
|
|
98
|
-
const f0 = hl([0.0142 * s, 0.0012, -0.0095]), f1 = hl([0.0228 * s, -0.001, -0.0245]);
|
|
99
|
-
const f2 = hl([0.0268 * s, -0.0075, -0.037]), f3 = [0.024 * s, 0.037, 0.018];
|
|
100
|
-
m.cone({ ...H, tag: 'stfold', a: f0, b: f1, ra: 0.0017, rb: 0.0021, k: 0.004 });
|
|
101
|
-
m.cone({ ...H, tag: 'stfold', a: f1, b: f2, ra: 0.0021, rb: 0.002, k: 0.004 });
|
|
102
|
-
m.cone({ tag: 'stfold', bone: 'chest', a: f2, b: f3, ra: 0.002, rb: 0.0015, k: 0.005 });
|
|
103
|
-
// eyes: bulging lids on their own bone (they retract into the head to blink)
|
|
104
|
-
const n0 = m.prims.length;
|
|
105
|
-
sculptEyeSocket(m, EYE, HEAD_O, s, { bone: 'eye' + (s > 0 ? 'L' : 'R'), orbit: { r: [0.0085, 0.006, 0.004], at: [0, -0.001, 0.007], k: 0.003 } });
|
|
106
|
-
for (const p of m.prims.slice(n0)) p.group = 'eye' + (s > 0 ? 'L' : 'R');
|
|
107
|
-
// the fleshy base of the eye bulge (a turret the globe sits in), on the eye bone
|
|
108
|
-
const ec = hl([EYE_C[0] * s, EYE_C[1], EYE_C[2]]);
|
|
109
|
-
m.ell({ tag: 'eyebase', bone: 'eye' + (s > 0 ? 'L' : 'R'), group: 'eye' + (s > 0 ? 'L' : 'R'), c: add(ec, [0.0005 * s, -0.004, -0.0005]), r: [0.0075, 0.005, 0.0082], k: 0.006 });
|
|
110
|
-
}
|
|
111
|
-
// the mouth: the upper jaw's underside is cut flat along the lip line (the lower jaw is its own part)
|
|
112
|
-
m.ell({ ...H, tag: 'palate', c: hl([0, -0.028, 0.005]), r: [0.05, 0.0115, 0.06], axis: norm([0, 0.04, 1]), k: 0.0008, carve: true });
|
|
113
|
-
|
|
114
|
-
// ---------------------------------------------------------------- LOWER JAW (rigid, meshed separately)
|
|
115
|
-
const JW = { bone: 'jaw', group: 'jaw', part: 'jaw' };
|
|
116
|
-
m.ell({ ...JW, tag: 'mandible', c: hl([0, -0.0185, 0.004]), r: [0.0232 * hw, 0.0066, 0.028], k: 0 });
|
|
117
|
-
m.ell({ ...JW, tag: 'chin', c: hl([0, -0.0188, 0.0255]), r: [0.0105, 0.0055, 0.0068], k: 0.006 });
|
|
118
|
-
for (const s of [1, -1]) m.ell({ ...JW, tag: 'jawcorner', c: hl([0.0195 * s * hw, -0.0188, -0.017]), r: [0.0062, 0.0062, 0.0105], k: 0.006 });
|
|
119
|
-
|
|
120
|
-
// ---------------------------------------------------------------- THROAT (buccal floor and vocal sac: the throat bone)
|
|
121
|
-
const TH = { bone: 'throat', group: 'throat' };
|
|
122
|
-
m.ell({ ...TH, tag: 'throat', c: [0, 0.0355, 0.036], r: [0.0205, 0.0082, 0.019], k: 0.012 });
|
|
123
|
-
m.ell({ ...TH, tag: 'gular', c: [0, 0.0335, 0.022], r: [0.0195, 0.0095, 0.012], k: 0.012 });
|
|
124
|
-
|
|
125
|
-
// ---------------------------------------------------------------- TONGUE (rigid, attached at the front of the jaw)
|
|
126
|
-
m.cone({ bone: 'tongue', group: 'tongue', part: 'tongue', tag: 'tongue', a: J.tongueBase, b: lerp(J.tongueBase, J.tongueTip, 0.82), ra: 0.0028, rb: 0.0048, k: 0 });
|
|
127
|
-
m.ell({ bone: 'tongue', group: 'tongue', part: 'tongue', tag: 'tonguetip', c: lerp(J.tongueBase, J.tongueTip, 0.88), r: [0.0068, 0.0032, 0.0055], k: 0.003 });
|
|
128
|
-
|
|
129
|
-
// ---------------------------------------------------------------- DORSOLATERAL FOLDS (common frog)
|
|
130
|
-
if (temporaria) {
|
|
131
|
-
for (const s of [1, -1]) {
|
|
132
|
-
const pts = [hl([0.0125 * s, 0.0005, -0.012]), [0.0165 * s, 0.059, 0.013], [0.0175 * s, 0.0565, -0.008], [0.0165 * s, 0.054, -0.026], [0.0135 * s, 0.047, -0.042]];
|
|
133
|
-
const bones = ['head', 'chest', 'spine3', 'spine2'];
|
|
134
|
-
for (let i = 0; i < 4; i++) m.cone({ tag: 'dlfold', bone: bones[i], a: pts[i], b: pts[i + 1], ra: 0.0016, rb: 0.0016, k: 0.004 });
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ---------------------------------------------------------------- LEGS
|
|
139
|
-
const arm = (male ? 1.18 : 1) * (params.armK || 1);
|
|
140
|
-
for (const S of ['L', 'R']) {
|
|
141
|
-
const s = S === 'L' ? 1 : -1;
|
|
142
|
-
const lat = [s, 0, 0];
|
|
143
|
-
const sx = (v) => [v[0] * s, v[1], v[2]];
|
|
144
|
-
// ---- front: short, upright, four slender fingers
|
|
145
|
-
const g = 'F' + S;
|
|
146
|
-
const Sh = J['shoulder' + S], E = J['elbow' + S], W = J['wrist' + S], M = J['mcp' + S], T = J['ftoe' + S];
|
|
147
|
-
ellY({ tag: 'armpit', bone: 'humerus' + S, group: g, c: add(lerp(Sh, E, 0.3), sx([-0.003, 0.002, 0.002])), ydir: sub(E, Sh), lateral: lat, r: [0.0075, 0.012, 0.0075], k: 0.01 });
|
|
148
|
-
m.cone({ tag: 'upperarm', bone: 'humerus' + S, group: g, a: Sh, b: E, ra: 0.0062 * arm, rb: 0.0048 * arm, k: 0.008 });
|
|
149
|
-
m.cone({ tag: 'forearm', bone: 'radius' + S, group: g, a: E, b: W, ra: 0.0048 * arm, rb: 0.0031, k: 0.003 });
|
|
150
|
-
ellY({ tag: 'forearmmuscle', bone: 'radius' + S, group: g, c: lerp(E, W, 0.3), ydir: sub(W, E), lateral: lat, r: [0.0046 * arm, 0.0085, 0.0048 * arm], k: 0.003 });
|
|
151
|
-
const dp = norm(sub(M, W)), up = [0, 1, 0];
|
|
152
|
-
ellY({ tag: 'palm', bone: 'metacarpus' + S, group: g, c: lerp(W, M, 0.55), ydir: dp, lateral: norm(cross(dp, up)), r: [0.0045, 0.0068, 0.0022], k: 0.003 });
|
|
153
|
-
// fingers fan out from the palm: III longest, pointing forward and in; I (thumb) inside
|
|
154
|
-
const fdir = norm(sub(T, M));
|
|
155
|
-
// [angle from straight ahead (rad, + outward), length]
|
|
156
|
-
const FING = [[-0.95, 0.0105, 1], [-0.62, 0.0135, 1], [-0.3, 0.0184, 1], [0.08, 0.0128, 1]];
|
|
157
|
-
for (let i = 0; i < 4; i++) {
|
|
158
|
-
const [a, L] = FING[i];
|
|
159
|
-
const d = norm([s * Math.sin(a), fdir[1], Math.cos(a)]);
|
|
160
|
-
const base = add(M, mul(d, -0.001));
|
|
161
|
-
const tip = add(base, mul(d, L));
|
|
162
|
-
tip[1] = 0.0014;
|
|
163
|
-
m.cone({ tag: 'finger', bone: 'fpaw' + S, group: g, a: base, b: tip, ra: 0.0017, rb: 0.0011, k: 0.0015 });
|
|
164
|
-
m.sphere({ tag: 'fingertip', bone: 'fpaw' + S, group: g, c: tip, rad: 0.00135, k: 0.001 });
|
|
165
|
-
// male: dark nuptial pad on the thumb
|
|
166
|
-
if (i === 0 && male) m.ell({ tag: 'nuptial', bone: 'fpaw' + S, group: g, c: lerp(base, tip, 0.3), r: [0.0022, 0.0022, 0.003], axis: d, k: 0.002 });
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// ---- hind: heavy thigh, tibiofibula, long tarsus, long webbed foot
|
|
170
|
-
const h = 'H' + S;
|
|
171
|
-
const hs = params.splitHind !== true ? h : h + 's', hf = params.splitHind !== true ? h : h + 'f';
|
|
172
|
-
const Hp = J['hip' + S], K = J['knee' + S], Hk = J['hock' + S], Mt = J['mtp' + S], Tt = J['htoe' + S];
|
|
173
|
-
// web between thigh and body (spans limb and body)
|
|
174
|
-
ellY({ tag: 'groin', bone: 'femur' + S, group: h, c: add(lerp(Hp, K, 0.22), sx([-0.002, 0.004, 0])), ydir: sub(K, Hp), lateral: lat, r: [0.0095, 0.016, 0.0095], k: 0.012, bias: 0.001 });
|
|
175
|
-
// thigh: a thick muscle mass (the widest part of the hind limb), tapering to the knee
|
|
176
|
-
m.cone({ tag: 'thigh', bone: 'femur' + S, group: h, a: Hp, b: K, ra: 0.0105, rb: 0.0058, k: 0.004 });
|
|
177
|
-
ellY({ tag: 'thighmuscle', bone: 'femur' + S, group: h, c: add(lerp(Hp, K, 0.42), sx([0.0015, 0.0022, 0.0])), ydir: sub(K, Hp), lateral: lat, r: [0.0128, 0.026, 0.0118], k: 0.0025 });
|
|
178
|
-
// shank: the calf bulges near the knee, slim toward the ankle (small blend with the thigh so the
|
|
179
|
-
// two stay separate when the leg extends)
|
|
180
|
-
m.sphere({ tag: 'kneecap', bone: 'tibia' + S, group: hs, c: K, rad: 0.0046, k: 0.005 });
|
|
181
|
-
m.cone({ tag: 'shank', bone: 'tibia' + S, group: hs, a: K, b: Hk, ra: 0.0056, rb: 0.0036, k: 0.006 });
|
|
182
|
-
ellY({ tag: 'calf', bone: 'tibia' + S, group: hs, c: add(lerp(K, Hk, 0.36), sx([0.0012, 0.0006, 0])), ydir: sub(Hk, K), lateral: lat, r: [0.0066, 0.0185, 0.0064], k: 0.006 });
|
|
183
|
-
// the folds between thigh and shank and between shank and tarsus: in the Z-folded sit the segments
|
|
184
|
-
// lie pressed together; a narrow slot down to near each joint keeps their skins apart (each wall
|
|
185
|
-
// rides its own bone), so the legs straighten in a leap without stretching a web of skin across
|
|
186
|
-
// the fold
|
|
187
|
-
if (params.foldSlots !== false) foldSlot(m, K, Hp, Hk, 0.0045, 0.038, 'kneefold', 'tibia' + S, h);
|
|
188
|
-
if (params.foldSlots !== false) foldSlot(m, Hk, K, Mt, 0.0035, 0.024, 'anklefold', 'metatarsus' + S, h);
|
|
189
|
-
// tarsus (the frog's extra long segment) and the heel
|
|
190
|
-
m.sphere({ tag: 'heel', bone: 'metatarsus' + S, group: hf, c: Hk, rad: 0.0038, k: 0.004 });
|
|
191
|
-
m.cone({ tag: 'tarsus', bone: 'metatarsus' + S, group: hf, a: Hk, b: Mt, ra: 0.0036, rb: 0.0031, k: 0.004 });
|
|
192
|
-
// foot: five long toes fanning out, IV longest; webbing to near the tips (not IV's last phalanges)
|
|
193
|
-
const fd = norm(sub(Tt, Mt));
|
|
194
|
-
const fl = norm(cross(fd, [0, 1, 0])); // toward the midline for the left foot? (fd x up)
|
|
195
|
-
const inward = mul(fl, dot(fl, [s, 0, 0]) > 0 ? -1 : 1); // unit vector toward the midline
|
|
196
|
-
// [angle from straight ahead (rad, + outward), length from the tarsus (m)]: I-V, IV longest
|
|
197
|
-
const TOES = [[-0.08, 0.021], [0.1, 0.031], [0.28, 0.043], [0.52, 0.07], [0.74, 0.042]];
|
|
198
|
-
const rot = (a) => { // rotate fd about y, + turns outward
|
|
199
|
-
const c = Math.cos(a), sn = Math.sin(a);
|
|
200
|
-
return norm(add(mul(fd, c), mul(inward, -sn)));
|
|
201
|
-
};
|
|
202
|
-
const base0 = add(Mt, mul(fd, 0.004));
|
|
203
|
-
const tips = [];
|
|
204
|
-
m.ell({ tag: 'sole', bone: 'hpaw' + S, group: hf, c: add(Mt, mul(fd, 0.009)), r: [0.0052, 0.0028, 0.0105], axis: fd, k: 0.003 });
|
|
205
|
-
for (let i = 0; i < 5; i++) {
|
|
206
|
-
const [a, lk] = TOES[i];
|
|
207
|
-
const d = rot(a);
|
|
208
|
-
const b = add(base0, mul(d, 0.004));
|
|
209
|
-
const tip = add(b, mul(d, lk - 0.008));
|
|
210
|
-
tip[1] = 0.0017;
|
|
211
|
-
tips.push({ b, tip, d });
|
|
212
|
-
m.cone({ tag: 'toe', bone: 'hpaw' + S, group: hf, a: add(Mt, mul(d, 0.002)), b: tip, ra: 0.0024, rb: 0.0013, k: 0.002 });
|
|
213
|
-
m.sphere({ tag: 'toetip', bone: 'hpaw' + S, group: hf, c: tip, rad: 0.0015, k: 0.0008 });
|
|
214
|
-
}
|
|
215
|
-
// web: a thin membrane in the plane of the foot, its free margin notched between the toes
|
|
216
|
-
{
|
|
217
|
-
const o = [Mt[0], Mt[1] - 0.0024, Mt[2]];
|
|
218
|
-
const un = norm(sub([Tt[0], 0.0019, Tt[2]], o));
|
|
219
|
-
const v = norm(cross([0, 1, 0], un)); // lateral in-plane axis (points to the animal's left for fd forward)
|
|
220
|
-
const to2 = (p) => { const q = sub(p, o); return [dot(q, un), dot(q, v)]; };
|
|
221
|
-
const poly = [to2(add(Mt, mul(fd, -0.002)))];
|
|
222
|
-
const webTo = [0.92, 0.9, 0.86, 0.7, 0.92];
|
|
223
|
-
const P2 = tips.map((t, i) => to2(lerp(t.b, t.tip, webTo[i])));
|
|
224
|
-
// order the toes by their in-plane angle so the outline does not cross itself
|
|
225
|
-
const order = [0, 1, 2, 3, 4].sort((a, b) => Math.atan2(P2[a][1], P2[a][0]) - Math.atan2(P2[b][1], P2[b][0]));
|
|
226
|
-
for (let k = 0; k < order.length; k++) {
|
|
227
|
-
const i = order[k];
|
|
228
|
-
poly.push(P2[i]);
|
|
229
|
-
if (k < order.length - 1) {
|
|
230
|
-
// concave margin between two toes: back toward the base
|
|
231
|
-
const j = order[k + 1];
|
|
232
|
-
const mid = [(P2[i][0] + P2[j][0]) * 0.5, (P2[i][1] + P2[j][1]) * 0.5];
|
|
233
|
-
poly.push([mid[0] * 0.8, mid[1] * 0.8]);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
m.fin({ tag: 'web', bone: 'hpaw' + S, group: hf, o, u: un, v, poly, t: 0.0014, k: 0.0018, thin: true });
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return m;
|
|
240
|
-
}
|