@franzenzenhofer/asanakit 0.1.0 → 0.2.0
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/README.md +78 -46
- package/dist/anatomy/muscles.d.ts +10 -7
- package/dist/anatomy/muscles.d.ts.map +1 -1
- package/dist/anatomy/muscles.js +21 -17
- package/dist/anatomy/muscles.js.map +1 -1
- package/dist/anatomy/validate.d.ts.map +1 -1
- package/dist/anatomy/validate.js +16 -10
- package/dist/anatomy/validate.js.map +1 -1
- package/dist/cli/commands/export.d.ts.map +1 -1
- package/dist/cli/commands/export.js +24 -2
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +3 -1
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/render.d.ts.map +1 -1
- package/dist/cli/commands/render.js +12 -3
- package/dist/cli/commands/render.js.map +1 -1
- package/dist/cli/commands/view.d.ts +3 -0
- package/dist/cli/commands/view.d.ts.map +1 -0
- package/dist/cli/commands/view.js +40 -0
- package/dist/cli/commands/view.js.map +1 -0
- package/dist/cli/index.js +7 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/resolve.d.ts +6 -0
- package/dist/cli/resolve.d.ts.map +1 -1
- package/dist/cli/resolve.js +40 -0
- package/dist/cli/resolve.js.map +1 -1
- package/dist/core/camera.d.ts +56 -0
- package/dist/core/camera.d.ts.map +1 -0
- package/dist/core/camera.js +20 -0
- package/dist/core/camera.js.map +1 -0
- package/dist/core/joints.d.ts +18 -0
- package/dist/core/joints.d.ts.map +1 -0
- package/dist/core/joints.js +27 -0
- package/dist/core/joints.js.map +1 -0
- package/dist/core/quat.d.ts +18 -0
- package/dist/core/quat.d.ts.map +1 -0
- package/dist/core/quat.js +25 -0
- package/dist/core/quat.js.map +1 -0
- package/dist/core/rig.d.ts +1 -6
- package/dist/core/rig.d.ts.map +1 -1
- package/dist/core/rig.js +45 -74
- package/dist/core/rig.js.map +1 -1
- package/dist/core/skeleton.d.ts +4 -13
- package/dist/core/skeleton.d.ts.map +1 -1
- package/dist/core/skeleton.js +39 -69
- package/dist/core/skeleton.js.map +1 -1
- package/dist/core/types.d.ts +62 -55
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/vec3.d.ts +13 -0
- package/dist/core/vec3.d.ts.map +1 -0
- package/dist/core/vec3.js +26 -0
- package/dist/core/vec3.js.map +1 -0
- package/dist/export3d/gltf.d.ts +11 -0
- package/dist/export3d/gltf.d.ts.map +1 -0
- package/dist/export3d/gltf.js +28 -0
- package/dist/export3d/gltf.js.map +1 -0
- package/dist/export3d/index.d.ts +3 -0
- package/dist/export3d/index.d.ts.map +1 -0
- package/dist/export3d/index.js +3 -0
- package/dist/export3d/index.js.map +1 -0
- package/dist/export3d/shims.d.ts +7 -0
- package/dist/export3d/shims.d.ts.map +1 -0
- package/dist/export3d/shims.js +27 -0
- package/dist/export3d/shims.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/library/index.js +4 -4
- package/dist/library/index.js.map +1 -1
- package/dist/model/pose.d.ts +11 -5
- package/dist/model/pose.d.ts.map +1 -1
- package/dist/model/pose.js +30 -16
- package/dist/model/pose.js.map +1 -1
- package/dist/model/schema.d.ts +69 -28
- package/dist/model/schema.d.ts.map +1 -1
- package/dist/model/schema.js +57 -17
- package/dist/model/schema.js.map +1 -1
- package/dist/physics/index.d.ts +3 -0
- package/dist/physics/index.d.ts.map +1 -0
- package/dist/physics/index.js +3 -0
- package/dist/physics/index.js.map +1 -0
- package/dist/physics/rapier-types.d.ts +60 -0
- package/dist/physics/rapier-types.d.ts.map +1 -0
- package/dist/physics/rapier-types.js +12 -0
- package/dist/physics/rapier-types.js.map +1 -0
- package/dist/physics/settle.d.ts +3 -0
- package/dist/physics/settle.d.ts.map +1 -0
- package/dist/physics/settle.js +108 -0
- package/dist/physics/settle.js.map +1 -0
- package/dist/physics/world.d.ts +4 -0
- package/dist/physics/world.d.ts.map +1 -0
- package/dist/physics/world.js +18 -0
- package/dist/physics/world.js.map +1 -0
- package/dist/render/anatomy.js +1 -1
- package/dist/render/anatomy.js.map +1 -1
- package/dist/render/annotations.d.ts +3 -2
- package/dist/render/annotations.d.ts.map +1 -1
- package/dist/render/annotations.js.map +1 -1
- package/dist/render/camera.d.ts +43 -0
- package/dist/render/camera.d.ts.map +1 -0
- package/dist/render/camera.js +57 -0
- package/dist/render/camera.js.map +1 -0
- package/dist/render/context.d.ts +5 -3
- package/dist/render/context.d.ts.map +1 -1
- package/dist/render/figure.d.ts +4 -2
- package/dist/render/figure.d.ts.map +1 -1
- package/dist/render/figure.js +29 -43
- package/dist/render/figure.js.map +1 -1
- package/dist/render/index.d.ts +1 -0
- package/dist/render/index.d.ts.map +1 -1
- package/dist/render/index.js +1 -0
- package/dist/render/index.js.map +1 -1
- package/dist/render/props.d.ts +4 -3
- package/dist/render/props.d.ts.map +1 -1
- package/dist/render/props.js.map +1 -1
- package/dist/render/scene.d.ts +7 -1
- package/dist/render/scene.d.ts.map +1 -1
- package/dist/render/scene.js +8 -1
- package/dist/render/scene.js.map +1 -1
- package/dist/render/sheet.d.ts +3 -0
- package/dist/render/sheet.d.ts.map +1 -1
- package/dist/render/sheet.js +2 -0
- package/dist/render/sheet.js.map +1 -1
- package/dist/solve.d.ts +14 -0
- package/dist/solve.d.ts.map +1 -0
- package/dist/solve.js +17 -0
- package/dist/solve.js.map +1 -0
- package/dist/standards/keypoints.d.ts +2 -10
- package/dist/standards/keypoints.d.ts.map +1 -1
- package/dist/standards/keypoints.js +33 -14
- package/dist/standards/keypoints.js.map +1 -1
- package/dist/three/index.d.ts +2 -0
- package/dist/three/index.d.ts.map +1 -0
- package/dist/three/index.js +2 -0
- package/dist/three/index.js.map +1 -0
- package/dist/three/scene.d.ts +22 -0
- package/dist/three/scene.d.ts.map +1 -0
- package/dist/three/scene.js +90 -0
- package/dist/three/scene.js.map +1 -0
- package/dist/viewer/html.d.ts +16 -0
- package/dist/viewer/html.d.ts.map +1 -0
- package/dist/viewer/html.js +59 -0
- package/dist/viewer/html.js.map +1 -0
- package/dist/viewer/index.d.ts +2 -0
- package/dist/viewer/index.d.ts.map +1 -0
- package/dist/viewer/index.js +2 -0
- package/dist/viewer/index.js.map +1 -0
- package/dist/viewer/viewer.bundle.js +4119 -0
- package/docs/AUTHORING.md +119 -58
- package/package.json +20 -5
- package/poses/surf/bottom-turn.pose.yaml +24 -24
- package/poses/surf/cutback.pose.yaml +24 -24
- package/poses/surf/duck-dive.pose.yaml +23 -23
- package/poses/surf/noseride.pose.yaml +23 -25
- package/poses/surf/paddling.pose.yaml +24 -24
- package/poses/surf/pop-up.pose.yaml +24 -24
- package/poses/surf/takeoff.pose.yaml +24 -24
- package/poses/surf/tube-stance.pose.yaml +24 -24
- package/poses/yoga/ashtanga/adho-mukha-svanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/ardha-uttanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/baddha-konasana.pose.yaml +21 -23
- package/poses/yoga/ashtanga/balasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/chaturanga-dandasana.pose.yaml +21 -21
- package/poses/yoga/ashtanga/dandasana.pose.yaml +21 -23
- package/poses/yoga/ashtanga/halasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/janu-sirsasana-a.pose.yaml +22 -22
- package/poses/yoga/ashtanga/karnapidasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/marichyasana-a.pose.yaml +22 -22
- package/poses/yoga/ashtanga/marichyasana-c.pose.yaml +21 -23
- package/poses/yoga/ashtanga/matsyasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/navasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/padahastasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/padangusthasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/padmasana.pose.yaml +22 -24
- package/poses/yoga/ashtanga/parsvottanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/paschimottanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/prasarita-padottanasana-a.pose.yaml +26 -26
- package/poses/yoga/ashtanga/prasarita-padottanasana-c.pose.yaml +26 -26
- package/poses/yoga/ashtanga/primary.seq.yaml +2 -4
- package/poses/yoga/ashtanga/purvottanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/salamba-sarvangasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/samasthiti.pose.yaml +10 -10
- package/poses/yoga/ashtanga/savasana.pose.yaml +21 -21
- package/poses/yoga/ashtanga/setu-bandhasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/sirsasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/supta-padangusthasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/upavistha-konasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/urdhva-dhanurasana.pose.yaml +23 -23
- package/poses/yoga/ashtanga/urdhva-hastasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/urdhva-mukha-svanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/utkatasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/uttanasana.pose.yaml +22 -22
- package/poses/yoga/ashtanga/utthita-parsvakonasana.pose.yaml +24 -24
- package/poses/yoga/ashtanga/utthita-trikonasana.pose.yaml +24 -24
- package/poses/yoga/ashtanga/virabhadrasana-a.pose.yaml +22 -22
- package/poses/yoga/ashtanga/virabhadrasana-b.pose.yaml +21 -23
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Export a solved skeleton as keypoints in the two standard layouts, so asanakit
|
|
3
|
+
* output can feed anything that already speaks pose-estimation data.
|
|
4
|
+
*
|
|
5
|
+
* The landmark NAMES and EDGE lists below restate the public layouts of
|
|
6
|
+
* MediaPipe BlazePose (33) and COCO (17), as published in the Apache-2.0
|
|
7
|
+
* licensed tfjs-models / mediapipe projects. Only the layout is reused; the
|
|
8
|
+
* geometry is asanakit's own - and since the rig is 3D, every keypoint carries
|
|
9
|
+
* a real z (MediaPipe convention: hip-relative, negative toward the camera).
|
|
10
|
+
*/
|
|
11
|
+
import { axisAngleDeg, rotateVec3 } from '../core/quat.js';
|
|
12
|
+
import { add3, lerp3, normalize3, scale3, sub3 } from '../core/vec3.js';
|
|
2
13
|
export const MEDIAPIPE_33 = [
|
|
3
14
|
'nose', 'left_eye_inner', 'left_eye', 'left_eye_outer', 'right_eye_inner', 'right_eye', 'right_eye_outer',
|
|
4
15
|
'left_ear', 'right_ear', 'mouth_left', 'mouth_right',
|
|
@@ -24,19 +35,21 @@ const MEDIAPIPE_EDGES = [
|
|
|
24
35
|
[24, 26], [26, 28], [28, 30], [28, 32],
|
|
25
36
|
];
|
|
26
37
|
/**
|
|
27
|
-
* The rig has no facial bones, so eyes, ears and mouth are derived from the
|
|
28
|
-
* bone's
|
|
29
|
-
* for a consumer that only needs head orientation.
|
|
38
|
+
* The rig has no facial bones, so eyes, ears and mouth are derived from the
|
|
39
|
+
* head bone's frame. They are approximations by construction - honest ones,
|
|
40
|
+
* and enough for a consumer that only needs head orientation.
|
|
30
41
|
*/
|
|
31
42
|
const facePoints = (skeleton) => {
|
|
32
43
|
const head = skeleton.bones.head;
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
44
|
+
const q = head.orientation;
|
|
45
|
+
const up = rotateVec3(q, [0, 1, 0]);
|
|
46
|
+
const forward = rotateVec3(q, [0, 0, 1]);
|
|
47
|
+
const left = rotateVec3(q, [1, 0, 0]);
|
|
48
|
+
const centre = lerp3(head.start, head.end, 0.55);
|
|
49
|
+
const size = head.length;
|
|
50
|
+
const at = (fwd, rise, side) => add3(add3(add3(centre, scale3(forward, fwd * size)), scale3(up, rise * size)), scale3(left, side * size));
|
|
38
51
|
return {
|
|
39
|
-
nose:
|
|
52
|
+
nose: at(0.42, 0, 0),
|
|
40
53
|
left_eye: at(0.3, 0.12, 0.08),
|
|
41
54
|
left_eye_inner: at(0.32, 0.12, 0.03),
|
|
42
55
|
left_eye_outer: at(0.26, 0.12, 0.14),
|
|
@@ -47,16 +60,19 @@ const facePoints = (skeleton) => {
|
|
|
47
60
|
right_ear: at(-0.1, 0.06, -0.22),
|
|
48
61
|
mouth_left: at(0.3, -0.18, 0.09),
|
|
49
62
|
mouth_right: at(0.3, -0.18, -0.09),
|
|
50
|
-
_forward: forward,
|
|
51
63
|
};
|
|
52
64
|
};
|
|
53
65
|
const heel = (skeleton, side) => {
|
|
54
66
|
const foot = skeleton.bones[side === 'L' ? 'footL' : 'footR'];
|
|
55
|
-
|
|
67
|
+
const dir = normalize3(sub3(foot.end, foot.start));
|
|
68
|
+
return add3(foot.start, scale3(dir, -foot.length * 0.35));
|
|
56
69
|
};
|
|
70
|
+
/** Pinky and thumb fan out from the wrist around the hand's own forward axis. */
|
|
57
71
|
const hand = (skeleton, side, spread) => {
|
|
58
72
|
const h = skeleton.bones[side === 'L' ? 'handL' : 'handR'];
|
|
59
|
-
|
|
73
|
+
const dir = normalize3(sub3(h.end, h.start));
|
|
74
|
+
const axis = rotateVec3(h.orientation, [0, 0, 1]);
|
|
75
|
+
return add3(h.end, scale3(rotateVec3(axisAngleDeg(axis, spread), dir), h.length * 0.3));
|
|
60
76
|
};
|
|
61
77
|
const pointFor = (name, skeleton, face) => {
|
|
62
78
|
const l = skeleton.landmarks;
|
|
@@ -99,6 +115,7 @@ export const toKeypoints = (skeleton, format, options = {}) => {
|
|
|
99
115
|
const minX = Math.min(...xs);
|
|
100
116
|
const minY = Math.min(...ys);
|
|
101
117
|
const span = Math.max(Math.max(...xs) - minX, Math.max(...ys) - minY, 1e-6);
|
|
118
|
+
const hipZ = skeleton.landmarks.hipCenter[2];
|
|
102
119
|
return {
|
|
103
120
|
format,
|
|
104
121
|
space: normalize ? 'normalized' : 'stature',
|
|
@@ -108,9 +125,11 @@ export const toKeypoints = (skeleton, format, options = {}) => {
|
|
|
108
125
|
return {
|
|
109
126
|
index,
|
|
110
127
|
name,
|
|
111
|
-
// Image space is y-down, so normalising also flips
|
|
128
|
+
// Image space is y-down, so normalising also flips that axis; z stays
|
|
129
|
+
// hip-relative and negative toward the camera, as MediaPipe reports it.
|
|
112
130
|
x: normalize ? (p[0] - minX) / span : p[0],
|
|
113
131
|
y: normalize ? 1 - (p[1] - minY) / span : p[1],
|
|
132
|
+
z: normalize ? -(p[2] - hipZ) / span : p[2],
|
|
114
133
|
};
|
|
115
134
|
}),
|
|
116
135
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keypoints.js","sourceRoot":"","sources":["../../src/standards/keypoints.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"keypoints.js","sourceRoot":"","sources":["../../src/standards/keypoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/three/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/three/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skeleton -> three.js scene graph. One shared module builds the figure for
|
|
3
|
+
* BOTH consumers: the GLB exporter running in Node and the interactive viewer
|
|
4
|
+
* running in a browser. three's scene-graph math is pure JavaScript, so no
|
|
5
|
+
* GPU or DOM is needed here.
|
|
6
|
+
*/
|
|
7
|
+
import { Group } from 'three';
|
|
8
|
+
import { type MuscleId } from '../anatomy/muscles.js';
|
|
9
|
+
import type { Skeleton } from '../core/types.js';
|
|
10
|
+
export interface FigureSceneOptions {
|
|
11
|
+
/** Bone capsule color; a light theme's ink. */
|
|
12
|
+
readonly color?: string;
|
|
13
|
+
readonly engaged?: readonly MuscleId[];
|
|
14
|
+
readonly stretched?: readonly MuscleId[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build the stick figure as a group of capsules and spheres, y-up, feet on
|
|
18
|
+
* y = 0, about one unit tall - exactly the solver's world space, so the GLB
|
|
19
|
+
* and the viewer agree with every SVG projection of the same skeleton.
|
|
20
|
+
*/
|
|
21
|
+
export declare const buildFigureScene: (skeleton: Skeleton, options?: FigureSceneOptions) => Group;
|
|
22
|
+
//# sourceMappingURL=scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../../src/three/scene.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAEL,KAAK,EAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAU,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGzD,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC1C;AA4ED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,UAAU,QAAQ,EAAE,UAAS,kBAAuB,KAAG,KA8BvF,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skeleton -> three.js scene graph. One shared module builds the figure for
|
|
3
|
+
* BOTH consumers: the GLB exporter running in Node and the interactive viewer
|
|
4
|
+
* running in a browser. three's scene-graph math is pure JavaScript, so no
|
|
5
|
+
* GPU or DOM is needed here.
|
|
6
|
+
*/
|
|
7
|
+
import { CapsuleGeometry, Group, Mesh, MeshStandardMaterial, Quaternion, SphereGeometry, Vector3, } from 'three';
|
|
8
|
+
import { MUSCLES } from '../anatomy/muscles.js';
|
|
9
|
+
import { midpoint3, sub3, len3 } from '../core/vec3.js';
|
|
10
|
+
const BONE_RADIUS = 0.016;
|
|
11
|
+
const HEAD_RADIUS = 0.055;
|
|
12
|
+
const JOINT_RADIUS = 0.02;
|
|
13
|
+
/** Fixed tessellation, so the same skeleton always exports identical bytes. */
|
|
14
|
+
const CAPSULE_SEGMENTS = { cap: 6, radial: 12 };
|
|
15
|
+
const SPHERE_SEGMENTS = { width: 24, height: 16 };
|
|
16
|
+
const DEFAULT_COLOR = '#1a1a1a';
|
|
17
|
+
const ENGAGED_COLOR = '#c0392b';
|
|
18
|
+
const STRETCHED_COLOR = '#2471a3';
|
|
19
|
+
const REST_AXIS = new Vector3(0, 1, 0);
|
|
20
|
+
/** Which rig bones a highlighted muscle paints. */
|
|
21
|
+
const muscleBones = (ids) => {
|
|
22
|
+
const bones = new Set();
|
|
23
|
+
for (const id of ids) {
|
|
24
|
+
const base = MUSCLES[id].bone;
|
|
25
|
+
if (base === 'pelvis' || base === 'spine' || base === 'neck' || base === 'head') {
|
|
26
|
+
bones.add(base);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
bones.add(`${base}L`);
|
|
30
|
+
bones.add(`${base}R`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return bones;
|
|
34
|
+
};
|
|
35
|
+
const material = (color) => new MeshStandardMaterial({ color, roughness: 0.65, metalness: 0 });
|
|
36
|
+
const alignToAxis = (mesh, axis) => {
|
|
37
|
+
mesh.quaternion.copy(new Quaternion().setFromUnitVectors(REST_AXIS, new Vector3(axis[0], axis[1], axis[2]).normalize()));
|
|
38
|
+
};
|
|
39
|
+
const boneMesh = (start, end, spec) => {
|
|
40
|
+
const axis = sub3(end, start);
|
|
41
|
+
const length = len3(axis);
|
|
42
|
+
const geometry = new CapsuleGeometry(spec.radius, Math.max(length, 1e-6), CAPSULE_SEGMENTS.cap, CAPSULE_SEGMENTS.radial);
|
|
43
|
+
const mesh = new Mesh(geometry, spec.mat);
|
|
44
|
+
mesh.name = spec.name;
|
|
45
|
+
const mid = midpoint3(start, end);
|
|
46
|
+
mesh.position.set(mid[0], mid[1], mid[2]);
|
|
47
|
+
alignToAxis(mesh, axis);
|
|
48
|
+
return mesh;
|
|
49
|
+
};
|
|
50
|
+
const headMesh = (skeleton, mat) => {
|
|
51
|
+
const head = new Mesh(new SphereGeometry(HEAD_RADIUS * skeleton.scale, SPHERE_SEGMENTS.width, SPHERE_SEGMENTS.height), mat);
|
|
52
|
+
head.name = 'bone:head';
|
|
53
|
+
const centre = skeleton.landmarks.headCenter;
|
|
54
|
+
head.position.set(centre[0], centre[1], centre[2]);
|
|
55
|
+
alignToAxis(head, sub3(skeleton.bones.head.end, skeleton.bones.head.start));
|
|
56
|
+
head.scale.set(0.82, 1.18, 0.9); // An ellipsoid skull, not a ball.
|
|
57
|
+
return head;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Build the stick figure as a group of capsules and spheres, y-up, feet on
|
|
61
|
+
* y = 0, about one unit tall - exactly the solver's world space, so the GLB
|
|
62
|
+
* and the viewer agree with every SVG projection of the same skeleton.
|
|
63
|
+
*/
|
|
64
|
+
export const buildFigureScene = (skeleton, options = {}) => {
|
|
65
|
+
const group = new Group();
|
|
66
|
+
group.name = 'asanakit-figure';
|
|
67
|
+
const base = material(options.color ?? DEFAULT_COLOR);
|
|
68
|
+
const engagedMat = material(ENGAGED_COLOR);
|
|
69
|
+
const stretchedMat = material(STRETCHED_COLOR);
|
|
70
|
+
const engaged = muscleBones(options.engaged ?? []);
|
|
71
|
+
const stretched = muscleBones(options.stretched ?? []);
|
|
72
|
+
const scale = skeleton.scale;
|
|
73
|
+
const materialFor = (id) => engaged.has(id) ? engagedMat : stretched.has(id) ? stretchedMat : base;
|
|
74
|
+
for (const bone of Object.values(skeleton.bones)) {
|
|
75
|
+
if (bone.id === 'head')
|
|
76
|
+
continue; // The head is a sphere, not a stick.
|
|
77
|
+
group.add(boneMesh(bone.start, bone.end, { radius: BONE_RADIUS * scale, mat: materialFor(bone.id), name: `bone:${bone.id}` }));
|
|
78
|
+
}
|
|
79
|
+
group.add(headMesh(skeleton, materialFor('head')));
|
|
80
|
+
for (const [id, p] of Object.entries(skeleton.landmarks)) {
|
|
81
|
+
if (id === 'headCenter' || id === 'headTop')
|
|
82
|
+
continue;
|
|
83
|
+
const joint = new Mesh(new SphereGeometry(JOINT_RADIUS * scale, 12, 8), base);
|
|
84
|
+
joint.name = `joint:${id}`;
|
|
85
|
+
joint.position.set(p[0], p[1], p[2]);
|
|
86
|
+
group.add(joint);
|
|
87
|
+
}
|
|
88
|
+
return group;
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=scene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.js","sourceRoot":"","sources":["../../src/three/scene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CameraAngles } from '../core/camera.js';
|
|
2
|
+
import type { Skeleton } from '../core/types.js';
|
|
3
|
+
import type { MuscleId } from '../anatomy/muscles.js';
|
|
4
|
+
export interface ViewerOptions {
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly subtitle?: string | undefined;
|
|
7
|
+
readonly camera: CameraAngles;
|
|
8
|
+
readonly engaged?: readonly MuscleId[];
|
|
9
|
+
readonly stretched?: readonly MuscleId[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A single self-contained offline HTML file: the solved skeleton as JSON plus
|
|
13
|
+
* the prebuilt three.js viewer bundle. No CDN, no network, works from file://.
|
|
14
|
+
*/
|
|
15
|
+
export declare const buildViewerHtml: (skeleton: Skeleton, options: ViewerOptions) => Promise<string>;
|
|
16
|
+
//# sourceMappingURL=html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC1C;AAuBD;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,UAAU,QAAQ,EAAE,SAAS,aAAa,KAAG,OAAO,CAAC,MAAM,CAqChG,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Both the compiled module (dist/viewer/html.js) and the tsx-run source
|
|
4
|
+
* (src/viewer/html.ts) sit two levels below the package root, so one relative
|
|
5
|
+
* path finds the bundle from either world.
|
|
6
|
+
*/
|
|
7
|
+
const BUNDLE_URL = new URL('../../dist/viewer/viewer.bundle.js', import.meta.url);
|
|
8
|
+
const loadBundle = async () => {
|
|
9
|
+
try {
|
|
10
|
+
return await readFile(BUNDLE_URL, 'utf8');
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
throw new Error('Viewer bundle missing. Run "npm run build" to produce dist/viewer/viewer.bundle.js.');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** `</script>` inside inlined JSON or JS would end the tag; escape every `</`. */
|
|
17
|
+
const inline = (text) => text.replaceAll('</', '<\\/');
|
|
18
|
+
const escapeHtml = (text) => text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
19
|
+
/**
|
|
20
|
+
* A single self-contained offline HTML file: the solved skeleton as JSON plus
|
|
21
|
+
* the prebuilt three.js viewer bundle. No CDN, no network, works from file://.
|
|
22
|
+
*/
|
|
23
|
+
export const buildViewerHtml = async (skeleton, options) => {
|
|
24
|
+
const bundle = await loadBundle();
|
|
25
|
+
const payload = JSON.stringify({
|
|
26
|
+
skeleton,
|
|
27
|
+
camera: options.camera,
|
|
28
|
+
engaged: options.engaged ?? [],
|
|
29
|
+
stretched: options.stretched ?? [],
|
|
30
|
+
});
|
|
31
|
+
const subtitle = options.subtitle === undefined ? '' : `<em>${escapeHtml(options.subtitle)}</em>`;
|
|
32
|
+
return `<!DOCTYPE html>
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="utf-8">
|
|
36
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
37
|
+
<title>${escapeHtml(options.title)} - asanakit</title>
|
|
38
|
+
<style>
|
|
39
|
+
html, body { margin: 0; height: 100%; overflow: hidden; background: #ffffff; }
|
|
40
|
+
canvas { display: block; }
|
|
41
|
+
#hud {
|
|
42
|
+
position: fixed; top: 14px; left: 18px; z-index: 1;
|
|
43
|
+
font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif; color: #1a1a1a;
|
|
44
|
+
user-select: none; pointer-events: none;
|
|
45
|
+
}
|
|
46
|
+
#hud strong { font-size: 17px; }
|
|
47
|
+
#hud em { display: block; font-size: 13px; color: #777; margin-top: 2px; }
|
|
48
|
+
#hud span { display: block; font-size: 11px; color: #aaa; margin-top: 6px; }
|
|
49
|
+
</style>
|
|
50
|
+
</head>
|
|
51
|
+
<body>
|
|
52
|
+
<div id="hud"><strong>${escapeHtml(options.title)}</strong>${subtitle}<span>drag to orbit · scroll to zoom · right-drag to pan</span></div>
|
|
53
|
+
<script>window.ASANAKIT_VIEWER = ${inline(payload)};</script>
|
|
54
|
+
<script>${inline(bundle)}</script>
|
|
55
|
+
</body>
|
|
56
|
+
</html>
|
|
57
|
+
`;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/viewer/html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAa5C;;;;GAIG;AACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,oCAAoC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAElF,MAAM,UAAU,GAAG,KAAK,IAAqB,EAAE;IAC7C,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACzG,CAAC;AACH,CAAC,CAAC;AAEF,kFAAkF;AAClF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAEvE,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE,CAC1C,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAEhF;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,QAAkB,EAAE,OAAsB,EAAmB,EAAE;IACnG,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,QAAQ;QACR,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;KACnC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAElG,OAAO;;;;;SAKA,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;wBAeV,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,QAAQ;mCAClC,MAAM,CAAC,OAAO,CAAC;UACxC,MAAM,CAAC,MAAM,CAAC;;;CAGvB,CAAC;AACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/viewer/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/viewer/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|