Draw the ground as an exercise mat that rotates with the figure

The floor rectangle was screen-locked, which broke the illusion the
moment the camera orbited. It is now a world-space quad on the ground
plane, sized to each motion's projected footprint across its key frames
and rotated through the same camera as the figure - a long rectangle in
profile, a parallelogram mid-orbit, end-on when face-on. Both renderers
in lockstep; fixtures unaffected (the mat is a pure addition).

Claude-Session: https://claude.ai/code/session_01LEoff8bXGBS83tK1c55Mf7
This commit is contained in:
2026-07-06 21:31:36 -04:00
parent b82054b81a
commit 6d9eff1a71
98 changed files with 177 additions and 107 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
**July 2026**
Form guides are now viewed from a slight elevation, with the floor drawn as a plane the figure stands on.
Form guides are now viewed from a slight elevation, with an exercise mat under the figure that turns with the camera.
The stick figure now has broader, more human proportions with a visible shoulder girdle and pelvis.
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abdominal</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 105.8 160.8 L 213.8 160.8 L 213.8 150.3 L 105.8 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 120.0 128.0 L 114.0 62.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 130.0 L 150.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 122.0 150.0" stroke="#c5cad4" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abdominal</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 105.8 160.8 L 213.8 160.8 L 213.8 150.3 L 105.8 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 120.0 128.0 L 114.0 62.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 130.0 L 150.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 122.0 150.0" stroke="#c5cad4" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 188 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abdominal</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 105.8 160.8 L 213.8 160.8 L 213.8 150.3 L 105.8 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 120.0 128.0 L 114.0 62.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 130.0 L 150.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 122.0 150.0" stroke="#c5cad4" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 192 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Abductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Adductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Adductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 192 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Adductor</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 145.6 L 130.0 165.2 L 190.0 165.2 L 190.0 145.6 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<rect x="152" y="56" width="16" height="72" rx="5" fill="#c5cad4"/>
<rect x="130" y="126" width="60" height="10" rx="3" fill="#c5cad4"/>
<path d="M 160.0 136.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Arm Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 115.2 160.7 L 203.0 160.7 L 203.0 150.3 L 115.2 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 150.0 134.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 136.0 52.0 L 164.0 70.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 164.0 70.0 L 164.0 128.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Arm Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 115.2 160.7 L 203.0 160.7 L 203.0 150.3 L 115.2 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 150.0 134.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 136.0 52.0 L 164.0 70.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 164.0 70.0 L 164.0 128.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 135 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Arm Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 115.2 160.7 L 203.0 160.7 L 203.0 150.3 L 115.2 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 150.0 134.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 136.0 52.0 L 164.0 70.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 164.0 70.0 L 164.0 128.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Bird Dog</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 37.3 160.4 L 298.0 160.4 L 298.0 150.0 L 37.3 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 112.0 93.0 L 115.9 122.2 L 111.0 151.4" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Bird Dog</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 37.3 160.4 L 298.0 160.4 L 298.0 150.0 L 37.3 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 112.0 93.0 L 115.9 122.2 L 111.0 151.4" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 240.3 95.0 L 279.0 84.8 L 286.0 93.1" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Bird Dog</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 37.3 160.4 L 298.0 160.4 L 298.0 150.0 L 37.3 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 112.0 93.0 L 115.9 122.2 L 111.0 151.4" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Bird Dog</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 37.3 160.4 L 298.0 160.4 L 298.0 150.0 L 37.3 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 112.0 93.0 L 83.6 83.3 L 55.2 73.7" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 106.0 94.8 L 106.0 92.9 L 112.0 93.0" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 248 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Bird Dog</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 37.3 160.4 L 298.0 160.4 L 298.0 150.0 L 37.3 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 112.0 93.0 L 115.9 122.2 L 111.0 151.4" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 240.3 95.0 L 279.0 84.8 L 286.0 93.1" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#0d9488" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Calfs</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 109.6 160.6 L 238.3 160.6 L 238.3 150.2 L 109.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 124.0 126.0 L 158.0 124.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 128.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 120.0 150.0 L 156.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Calfs</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 109.6 160.6 L 238.3 160.6 L 238.3 150.2 L 109.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 124.0 126.0 L 158.0 124.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 128.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 120.0 150.0 L 156.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 146 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Calfs</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 109.6 160.6 L 238.3 160.6 L 238.3 150.2 L 109.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 124.0 126.0 L 158.0 124.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 128.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 120.0 150.0 L 156.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Cat-Cow</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 67.4 160.4 L 262.5 160.4 L 262.5 150.0 L 67.4 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 115.3 94.5 L 120.9 123.5 L 111.0 151.4" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Cat-Cow</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 67.4 160.4 L 262.5 160.4 L 262.5 150.0 L 67.4 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 115.9 96.8 L 124.6 125.0 L 111.0 151.4" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 143 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Cat-Cow</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 67.4 160.4 L 262.5 160.4 L 262.5 150.0 L 67.4 150.0 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 115.3 94.5 L 120.9 123.5 L 111.0 151.4" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 195.9 106.8 L 201.5 151.7 L 241.5 151.7 L 250.5 157.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.0 107.2 L 195.6 152.2 L 235.6 152.2 L 244.6 158.4" stroke="#3a3f4b" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Chest Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 78.4 160.7 L 184.9 160.7 L 184.9 150.3 L 78.4 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 114.0 132.0 L 86.0 40.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 133.0 L 146.0 133.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 135.0 L 122.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Chest Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 78.4 160.7 L 184.9 160.7 L 184.9 150.3 L 78.4 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 114.0 132.0 L 86.0 40.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 133.0 L 146.0 133.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 135.0 L 122.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 138 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Chest Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 78.4 160.7 L 184.9 160.7 L 184.9 150.3 L 78.4 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 114.0 132.0 L 86.0 40.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 106.0 133.0 L 146.0 133.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 122.0 135.0 L 122.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Dead Bug</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 45.6 161.1 L 285.6 161.1 L 285.6 150.7 L 45.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 105.9 118.5 L 105.9 89.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 211.1 108.0 L 250.5 114.9 L 252.4 104.2" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Dead Bug</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 45.6 161.1 L 285.6 161.1 L 285.6 150.7 L 45.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 105.9 118.5 L 105.9 89.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 235.1 136.3 L 273.6 125.4 L 270.5 115.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Dead Bug</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 45.6 161.1 L 285.6 161.1 L 285.6 150.7 L 45.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 105.9 118.5 L 105.9 89.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 211.1 108.0 L 250.5 114.9 L 252.4 104.2" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Dead Bug</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 45.6 161.1 L 285.6 161.1 L 285.6 150.7 L 45.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 84.7 127.2 L 63.5 106.3" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 211.1 108.0 L 250.5 114.9 L 252.4 104.2" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 233 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Dead Bug</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 45.6 161.1 L 285.6 161.1 L 285.6 150.7 L 45.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 105.9 118.5 L 105.9 89.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 235.1 136.3 L 273.6 125.4 L 270.5 115.0" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Hollow Body Hold</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 236.9 148.8 L 276.9 148.8 L 276.9 137.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Hollow Body Hold</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 123 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Hollow Body Hold</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 28.0 161.1 L 288.9 161.1 L 288.9 150.7 L 28.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 235.9 139.3 L 275.0 131.1 L 272.7 120.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 108.7 129.5 L 102.8 129.4 L 102.8 131.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Lat Pull Down</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 127.5 160.7 L 220.0 160.7 L 220.0 150.3 L 127.5 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 126.0 130.0 L 162.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 132.0 L 144.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="272.0" cy="19.0" r="4" fill="#6b7180"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Lat Pull Down</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 127.5 160.7 L 220.0 160.7 L 220.0 150.3 L 127.5 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 126.0 130.0 L 162.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 132.0 L 144.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="272.0" cy="19.0" r="4" fill="#6b7180"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 163 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Lat Pull Down</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 127.5 160.7 L 220.0 160.7 L 220.0 150.3 L 127.5 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 126.0 130.0 L 162.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 132.0 L 144.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="272.0" cy="19.0" r="4" fill="#6b7180"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 130.0 105.0 L 158.0 106.0" stroke="#c5cad4" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 130.0 105.0 L 158.0 106.0" stroke="#c5cad4" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 172 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Curl</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 130.0 105.0 L 158.0 106.0" stroke="#c5cad4" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Extension</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 126.0 L 108.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Extension</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 126.0 L 108.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 165 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Extension</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 75.2 160.6 L 221.1 160.6 L 221.1 150.2 L 75.2 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 110.0 122.0 L 86.0 48.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 104.0 124.0 L 166.0 120.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 126.0 L 108.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 88.6 160.6 L 238.5 160.6 L 238.5 150.2 L 88.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 134.0 123.0 L 96.0 36.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 127.0 L 156.0 122.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 88.6 160.6 L 238.5 160.6 L 238.5 150.2 L 88.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 134.0 123.0 L 96.0 36.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 127.0 L 156.0 122.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 166 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 88.6 160.6 L 238.5 160.6 L 238.5 150.2 L 88.6 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 134.0 123.0 L 96.0 36.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 127.0 L 156.0 122.0" stroke="#c5cad4" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 138.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Raises</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 58.4 161.1 L 288.1 161.1 L 288.1 150.7 L 58.4 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 135.9 149.1 L 165.9 150.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Raises</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 58.4 161.1 L 288.1 161.1 L 288.1 150.7 L 58.4 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 135.9 149.1 L 165.9 150.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 190.9 148.8 L 236.5 142.4 L 276.1 137.0 L 274.5 126.2" stroke="#86cfc5" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 112 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Leg Raises</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 58.4 161.1 L 288.1 161.1 L 288.1 150.7 L 58.4 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 105.9 148.1 L 135.9 149.1 L 165.9 150.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 105.9 148.1 L 100.0 148.0 L 100.0 149.9" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="pelvisBar" d="M 190.9 148.8 L 185.0 148.0 L 185.0 149.2" stroke="#3a3f4b" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 42.3 160.6 L 270.6 160.6 L 270.6 150.2 L 42.3 150.2 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 93.2 121.4 L 93.2 150.9 L 63.2 150.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 177.9 114.8 L 204.3 151.9 L 244.3 151.9 L 244.3 162.7" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 87.3 123.2 L 87.3 121.3 L 93.2 121.4" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 42.3 160.9 L 270.6 160.9 L 270.6 150.5 L 42.3 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 90.2 122.5 L 90.2 152.1 L 60.2 152.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 173.9 137.8 L 219.2 145.6 L 258.6 152.5 L 256.7 163.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 84.3 124.4 L 84.3 122.5 L 90.2 122.5" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 42.3 160.9 L 270.6 160.9 L 270.6 150.5 L 42.3 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 90.2 122.5 L 90.2 152.1 L 60.2 152.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 173.9 137.8 L 219.2 145.6 L 258.6 152.5 L 256.7 163.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 84.3 124.4 L 84.3 122.5 L 90.2 122.5" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Reverse Crunch</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 40.6 161.1 L 223.3 161.1 L 223.3 150.7 L 40.6 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 92.9 148.1 L 122.9 149.1 L 152.9 150.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 177.9 148.8 L 169.9 104.1 L 207.5 117.6 L 211.3 107.4" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 92.9 148.1 L 87.0 148.0 L 87.0 149.9" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Reverse Crunch</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 40.6 160.9 L 223.3 160.9 L 223.3 150.5 L 40.6 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 88.5 143.4 L 118.5 144.4 L 148.5 145.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 171.9 136.8 L 152.5 95.7 L 191.9 102.5 L 193.8 91.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 125 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Reverse Crunch</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 40.6 160.9 L 223.3 160.9 L 223.3 150.5 L 40.6 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_l" d="M 88.5 143.4 L 118.5 144.4 L 148.5 145.5" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_l" d="M 171.9 136.8 L 152.5 95.7 L 191.9 102.5 L 193.8 91.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 88.5 143.4 L 82.6 143.4 L 82.6 145.3" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Rotary</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 144.5 L 130.0 166.5 L 190.0 166.5 L 190.0 144.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 182.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 160.0 132.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 150.0 L 176.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Rotary</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 144.5 L 130.0 166.5 L 190.0 166.5 L 190.0 144.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 182.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 160.0 132.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 150.0 L 176.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 142 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Rotary</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 130.0 144.5 L 130.0 166.5 L 190.0 166.5 L 190.0 144.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 138.0 130.0 L 182.0 130.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 160.0 132.0 L 160.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 144.0 150.0 L 176.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

