Give cross-body bars a true 3D axis and fix the goblet squat hold

The orbit was always a real camera orbit — figure and props share one
rigid rotation — but a bar's screen-space angle authored the wrong 3D
rod: the default horizontal encoded a rod along the body axis, so
barbells hovered fixed on screen and vanished at the head-on view
where they should span widest. Line props now take "axis": "z" (both
renderers in lockstep, fixture-pinned): the world left-right direction
projects through the camera pitch like the floor quad — end-on plates
in profile, full span face-on, swinging with the hands in between.
Applied to the ten cross-body bars; vertical handles were already
orbit-invariant.

Goblet Squat's hand pins sat so close to the shoulders that the
two-bone IK was degenerate, flipping between a chicken-wing and an
elbow-behind solve; re-pinned level with the shoulders so the elbows
tuck straight down through the whole rep.

Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
2026-07-08 12:49:35 -04:00
parent 60927b5d1f
commit fd2deaa9c7
79 changed files with 190 additions and 143 deletions
@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 164.1 90.9 L 160.0 90.4 L 160.0 91.3" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 160.0 90.4 Q 163.2 60.6 166.2 32.1" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 166.2 33.5 L 182.9 46.1 L 164.2 36.6" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 147.4 36.0 L 183.8 36.0" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="147.4" cy="36.0" r="9.799999999999999" fill="#6b7180"/>
<circle cx="183.8" cy="36.0" r="9.799999999999999" fill="#6b7180"/>
<path d="M 165.6 32.8 L 165.6 39.1" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="165.6" cy="32.8" r="9.799999999999999" fill="#6b7180"/>
<circle cx="165.6" cy="39.1" r="9.799999999999999" fill="#6b7180"/>
<circle id="head" cx="168.2" cy="18.5" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="175.2" y1="18.7" x2="180.1" y2="18.9" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 134.0 121.7 L 129.9 121.2 L 129.9 122.1" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 129.9 121.2 Q 148.2 97.2 162.3 72.1" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 162.3 73.4 L 183.0 70.2 L 162.1 68.8" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 145.3 68.1 L 181.7 68.1" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="145.3" cy="68.1" r="9.799999999999999" fill="#6b7180"/>
<circle cx="181.7" cy="68.1" r="9.799999999999999" fill="#6b7180"/>
<path d="M 163.5 65.0 L 163.5 71.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="163.5" cy="65.0" r="9.799999999999999" fill="#6b7180"/>
<circle cx="163.5" cy="71.3" r="9.799999999999999" fill="#6b7180"/>
<circle id="head" cx="170.5" cy="60.9" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="177.5" y1="61.9" x2="182.3" y2="62.6" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 14}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 14}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 157 KiB

+3 -3
View File
@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 134.0 121.7 L 129.9 121.2 L 129.9 122.1" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 129.9 121.2 Q 148.2 97.2 162.3 72.1" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 162.3 73.4 L 183.0 70.2 L 162.1 68.8" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 145.3 68.1 L 181.7 68.1" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="145.3" cy="68.1" r="9.799999999999999" fill="#6b7180"/>
<circle cx="181.7" cy="68.1" r="9.799999999999999" fill="#6b7180"/>
<path d="M 163.5 65.0 L 163.5 71.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="163.5" cy="65.0" r="9.799999999999999" fill="#6b7180"/>
<circle cx="163.5" cy="71.3" r="9.799999999999999" fill="#6b7180"/>
<circle id="head" cx="170.5" cy="60.9" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="177.5" y1="61.9" x2="182.3" y2="62.6" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -11,9 +11,9 @@
<path id="spine" d="M 150.0 116.0 Q 106.5 116.0 65.0 116.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 117.2 L 195.3 109.3 L 196.0 148.7 L 206.9 147.6" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 65.0 117.9 L 91.6 131.7 L 93.0 102.2" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 69.0 101.2 L 121.0 101.2" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="69.0" cy="101.2" r="12" fill="#6b7180"/>
<circle cx="121.0" cy="101.2" r="12" fill="#6b7180"/>
<path d="M 95.0 96.7 L 95.0 105.8" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="95.0" cy="96.7" r="12" fill="#6b7180"/>
<circle cx="95.0" cy="105.8" r="12" fill="#6b7180"/>
<circle id="head" cx="45.2" cy="113.3" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="46.6" y1="103.4" x2="47.6" y2="96.5" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -11,9 +11,9 @@
<path id="spine" d="M 150.0 116.0 Q 106.5 116.0 65.0 116.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 117.2 L 195.3 109.3 L 196.0 148.7 L 206.9 147.6" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 65.0 117.9 L 60.6 88.7 L 67.0 59.8" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 43.0 58.9 L 95.0 58.9" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="43.0" cy="58.9" r="12" fill="#6b7180"/>
<circle cx="95.0" cy="58.9" r="12" fill="#6b7180"/>
<path d="M 69.0 54.4 L 69.0 63.4" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="69.0" cy="54.4" r="12" fill="#6b7180"/>
<circle cx="69.0" cy="63.4" r="12" fill="#6b7180"/>
<circle id="head" cx="45.2" cy="113.3" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="46.6" y1="103.4" x2="47.6" y2="96.5" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
{"kind": "line", "pts": [[78, 129], [78, 150]], "w": 4},
{"kind": "line", "pts": [[144, 129], [144, 150]], "w": 4}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
],
"frames": [
{
Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 156 KiB

+3 -3
View File
@@ -11,9 +11,9 @@
<path id="spine" d="M 150.0 116.0 Q 106.5 116.0 65.0 116.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 117.2 L 195.3 109.3 L 196.0 148.7 L 206.9 147.6" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 65.0 117.9 L 91.6 131.7 L 93.0 102.2" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 69.0 101.2 L 121.0 101.2" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="69.0" cy="101.2" r="12" fill="#6b7180"/>
<circle cx="121.0" cy="101.2" r="12" fill="#6b7180"/>
<path d="M 95.0 96.7 L 95.0 105.8" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="95.0" cy="96.7" r="12" fill="#6b7180"/>
<circle cx="95.0" cy="105.8" r="12" fill="#6b7180"/>
<circle id="head" cx="45.2" cy="113.3" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="46.6" y1="103.4" x2="47.6" y2="96.5" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

+3 -3
View File
@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 116.5 109.1 L 112.4 108.6 L 112.4 109.5" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 112.4 108.6 Q 142.6 103.8 169.8 93.5" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 169.8 94.8 L 164.3 114.8 L 158.1 134.6" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 141.4 133.7 L 177.8 133.7" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="141.4" cy="133.7" r="11.2" fill="#6b7180"/>
<circle cx="177.8" cy="133.7" r="11.2" fill="#6b7180"/>
<path d="M 159.6 130.6 L 159.6 136.9" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="159.6" cy="130.6" r="11.2" fill="#6b7180"/>
<circle cx="159.6" cy="136.9" r="11.2" fill="#6b7180"/>
<circle id="head" cx="183.4" cy="90.4" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="190.4" y1="91.2" x2="195.3" y2="91.8" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

+3 -3
View File
@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 157.1 90.9 L 153.0 90.4 L 153.0 91.3" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 153.0 90.4 Q 158.3 60.9 163.3 32.7" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 163.3 34.0 L 167.6 54.3 L 160.7 73.8" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 143.9 73.2 L 180.3 73.2" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="143.9" cy="73.2" r="11.2" fill="#6b7180"/>
<circle cx="180.3" cy="73.2" r="11.2" fill="#6b7180"/>
<path d="M 162.1 70.0 L 162.1 76.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="162.1" cy="70.0" r="11.2" fill="#6b7180"/>
<circle cx="162.1" cy="76.3" r="11.2" fill="#6b7180"/>
<circle id="head" cx="166.2" cy="19.2" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="173.2" y1="19.7" x2="178.1" y2="20.0" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l", "spine"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 16}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 16}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 167 KiB

+3 -3
View File
@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 116.5 109.1 L 112.4 108.6 L 112.4 109.5" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 112.4 108.6 Q 142.6 103.8 169.8 93.5" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 169.8 94.8 L 164.3 114.8 L 158.1 134.6" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 141.4 133.7 L 177.8 133.7" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="141.4" cy="133.7" r="11.2" fill="#6b7180"/>
<circle cx="177.8" cy="133.7" r="11.2" fill="#6b7180"/>
<path d="M 159.6 130.6 L 159.6 136.9" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="159.6" cy="130.6" r="11.2" fill="#6b7180"/>
<circle cx="159.6" cy="136.9" r="11.2" fill="#6b7180"/>
<circle id="head" cx="183.4" cy="90.4" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="190.4" y1="91.2" x2="195.3" y2="91.8" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,16 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Goblet Squat</title>
<path d="M 142.9 157.6 L 199.8 157.6 L 199.8 150.1 L 142.9 150.1 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path d="M 142.9 157.6 L 197.4 157.6 L 197.4 150.1 L 142.9 150.1 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path id="leg_l" d="M 164.3 90.6 L 155.0 121.9 L 164.3 148.8 L 156.8 151.3" stroke="#86cfc5" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 160.0 91.0 L 151.5 122.5 L 161.4 149.1 L 154.0 151.8" stroke="#0d9488" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 169.6 30.1 L 191.1 28.5 L 174.4 41.9" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 169.6 30.1 L 163.7 50.5 L 180.9 37.7" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 169.6 30.1 L 165.3 30.0 L 165.3 31.4" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 164.3 90.6 L 160.0 90.1 L 160.0 91.0" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 160.0 90.1 Q 162.7 59.4 165.3 30.0" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 165.3 31.4 L 186.7 28.1 L 171.5 43.2" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 173.0 48.3 L 173.0 36.8" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="173.0" cy="48.3" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="173.0" cy="36.8" r="3.5999999999999996" fill="#6b7180"/>
<path id="arm_r" d="M 165.3 31.4 L 161.1 52.3 L 178.0 39.0" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 179.4 44.1 L 179.4 32.6" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="179.4" cy="44.1" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="179.4" cy="32.6" r="3.5999999999999996" fill="#6b7180"/>
<circle id="head" cx="167.1" cy="16.0" r="7.199999999999999" fill="white" stroke="#3a3f4b" stroke-width="4.32"/>
<line id="nose" x1="174.3" y1="16.1" x2="179.3" y2="16.2" stroke="#3a3f4b" stroke-width="2.88" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,16 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Goblet Squat</title>
<path d="M 142.9 158.1 L 199.8 158.1 L 199.8 150.6 L 142.9 150.6 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path d="M 142.9 158.1 L 197.4 158.1 L 197.4 150.6 L 142.9 150.6 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path id="leg_l" d="M 157.1 118.0 L 187.1 131.8 L 164.3 149.2 L 171.0 153.4" stroke="#86cfc5" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 178.0 60.9 L 163.3 76.5 L 184.5 72.1" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 178.0 60.9 L 170.7 80.9 L 188.8 69.3" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 152.8 118.3 L 183.3 131.0 L 161.4 149.5 L 168.3 153.3" stroke="#0d9488" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 178.0 60.9 L 173.7 60.8 L 173.7 62.2" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 157.1 118.0 L 152.8 117.4 L 152.8 118.3" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 152.8 117.4 Q 165.5 89.2 173.7 60.8" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 173.7 62.2 L 160.8 79.3 L 181.6 73.4" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 183.0 78.5 L 183.0 67.0" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="183.0" cy="78.5" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="183.0" cy="67.0" r="3.5999999999999996" fill="#6b7180"/>
<path id="arm_r" d="M 173.7 62.2 L 168.2 82.8 L 185.9 70.6" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 187.4 75.7 L 187.4 64.2" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="187.4" cy="75.7" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="187.4" cy="64.2" r="3.5999999999999996" fill="#6b7180"/>
<circle id="head" cx="179.1" cy="47.7" r="7.199999999999999" fill="white" stroke="#3a3f4b" stroke-width="4.32"/>
<line id="nose" x1="186.3" y1="48.2" x2="191.3" y2="48.5" stroke="#3a3f4b" stroke-width="2.88" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+6 -6
View File
@@ -12,24 +12,24 @@
"root": {"pos": [160, 66], "pitch": 5},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 38, "elbow_r": 125,
"shoulder_l": 38, "elbow_l": 125,
"shoulder_r": 5, "elbow_r": 140,
"shoulder_l": 5, "elbow_l": 140,
"hip_r": 5, "knee_r": 4, "ankle_r": 0,
"hip_l": 5, "knee_l": 4, "ankle_l": 0,
"pins": {"foot_r": [162, 148], "foot_l": [166, 150],
"hand_r": [176, -2], "hand_l": [180, 0]}
"hand_r": [185, -8], "hand_l": [189, -6]}
},
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [150, 104], "pitch": 22},
"spine": [0, -4],
"neck": 4, "head": -18,
"shoulder_r": 46, "elbow_r": 120,
"shoulder_l": 46, "elbow_l": 120,
"shoulder_r": 15, "elbow_r": 135,
"shoulder_l": 15, "elbow_l": 135,
"hip_r": 96, "knee_r": 116, "ankle_r": 20,
"hip_l": 96, "knee_l": 116, "ankle_l": 20,
"pins": {"foot_r": [162, 148], "foot_l": [166, 150],
"hand_r": [190, 40], "hand_l": [194, 42]}
"hand_r": [196, 36], "hand_l": [200, 38]}
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