+8 -5
View File
@@ -79,11 +79,14 @@ never touches a motion script** — proportions are the skeleton's problem.
proportions. Face-on machines (abductor/adductor, rotary torso) author
genuine abduction or spine rotation and let projection do the rest. The
camera can also orbit while the motion loops (`--orbit`).
- **Elevation** — the default viewpoint pitches down 10° (`CAMERA_PITCH`;
override per motion via `"camera": {"pitch": ...}`), so the floor reads as
a plane — drawn as a rectangle — and near/far contacts straddle it.
Elevation is pure presentation: pins solve in the flat authored view and
the *posed* body tilts, so authored canvas targets never go out of reach.
- **Elevation & the mat** — the default viewpoint pitches down 10°
(`CAMERA_PITCH`; override per motion via `"camera": {"pitch": ...}`), and
the ground is drawn as an **exercise mat**: a world-space quad sized to the
motion's footprint (`mat_bounds`) that rotates with the camera about the
figure — a long rectangle in profile, a parallelogram mid-orbit, end-on
when face-on. Near/far contacts straddle it. Elevation is pure
presentation: pins solve in the flat authored view and the *posed* body
tilts, so authored canvas targets never go out of reach.
- **Feet** — each leg ends in a foot bone off the ankle. Dorsiflexion 0 keeps
the foot perpendicular to the shin (right for standing, seated machines,
planks); kneeling poses trail it back (55), raises point it.
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Seated Row</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 118.3 160.7 L 216.0 160.7 L 216.0 150.3 L 118.3 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 156.0 132.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 159.0 46.0 L 157.0 96.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 176.0 150.0 L 206.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Seated Row</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 118.3 160.7 L 216.0 160.7 L 216.0 150.3 L 118.3 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 156.0 132.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 159.0 46.0 L 157.0 96.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 176.0 150.0 L 206.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 185 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Seated Row</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 118.3 160.7 L 216.0 160.7 L 216.0 150.3 L 118.3 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 122.0 132.0 L 156.0 132.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 159.0 46.0 L 157.0 96.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 176.0 150.0 L 206.0 150.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Shoulder Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 76.6 160.8 L 191.0 160.8 L 191.0 150.4 L 76.6 150.4 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 140.0 L 88.0 50.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 110.0 141.0 L 148.0 141.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 143.0 L 126.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Shoulder Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 76.6 160.8 L 191.0 160.8 L 191.0 150.4 L 76.6 150.4 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 140.0 L 88.0 50.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 110.0 141.0 L 148.0 141.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 143.0 L 126.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 153 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Shoulder Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 76.6 160.8 L 191.0 160.8 L 191.0 150.4 L 76.6 150.4 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 140.0 L 88.0 50.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 110.0 141.0 L 148.0 141.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 126.0 143.0 L 126.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Side Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 48.0 161.1 L 277.9 161.1 L 277.9 150.7 L 48.0 150.7 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="arm_r" d="M 99.1 124.2 L 127.3 134.3 L 156.2 141.9" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="leg_r" d="M 179.9 150.8 L 225.9 151.5 L 265.9 152.2 L 265.7 163.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 93.2 126.0 L 93.2 124.1 L 99.1 124.2" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Side Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 48.0 160.9 L 277.9 160.9 L 277.9 150.5 L 48.0 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_r" d="M 179.9 137.8 L 225.2 145.6 L 264.6 152.5 L 262.7 163.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 96.2 122.5 L 101.4 93.4 L 106.6 64.3" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 90.3 124.4 L 90.3 122.5 L 96.2 122.5" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 135 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Side Plank</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 48.0 160.9 L 277.9 160.9 L 277.9 150.5 L 48.0 150.5 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path id="leg_r" d="M 179.9 137.8 L 225.2 145.6 L 264.6 152.5 L 262.7 163.1" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="arm_r" d="M 96.2 122.5 L 101.4 93.4 L 106.6 64.3" stroke="#a9afba" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="girdle" d="M 90.3 124.4 L 90.3 122.5 L 96.2 122.5" stroke="#0d9488" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Tricep Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 82.7 160.7 L 182.8 160.7 L 182.8 150.3 L 82.7 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 92.0 42.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 135.0 L 146.0 135.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 124.0 137.0 L 124.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Tricep Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 82.7 160.7 L 182.8 160.7 L 182.8 150.3 L 82.7 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 92.0 42.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 135.0 L 146.0 135.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 124.0 137.0 L 124.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 142 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180" fill="none">
<title>Tricep Press</title>
<rect x="16" y="150.8" width="288" height="10.4" rx="3" fill="none" stroke="#b9bec9" stroke-width="3"/>
<path d="M 82.7 160.7 L 182.8 160.7 L 182.8 150.3 L 82.7 150.3 Z" fill="none" stroke="#b9bec9" stroke-width="3" stroke-linejoin="round"/>
<path d="M 116.0 134.0 L 92.0 42.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 108.0 135.0 L 146.0 135.0" stroke="#c5cad4" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 124.0 137.0 L 124.0 151.0" stroke="#c5cad4" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

+48 -18
View File
@@ -102,7 +102,7 @@ def _bucket(depth):
return round(depth / DEPTH_BUCKET)
def frame_geometry(nf, prof, cam, flipped=False, pitch=CAMERA_PITCH):
def frame_geometry(nf, prof, cam, flipped=False, pitch=CAMERA_PITCH, mat=None):
"""Resolve one normalized frame into drawable 2D geometry.
Returns (nf with IK-resolved angles and original pins, geo, order, shade):
@@ -167,6 +167,18 @@ def frame_geometry(nf, prof, cam, flipped=False, pitch=CAMERA_PITCH):
geo["girdle"] = [attach("shoulder_l", "arm_l"), neck_b, attach("shoulder_r", "arm_r")]
geo["pelvisBar"] = [attach("hip_l", "leg_l"), pelvis, attach("hip_r", "leg_r")]
# The exercise mat: a world-space quad on the ground plane, rotating with
# the camera about the figure's vertical axis (`mat` = screen-x bounds of
# the motion's footprint in the authored view).
if mat is not None:
yg = -(GROUND_Y + 4 - anchor[1])
rc = K.mmul(K.rot_x(pitch), K.rot_y(-cam))
geo["floor"] = [scr(K.mvec(rc, (dx, yg, dz))[:2] + (0,))
for dx, dz in ((mat[0] - anchor[0], FLOOR_HALF_DEPTH),
(mat[1] - anchor[0], FLOOR_HALF_DEPTH),
(mat[1] - anchor[0], -FLOOR_HALF_DEPTH),
(mat[0] - anchor[0], -FLOOR_HALF_DEPTH))]
# The nose tick rides the head's anterior axis; it foreshortens naturally
# and disappears when the face points at (or away from) the camera.
nd = p["nose_dir"]
@@ -183,6 +195,19 @@ def frame_geometry(nf, prof, cam, flipped=False, pitch=CAMERA_PITCH):
return work, geo, order, shade
def mat_bounds(norms, prof, cam, pitch=CAMERA_PITCH):
"""The motion's footprint in the authored view: min/max screen x of every
figure point across the key frames, padded - the exercise mat spans it."""
lo, hi = float("inf"), float("-inf")
for nf in norms:
_, geo, _, _ = frame_geometry(nf, prof, cam, pitch=pitch)
xs = [geo["head"][0] - geo["headR"], geo["head"][0] + geo["headR"]]
for part in ("arm_r", "arm_l", "leg_r", "leg_l", "spine", "girdle", "pelvisBar"):
xs += [pt[0] for pt in geo.get(part, [])]
lo, hi = min(lo, min(xs)), max(hi, max(xs))
return lo - 12, hi + 12
def ease(t):
return 3 * t * t - 2 * t * t * t
@@ -345,13 +370,15 @@ def draw_prims(d, prims, colors, scale):
# ------------------------------------------------------------------- drawing
def floor_rect_svg(colors):
"""The floor plane under the elevated camera: a rectangle straddling the
ground line (the old horizontal line was the pitch-zero degenerate case)."""
fh = FLOOR_HALF_DEPTH * math.sin(math.radians(CAMERA_PITCH))
return (f' <rect x="16" y="{GROUND_Y + 4 - fh:.1f}" width="{CANVAS[0] - 32}"'
f' height="{2 * fh:.1f}" rx="3" fill="none"'
f' stroke="{colors["ground"]}" stroke-width="3"/>')
def floor_svg(geo, colors):
"""The exercise mat: a world-space quad on the ground plane, sized to the
motion's footprint and rotating with the camera."""
quad = geo.get("floor")
if not quad:
return ""
d = "M " + " L ".join(f"{x:.1f} {y:.1f}" for x, y in quad) + " Z"
return (f' <path d="{d}" fill="none" stroke="{colors["ground"]}"'
f' stroke-width="3" stroke-linejoin="round"/>')
def part_style(part, working, colors, shade):
@@ -378,7 +405,7 @@ def svg_for_frame(name, geo, order, shade, working, colors, props=None):
w, h = CANVAS
parts = [f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" fill="none">',
f' <title>{name}</title>',
floor_rect_svg(colors)]
floor_svg(geo, colors)]
parts += svg_prims(bg, colors)
for part in order:
if part == "head":
@@ -431,10 +458,8 @@ def draw_geo(geo, order, shade, working, colors, scale=2, font=None, props=None)
for x, y in (pts[0], pts[-1]):
d.ellipse([x - r, y - r, x + r, y + r], fill=color)
fh = FLOOR_HALF_DEPTH * math.sin(math.radians(CAMERA_PITCH))
d.rounded_rectangle([16 * scale, (GROUND_Y + 4 - fh) * scale,
(CANVAS[0] - 16) * scale, (GROUND_Y + 4 + fh) * scale],
radius=3 * scale, outline=colors["ground"], width=3 * scale)
if geo.get("floor"):
line(geo["floor"] + geo["floor"][:1], colors["ground"], 3)
draw_prims(d, bg, colors, scale)
for part in order:
if part == "head":
@@ -511,8 +536,10 @@ def render_exercise(folder, figure="neutral", flip=False, strict=False):
hide = set(motion.get("hide", []))
norms, prof, cam, pitch, props = prepare(motion, figure, flip, strict)
mat = mat_bounds(norms, prof, cam, pitch)
def geometry(nf):
_, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch)
_, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
for limb in hide:
geo.pop(limb, None)
return geo, order, shade
@@ -520,7 +547,7 @@ def render_exercise(folder, figure="neutral", flip=False, strict=False):
resolved = []
key_geos = []
for nf in norms:
out, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch)
out, geo, order, shade = frame_geometry(nf, prof, cam, flip, pitch, mat)
for limb in hide:
geo.pop(limb, None)
resolved.append(out)
@@ -559,6 +586,7 @@ def render_orbit(folder, figure="neutral"):
hide = set(motion.get("hide", []))
norms, prof, cam, pitch, props = prepare(motion, figure)
resolved = [frame_geometry(nf, prof, cam, pitch=pitch)[0] for nf in norms]
mat = mat_bounds(norms, prof, cam, pitch)
font = legend_font()
colors = PALETTES["default"]
ticks = timeline(resolved)
@@ -569,7 +597,7 @@ def render_orbit(folder, figure="neutral"):
# then rotate the posed body - never re-pin in the rotated view.
posed, _, _, _ = frame_geometry(nf, prof, cam, pitch=pitch)
posed["pins"] = {}
_, geo, order, shade = frame_geometry(posed, prof, yaw, pitch=pitch)
_, geo, order, shade = frame_geometry(posed, prof, yaw, pitch=pitch, mat=mat)
for limb in hide:
geo.pop(limb, None)
imgs.append(draw_geo(geo, order, shade, working, colors, font=font, props=props))
@@ -585,8 +613,9 @@ def contact_sheet(folders, figure="neutral", out=None):
motion = load_motion(folder)
working, hide = set(motion.get("working", [])), set(motion.get("hide", []))
norms, prof, cam, pitch, props = prepare(motion, figure)
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)
_, geo, order, shade = frame_geometry(nf, prof, cam, pitch=pitch, mat=mat)
for limb in hide:
geo.pop(limb, None)
cells.append((f"{motion['name']} {i}/{len(norms)}",
@@ -611,7 +640,8 @@ def demo_sheet(folder):
cells = []
for label, figure, flip, palette in variants:
norms, prof, cam, pitch, props = prepare(motion, figure, flip)
_, geo, order, shade = frame_geometry(norms[idx], prof, cam, flip, pitch)
mat = mat_bounds(norms, prof, cam, pitch)
_, geo, order, shade = frame_geometry(norms[idx], prof, cam, flip, pitch, mat)
for limb in hide:
geo.pop(limb, None)
cells.append((f"{motion['name']}{label}",
@@ -109,13 +109,16 @@ struct ExerciseFigureView: View {
let geo = figure.geometry(at: time)
// The floor plane under the elevated camera: a rectangle straddling the
// ground line (a horizontal line is the pitch-zero degenerate case).
let floorHalf = MotionSolver.floorHalfDepth * sin(figure.timeline.pitch * .pi / 180)
let floor = CGRect(x: 16, y: Self.groundY + 4 - floorHalf,
width: Self.designSize.width - 32, height: 2 * floorHalf)
ctx.stroke(Path(roundedRect: floor, cornerRadius: 3), with: .color(.figureGround),
style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
// The exercise mat: a ground-plane quad sized to the motion's footprint,
// rotating with the camera about the figure.
if let floorQuad = geo.floor, let first = floorQuad.first {
var path = Path()
path.addLines(floorQuad)
path.addLine(to: first)
path.closeSubpath()
ctx.stroke(path, with: .color(.figureGround),
style: StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
}
// Equipment behind the figure: scene shapes and cables.
drawBackgroundProps(&ctx, geo)
+40 -6
View File
@@ -163,6 +163,9 @@ struct FigureGeometry {
/// right attach, far offsets included so the bars meet the drawn limbs exactly.
var girdle: [CGPoint]
var pelvisBar: [CGPoint]
/// The exercise mat: a world-space quad on the ground plane, sized to the
/// motion's footprint and rotating with the camera. Nil when no mat was given.
var floor: [CGPoint]?
/// Attach elbow/knee hand (arms: 3 points); hip knee ankle toe (legs: 4).
var limbs: [FigureLimb: [CGPoint]]
/// Parts far-to-near, `"head"` always last (`"spine"`, `"arm_r"`, then `"head"`).
@@ -403,11 +406,14 @@ enum MotionSolver {
/// The standard slightly-elevated viewpoint: the camera pitches down a touch so
/// the floor reads as a plane. Kept 1:1 with the reference renderer's CAMERA_PITCH.
static let defaultPitch: Double = 10
/// Floor plane half-depth; its projected height is `floorHalfDepth · sin(pitch)`.
/// Exercise-mat half-depth (into the screen) and the ground line's canvas y,
/// shared with the reference renderer.
static let floorHalfDepth: Double = 30
static let groundY: Double = 152
static func frameGeometry(_ nf: NormalizedFrame, prof: SkeletonProfile, cam: Double,
pitch: Double = MotionSolver.defaultPitch) -> (NormalizedFrame, FigureGeometry) {
pitch: Double = MotionSolver.defaultPitch,
mat: (lo: Double, hi: Double)? = nil) -> (NormalizedFrame, FigureGeometry) {
let p0 = pose(nf, prof: prof, cam: cam, camPitch: pitch)
var shade: [FigureLimb: Shade] = [:]
for (right, left) in pairs {
@@ -475,12 +481,23 @@ enum MotionSolver {
func attachPoint(_ v: Vec3, _ limb: FigureLimb) -> CGPoint {
scr(v, shade[limb] == .far ? off : .zero)
}
// The exercise mat: a ground-plane quad rotating with the camera about the
// figure's vertical axis (`mat` = footprint bounds in the authored view).
var floor: [CGPoint]?
if let mat {
let yg = -(groundY + 4 - anchor.y)
let rc = Mat3.rotX(pitch).times(Mat3.rotY(-cam))
floor = [(mat.lo, floorHalfDepth), (mat.hi, floorHalfDepth),
(mat.hi, -floorHalfDepth), (mat.lo, -floorHalfDepth)].map { dx, dz in
scr(rc.apply(Vec3(dx - anchor.x, yg, dz)))
}
}
let geo = FigureGeometry(
headCenter: head, headRadius: prof.headR, noseStart: noseStart, noseEnd: noseEnd,
spineStart: pelvis, spineControl: control, spineEnd: neckB,
girdle: [attachPoint(p.shoulderL, .armL), neckB, attachPoint(p.shoulderR, .armR)],
pelvisBar: [attachPoint(p.hipL, .legL), pelvis, attachPoint(p.hipR, .legR)],
limbs: limbs, order: order, shade: shade)
floor: floor, limbs: limbs, order: order, shade: shade)
return (resolved, geo)
}
}
@@ -494,13 +511,29 @@ struct MotionTimeline {
let cam: Double
let pitch: Double
let duration: Double
/// The motion's footprint in the authored view (min/max screen x of every figure
/// point across the key frames, padded) the exercise mat spans it.
let mat: (lo: Double, hi: Double)
init?(motion: ExerciseMotion, profile: SkeletonProfile) {
let cam = motion.camera?.yaw ?? 0
let pitch = motion.camera?.pitch ?? MotionSolver.defaultPitch
let norms = motion.frames.map { MotionSolver.normalize($0) }
guard !norms.isEmpty else { return nil }
let resolved = norms.map { MotionSolver.frameGeometry($0, prof: profile, cam: cam, pitch: pitch).0 }
var resolved: [NormalizedFrame] = []
var lo = Double.infinity, hi = -Double.infinity
for norm in norms {
let (frame, geo) = MotionSolver.frameGeometry(norm, prof: profile, cam: cam, pitch: pitch)
resolved.append(frame)
var xs: [Double] = [Double(geo.headCenter.x) - geo.headRadius,
Double(geo.headCenter.x) + geo.headRadius,
Double(geo.spineStart.x), Double(geo.spineControl.x),
Double(geo.spineEnd.x)]
xs += (geo.girdle + geo.pelvisBar).map { Double($0.x) }
xs += geo.limbs.values.flatMap { $0.map { Double($0.x) } }
lo = min(lo, xs.min() ?? lo)
hi = max(hi, xs.max() ?? hi)
}
let duration = resolved.reduce(0) { $0 + $1.hold + $1.tween }
guard duration > 0 else { return nil }
self.resolved = resolved
@@ -508,6 +541,7 @@ struct MotionTimeline {
self.cam = cam
self.pitch = pitch
self.duration = duration
self.mat = (lo - 12, hi + 12)
}
/// The resolved frame (or eased tween) at wall-clock `time`, looping every
@@ -535,10 +569,10 @@ struct MotionTimeline {
func geometry(at time: Double, yawOffset: Double = 0) -> FigureGeometry {
let frame = frame(at: time)
guard yawOffset != 0 else {
return MotionSolver.frameGeometry(frame, prof: profile, cam: cam, pitch: pitch).1
return MotionSolver.frameGeometry(frame, prof: profile, cam: cam, pitch: pitch, mat: mat).1
}
var posed = MotionSolver.frameGeometry(frame, prof: profile, cam: cam, pitch: pitch).0
posed.pins = [:]
return MotionSolver.frameGeometry(posed, prof: profile, cam: cam + yawOffset, pitch: pitch).1
return MotionSolver.frameGeometry(posed, prof: profile, cam: cam + yawOffset, pitch: pitch, mat: mat).1
}
}