+6 -6
View File
@@ -1,16 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Goblet Squat</title>
<path d="M 142.9 158.1 L 199.8 158.1 L 199.8 150.6 L 142.9 150.6 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path d="M 142.9 158.1 L 197.4 158.1 L 197.4 150.6 L 142.9 150.6 Z" fill="none" stroke="#b9bec9" stroke-width="2.16" stroke-linejoin="round"/>
<path id="leg_l" d="M 157.1 118.0 L 187.1 131.8 L 164.3 149.2 L 171.0 153.4" stroke="#86cfc5" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 178.0 60.9 L 163.3 76.5 L 184.5 72.1" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 178.0 60.9 L 170.7 80.9 L 188.8 69.3" stroke="#a9afba" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 152.8 118.3 L 183.3 131.0 L 161.4 149.5 L 168.3 153.3" stroke="#0d9488" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 178.0 60.9 L 173.7 60.8 L 173.7 62.2" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 157.1 118.0 L 152.8 117.4 L 152.8 118.3" stroke="#3a3f4b" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 152.8 117.4 Q 165.5 89.2 173.7 60.8" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 173.7 62.2 L 160.8 79.3 L 181.6 73.4" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 183.0 78.5 L 183.0 67.0" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="183.0" cy="78.5" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="183.0" cy="67.0" r="3.5999999999999996" fill="#6b7180"/>
<path id="arm_r" d="M 173.7 62.2 L 168.2 82.8 L 185.9 70.6" stroke="#3a3f4b" stroke-width="4.32" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 187.4 75.7 L 187.4 64.2" stroke="#6b7180" stroke-width="2.16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="187.4" cy="75.7" r="3.5999999999999996" fill="#6b7180"/>
<circle cx="187.4" cy="64.2" r="3.5999999999999996" fill="#6b7180"/>
<circle id="head" cx="179.1" cy="47.7" r="7.199999999999999" fill="white" stroke="#3a3f4b" stroke-width="4.32"/>
<line id="nose" x1="186.3" y1="48.2" x2="191.3" y2="48.5" stroke="#3a3f4b" stroke-width="2.88" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -10,9 +10,9 @@
<path id="spine" d="M 150.0 136.0 Q 107.3 127.0 69.3 110.2" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 137.2 L 187.9 111.6 L 203.0 148.0 L 212.8 143.1" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 69.3 112.1 L 99.3 112.3 L 124.0 129.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 100.0 128.1 L 152.0 128.1" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="100.0" cy="128.1" r="13" fill="#6b7180"/>
<circle cx="152.0" cy="128.1" r="13" fill="#6b7180"/>
<path d="M 126.0 123.6 L 126.0 132.7" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="126.0" cy="123.6" r="13" fill="#6b7180"/>
<circle cx="126.0" cy="132.7" r="13" fill="#6b7180"/>
<circle id="head" cx="60.2" cy="92.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="68.8" y1="87.6" x2="74.8" y2="84.0" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -10,9 +10,9 @@
<path id="spine" d="M 152.0 114.0 Q 108.5 114.0 67.1 111.1" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 152.0 115.2 L 197.5 108.7 L 203.0 147.7 L 213.7 145.3" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 67.1 113.0 L 96.5 107.4 L 126.0 113.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 102.0 112.0 L 154.0 112.0" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="102.0" cy="112.0" r="13" fill="#6b7180"/>
<circle cx="154.0" cy="112.0" r="13" fill="#6b7180"/>
<path d="M 128.0 107.5 L 128.0 116.6" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="128.0" cy="107.5" r="13" fill="#6b7180"/>
<circle cx="128.0" cy="116.6" r="13" fill="#6b7180"/>
<circle id="head" cx="54.5" cy="95.8" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="61.8" y1="89.0" x2="67.0" y2="84.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -7,7 +7,7 @@
{"kind": "line", "pts": [[50, 122], [88, 122]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[68, 127], [68, 150]], "w": 5}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 KiB

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 162 KiB

+3 -3
View File
@@ -10,9 +10,9 @@
<path id="spine" d="M 152.0 114.0 Q 108.5 114.0 67.1 111.1" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 152.0 115.2 L 197.5 108.7 L 203.0 147.7 L 213.7 145.3" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 67.1 113.0 L 96.5 107.4 L 126.0 113.0" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 102.0 112.0 L 154.0 112.0" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="102.0" cy="112.0" r="13" fill="#6b7180"/>
<circle cx="154.0" cy="112.0" r="13" fill="#6b7180"/>
<path d="M 128.0 107.5 L 128.0 116.6" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="128.0" cy="107.5" r="13" fill="#6b7180"/>
<circle cx="128.0" cy="116.6" r="13" fill="#6b7180"/>
<circle id="head" cx="54.5" cy="95.8" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="61.8" y1="89.0" x2="67.0" y2="84.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -11,9 +11,9 @@
<path id="spine" d="M 149.8 126.5 Q 127.0 97.8 105.3 70.4" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 149.8 127.5 L 187.2 116.2 L 192.3 149.3 L 201.4 147.1" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 105.3 72.1 L 130.3 77.2 L 114.1 57.8" stroke="#0d9488" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 93.7 57.0 L 137.9 57.0" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="93.7" cy="57.0" r="10.2" fill="#6b7180"/>
<circle cx="137.9" cy="57.0" r="10.2" fill="#6b7180"/>
<path d="M 115.8 53.2 L 115.8 60.9" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="115.8" cy="53.2" r="10.2" fill="#6b7180"/>
<circle cx="115.8" cy="60.9" r="10.2" fill="#6b7180"/>
<circle id="head" cx="99.5" cy="54.7" r="8.5" fill="white" stroke="#3a3f4b" stroke-width="5.1"/>
<line id="nose" x1="107.3" y1="51.3" x2="112.7" y2="48.9" stroke="#3a3f4b" stroke-width="3.4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -11,9 +11,9 @@
<path id="spine" d="M 149.8 126.5 Q 127.0 97.8 105.3 70.4" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 149.8 127.5 L 187.2 116.2 L 192.3 149.3 L 201.4 147.1" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 105.3 72.1 L 112.7 48.0 L 107.3 23.5" stroke="#0d9488" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 86.9 22.7 L 131.1 22.7" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="86.9" cy="22.7" r="10.2" fill="#6b7180"/>
<circle cx="131.1" cy="22.7" r="10.2" fill="#6b7180"/>
<path d="M 109.0 18.9 L 109.0 26.6" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="109.0" cy="18.9" r="10.2" fill="#6b7180"/>
<circle cx="109.0" cy="26.6" r="10.2" fill="#6b7180"/>
<circle id="head" cx="99.5" cy="54.7" r="8.5" fill="white" stroke="#3a3f4b" stroke-width="5.1"/>
<line id="nose" x1="107.3" y1="51.3" x2="112.7" y2="48.9" stroke="#3a3f4b" stroke-width="3.4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -9,7 +9,7 @@
{"kind": "line", "pts": [[140, 130], [166, 127]], "w": 8, "depth": 8},
{"kind": "line", "pts": [[152, 133], [152, 150]], "w": 5}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
],
"frames": [
{
Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 158 KiB

@@ -11,9 +11,9 @@
<path id="spine" d="M 149.8 126.5 Q 127.0 97.8 105.3 70.4" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 149.8 127.5 L 187.2 116.2 L 192.3 149.3 L 201.4 147.1" stroke="#3a3f4b" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 105.3 72.1 L 130.3 77.2 L 114.1 57.8" stroke="#0d9488" stroke-width="5.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 93.7 57.0 L 137.9 57.0" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="93.7" cy="57.0" r="10.2" fill="#6b7180"/>
<circle cx="137.9" cy="57.0" r="10.2" fill="#6b7180"/>
<path d="M 115.8 53.2 L 115.8 60.9" stroke="#6b7180" stroke-width="3.4" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="115.8" cy="53.2" r="10.2" fill="#6b7180"/>
<circle cx="115.8" cy="60.9" r="10.2" fill="#6b7180"/>
<circle id="head" cx="99.5" cy="54.7" r="8.5" fill="white" stroke="#3a3f4b" stroke-width="5.1"/>
<line id="nose" x1="107.3" y1="51.3" x2="112.7" y2="48.9" stroke="#3a3f4b" stroke-width="3.4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -12,7 +12,7 @@
<path id="spine" d="M 150.0 122.0 Q 146.6 79.2 147.7 38.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 123.2 L 194.4 111.4 L 193.0 150.8 L 204.0 151.2" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 147.7 40.3 L 174.8 27.4 L 194.0 4.7" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 172.0 3.8 L 220.0 3.8" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 196.0 -0.3 L 196.0 8.0" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="149.5" cy="18.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="155.3" y1="10.6" x2="159.3" y2="4.9" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -12,7 +12,7 @@
<path id="spine" d="M 150.0 122.0 Q 146.6 79.2 147.7 38.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 123.2 L 194.4 111.4 L 193.0 150.8 L 204.0 151.2" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 147.7 40.3 L 171.7 58.0 L 194.0 38.2" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 172.0 37.3 L 220.0 37.3" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 196.0 33.2 L 196.0 41.5" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="149.5" cy="18.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="158.2" y1="13.8" x2="164.2" y2="10.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -9,7 +9,7 @@
{"kind": "circle", "c": [272, 19], "r": 4, "fill": true, "color": "prop"}
]},
{"type": "cable", "from": [272, 19], "to": ["hand_r", "hand_l"], "w": 4},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 24}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 24}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 160 KiB

+1 -1
View File
@@ -12,7 +12,7 @@
<path id="spine" d="M 150.0 122.0 Q 146.6 79.2 147.7 38.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 150.0 123.2 L 194.4 111.4 L 193.0 150.8 L 204.0 151.2" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 147.7 40.3 L 171.7 58.0 L 194.0 38.2" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 172.0 37.3 L 220.0 37.3" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 196.0 33.2 L 196.0 41.5" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="149.5" cy="18.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="158.2" y1="13.8" x2="164.2" y2="10.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
<path id="spine" d="M 157.2 114.9 Q 157.2 84.9 157.2 56.3" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_l" d="M 161.3 56.3 L 160.4 35.7 L 158.6 15.1" stroke="#86cfc5" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 157.2 57.6 L 156.1 37.0 L 155.8 16.3" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 140.4 15.7 L 174.0 15.7" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 157.2 12.8 L 157.2 18.6" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="157.7" cy="42.5" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="164.7" y1="42.0" x2="169.6" y2="41.7" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
<path id="pelvisBar" d="M 161.3 93.0 L 157.2 92.5 L 157.2 93.4" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 157.2 92.5 Q 157.2 62.5 157.2 33.9" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 157.2 35.2 L 175.0 24.3 L 155.8 15.9" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 140.4 15.3 L 174.0 15.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 157.2 12.4 L 157.2 18.2" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="158.2" cy="20.2" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="165.1" y1="19.4" x2="170.0" y2="18.9" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
"camera": {"zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 24}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 24}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 131 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
<path id="pelvisBar" d="M 161.3 93.0 L 157.2 92.5 L 157.2 93.4" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 157.2 92.5 Q 157.2 62.5 157.2 33.9" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 157.2 35.2 L 175.0 24.3 L 155.8 15.9" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 140.4 15.3 L 174.0 15.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 157.2 12.4 L 157.2 18.2" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="158.2" cy="20.2" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="165.1" y1="19.4" x2="170.0" y2="18.9" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 115.1 110.5 L 111.0 110.0 L 111.0 110.9" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 111.0 110.0 Q 139.9 100.1 164.9 85.3" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 164.9 86.6 L 165.3 107.3 L 164.9 128.0" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 148.2 127.3 L 184.6 127.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="148.2" cy="127.3" r="9.1" fill="#6b7180"/>
<circle cx="184.6" cy="127.3" r="9.1" fill="#6b7180"/>
<path d="M 166.4 124.2 L 166.4 130.5" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="166.4" cy="124.2" r="9.1" fill="#6b7180"/>
<circle cx="166.4" cy="130.5" r="9.1" fill="#6b7180"/>
<circle id="head" cx="177.8" cy="79.9" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="184.7" y1="80.5" x2="189.6" y2="80.9" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 162.7 90.9 L 158.6 90.4 L 158.6 91.3" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 158.6 90.4 Q 163.9 60.9 168.9 32.7" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 168.9 34.0 L 173.2 54.3 L 166.3 73.8" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 149.5 73.2 L 185.9 73.2" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="149.5" cy="73.2" r="9.1" fill="#6b7180"/>
<circle cx="185.9" cy="73.2" r="9.1" fill="#6b7180"/>
<path d="M 167.7 70.0 L 167.7 76.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="167.7" cy="70.0" r="9.1" fill="#6b7180"/>
<circle cx="167.7" cy="76.3" r="9.1" fill="#6b7180"/>
<circle id="head" cx="171.8" cy="19.2" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="178.8" y1="19.7" x2="183.7" y2="20.0" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -4,7 +4,7 @@
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l", "spine"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 173 KiB

@@ -8,9 +8,9 @@
<path id="pelvisBar" d="M 115.1 110.5 L 111.0 110.0 L 111.0 110.9" stroke="#0d9488" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 111.0 110.0 Q 139.9 100.1 164.9 85.3" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 164.9 86.6 L 165.3 107.3 L 164.9 128.0" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 148.2 127.3 L 184.6 127.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="148.2" cy="127.3" r="9.1" fill="#6b7180"/>
<circle cx="184.6" cy="127.3" r="9.1" fill="#6b7180"/>
<path d="M 166.4 124.2 L 166.4 130.5" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="166.4" cy="124.2" r="9.1" fill="#6b7180"/>
<circle cx="166.4" cy="130.5" r="9.1" fill="#6b7180"/>
<circle id="head" cx="177.8" cy="79.9" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="184.7" y1="80.5" x2="189.6" y2="80.9" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

+15 -6
View File
@@ -179,12 +179,21 @@ authored yaw nothing moves, so the authored look is exact.
(`hand_r`, `foot_l`, …) plus the mid joints (`elbow_r`, `knee_l`, …), so a
machine pad can ride a knee (`["knee_r", "knee_l"]`) or span a shin
(`["knee_r", "foot_r"]`).
`bar` lies at a fixed authored-view `angle` (default 0 = horizontal — in
side view a two-handed bar is drawn horizontal by convention); `dumbbell`
and `pad` default to perpendicular to the lower bone (forearm/shin), or
take an explicit `angle`. Under orbit the segment rotates with the scene
and foreshortens naturally. `plateR` puts filled discs on both ends
(dumbbells default to 4.5).
`bar` lies at a fixed authored-view `angle` (default 0 = horizontal);
`dumbbell` and `pad` default to perpendicular to the lower bone
(forearm/shin), or take an explicit `angle`. Under orbit the segment
rotates with the scene and foreshortens naturally. `plateR` puts filled
discs on both ends (dumbbells default to 4.5).
A cross-body rod — a barbell, pull-up bar, or any grip that really runs
left-right *through* both hands — should instead set `"axis": "z"`
(superseding `angle`): its world-space direction projects through the
camera elevation like the floor quad, so in a profile view it reads
end-on (plates nearly concentric, seen from slightly above), opens to
its full span face-on, and swings with the figure in between. A fixed
screen-space `angle` can't do this — it keeps the rod glued to the
authored direction while the body turns under it. Vertical handles
(`angle: 90`) don't need it: a world-vertical rod is unchanged by a yaw
orbit.
- **`roller`** — a machine roller pad seen end-on: a filled disc riding the
limb's lower bone near the joint in `at`, on the `side` (+1/1) of the bone
it presses — a leg extension's instep roller (`side: 1`), a leg curl's
@@ -12,7 +12,7 @@
<path id="spine" d="M 120.0 130.0 Q 103.0 90.4 95.1 50.1" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 120.0 131.2 L 161.9 112.6 L 164.0 151.9 L 175.0 151.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 95.1 52.0 L 110.1 77.6 L 110.1 48.0" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 103.1 47.1 L 123.1 47.1" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 113.1 45.4 L 113.1 48.8" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="98.6" cy="30.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="108.5" y1="29.3" x2="115.4" y2="28.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -12,7 +12,7 @@
<path id="spine" d="M 120.0 130.0 Q 103.0 90.4 95.1 50.1" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 120.0 131.2 L 161.9 112.6 L 164.0 151.9 L 175.0 151.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 95.1 52.0 L 112.8 28.1 L 133.6 6.8" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.6 5.9 L 146.6 5.9" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 136.6 4.2 L 136.6 7.6" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="98.6" cy="30.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="108.5" y1="29.3" x2="115.4" y2="28.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

+1 -1
View File
@@ -9,7 +9,7 @@
{"kind": "line", "pts": [[126, 143], [126, 151]], "w": 5},
{"kind": "line", "pts": [[110, 151], [142, 151]], "w": 4, "depth": 5}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 10}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 10}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 168 KiB

+1 -1
View File
@@ -12,7 +12,7 @@
<path id="spine" d="M 120.0 130.0 Q 103.0 90.4 95.1 50.1" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 120.0 131.2 L 161.9 112.6 L 164.0 151.9 L 175.0 151.3" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 95.1 52.0 L 112.8 28.1 L 133.6 6.8" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.6 5.9 L 146.6 5.9" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 136.6 4.2 L 136.6 7.6" stroke="#6b7180" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="98.6" cy="30.7" r="10" fill="white" stroke="#3a3f4b" stroke-width="6"/>
<line id="nose" x1="108.5" y1="29.3" x2="115.4" y2="28.3" stroke="#3a3f4b" stroke-width="4" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -10,7 +10,7 @@
<path id="pelvisBar" d="M 157.1 92.3 L 153.0 91.8 L 153.0 92.7" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 153.0 91.8 Q 156.7 62.0 162.3 33.9" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 162.3 35.3 L 151.5 53.0 L 168.4 40.7" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 162.8 40.1 L 176.8 40.1" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 169.8 38.9 L 169.8 41.3" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="166.2" cy="20.7" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="173.1" y1="21.6" x2="177.9" y2="22.3" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -10,7 +10,7 @@
<path id="pelvisBar" d="M 157.1 92.3 L 153.0 91.8 L 153.0 92.7" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 153.0 91.8 Q 156.7 62.0 162.3 33.9" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 162.3 35.3 L 158.8 55.7 L 165.6 75.2" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 160.0 74.6 L 174.0 74.6" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 167.0 73.4 L 167.0 75.8" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="166.2" cy="20.7" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="173.1" y1="21.6" x2="177.9" y2="22.3" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

@@ -8,7 +8,7 @@
{"kind": "circle", "c": [186, -58], "r": 4, "fill": true, "color": "prop"}
]},
{"type": "cable", "from": [186, -58], "to": ["hand_r", "hand_l"], "w": 3},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 10}
{"type": "bar", "axis": "z", "at": ["hand_r", "hand_l"], "halfLen": 10}
],
"frames": [
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 121 KiB

+1 -1
View File
@@ -10,7 +10,7 @@
<path id="pelvisBar" d="M 157.1 92.3 L 153.0 91.8 L 153.0 92.7" stroke="#3a3f4b" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="spine" d="M 153.0 91.8 Q 156.7 62.0 162.3 33.9" stroke="#3a3f4b" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 162.3 35.3 L 158.8 55.7 L 165.6 75.2" stroke="#0d9488" stroke-width="4.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 160.0 74.6 L 174.0 74.6" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 167.0 73.4 L 167.0 75.8" stroke="#6b7180" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<circle id="head" cx="166.2" cy="20.7" r="7.0" fill="white" stroke="#3a3f4b" stroke-width="4.2"/>
<line id="nose" x1="173.1" y1="21.6" x2="177.9" y2="22.3" stroke="#3a3f4b" stroke-width="2.8" stroke-linecap="round"/>
<g font-family="-apple-system, Helvetica, sans-serif" font-size="11" fill="#6b7180">

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 622 KiB

After

Width:  |  Height:  |  Size: 844 KiB

+21 -9
View File
@@ -340,7 +340,7 @@ def joint_points(geo, ref):
sum(p[1] for p in pts) / len(pts)), direction)
def resolve_props(props, geo, anchor, rot=K.IDENTITY, auth_geo=None):
def resolve_props(props, geo, anchor, rot=K.IDENTITY, auth_geo=None, pitch=CAMERA_PITCH):
"""Props -> drawable primitives for one frame: (background, foreground).
`geo` is the frame's drawn (possibly orbit-rotated) geometry, `auth_geo`
@@ -348,7 +348,9 @@ def resolve_props(props, geo, anchor, rot=K.IDENTITY, auth_geo=None):
frame's root canvas anchor, and `rot` the `prop_rotation` between them.
Joint positions come from `geo`; everything authored — scene points,
cable anchors, bar angles, pad perpendiculars, roller offsets — resolves
against `auth_geo` and rotates through `rot`.
against `auth_geo` and rotates through `rot`. `pitch` is the camera
elevation, needed by `axis` props whose world-space direction projects
through it (like the floor quad).
"""
auth = auth_geo if auth_geo is not None else geo
@@ -415,11 +417,21 @@ def resolve_props(props, geo, anchor, rot=K.IDENTITY, auth_geo=None):
_, d = joint_points(auth, p["at"])
if not c or not d:
continue
if t == "bar" or "angle" in p:
if p.get("axis") == "z":
# A cross-body rod (barbell, pull-up bar): its true 3D axis is
# the world left-right axis, projected through the camera
# elevation like the floor quad — a small vertical sliver
# end-on in a profile view (the plates read nearly concentric,
# seen from slightly above), full span face-on, swinging with
# the figure in between, symmetric at 0 and 180.
pr = math.radians(pitch)
ux, uy = swing((0.0, math.sin(pr)), math.cos(pr))
elif t == "bar" or "angle" in p:
axis = dirv(p.get("angle", 0)) # fixed authored-view angle
ux, uy = swing(axis) # foreshortens under orbit
else:
axis = (-d[1], d[0]) # perpendicular to the lower bone
ux, uy = swing(axis) # foreshortens under orbit
ux, uy = swing(axis)
h = p.get("halfLen", {"bar": 24, "dumbbell": 7, "pad": 8}[t])
a = (c[0] - ux * h, c[1] - uy * h)
b = (c[0] + ux * h, c[1] + uy * h)
@@ -662,7 +674,7 @@ def render_exercise(folder, figure="neutral", flip=False, strict=False):
for nf in norms:
out, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
resolved.append(out)
prims = resolve_props(props, geo, nf["root"]["pos"])
prims = resolve_props(props, geo, nf["root"]["pos"], pitch=pitch)
geo, prims = apply_zoom(geo, prims, zoom)
key_cells.append((geo, order, shade, prims))
@@ -682,7 +694,7 @@ def render_exercise(folder, figure="neutral", flip=False, strict=False):
imgs = []
for nf in timeline(resolved):
geo, order, shade = geometry(nf)
prims = resolve_props(props, geo, nf["root"]["pos"])
prims = resolve_props(props, geo, nf["root"]["pos"], pitch=pitch)
geo, prims = apply_zoom(geo, prims, zoom)
imgs.append(draw_geo(geo, order, shade, working, colors, font=font, prims=prims))
imgs[0].save(folder / "preview.gif", save_all=True, append_images=imgs[1:],
@@ -716,7 +728,7 @@ def render_orbit(folder, figure="neutral"):
posed["pins"] = {}
_, geo, order, shade = frame_geometry(posed, prof, cam + off, pitch=pitch, mat=mat)
prims = resolve_props(props, geo, nf["root"]["pos"],
prop_rotation(pitch, off), auth_geo)
prop_rotation(pitch, off), auth_geo, pitch=pitch)
geo, prims = apply_zoom(geo, prims, zoom)
imgs.append(draw_geo(geo, order, shade, working, colors, font=font, prims=prims))
imgs[0].save(folder / "orbit.gif", save_all=True, append_images=imgs[1:],
@@ -734,7 +746,7 @@ def contact_sheet(folders, figure="neutral", out=None):
mat = mat_bounds(norms, prof, cam, pitch)
for i, nf in enumerate(norms, start=1):
_, geo, order, shade = frame_geometry(nf, prof, cam, pitch=pitch, mat=mat)
prims = resolve_props(props, geo, nf["root"]["pos"])
prims = resolve_props(props, geo, nf["root"]["pos"], pitch=pitch)
geo, prims = apply_zoom(geo, prims, zoom)
cells.append((f"{motion['name']} {i}/{len(norms)}",
draw_geo(geo, order, shade, working, PALETTES["default"],
@@ -760,7 +772,7 @@ def demo_sheet(folder):
norms, prof, cam, pitch, props, zoom = prepare(motion, figure, flip)
mat = mat_bounds(norms, prof, cam, pitch)
_, geo, order, shade = frame_geometry(norms[idx], prof, cam, flip, pitch, mat)
prims = resolve_props(props, geo, norms[idx]["root"]["pos"])
prims = resolve_props(props, geo, norms[idx]["root"]["pos"], pitch=pitch)
geo, prims = apply_zoom(geo, prims, zoom)
cells.append((f"{motion['name']}{label}",
draw_geo(geo, order, shade, working, PALETTES[palette],