Files
animation/tools/tailor/md_tee_v1.py
T
jeremy 3ba86b2ea8 feat: clothing lane, character sources, and DCC bridges
Bulk import of the working lanes that were living untracked on the PC.

Content:
- characters/  Lena/male body lanes, bakes, texture work, run logs
- clothing/    garment pipeline, configs, gates, contract docs
- garments/    MD-authored garment sources (.zprj/.zpac)
- UAL-Lib/     Universal Animation Library 2 source (.blend/.fbx/.glb)
- tools/       blender_bridge, iclone_bridge, md_bridge, tailor, glm_agent
- docs/, plans/, dev/, .agents/plans/

Repo hygiene:
- .gitattributes: LFS now covers .blend, .zprj, .zpac, .obj, .npy and the
  Reallusion .iAvatar/.ccAvatar/.ccRestore containers. Without this the
  ~3.8 GB in this commit would land as raw blobs. .png/.jpg are left out
  on purpose — ~250 are already tracked raw and converting them would
  rewrite every one without shrinking history.
- .gitignore: exclude /accurig/ (~1 GB AccuRig program files, redistributable
  from Reallusion, nothing authored here) and /dev/null/ (git-lfs hook copies
  dropped by a `>/dev/null` redirect on Windows).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 15:55:43 -07:00

84 lines
3.5 KiB
Python

# Lena tank/tee -- WORKING recipe (verified on Lena's avatar 2026-07-30,
# result: tools/tailor/lena_tee_v1.zprj + lena_tee_v1_garment.fbx).
# Run inside a bridge session:
# python tools/md_bridge.py --file tools/tailor/md_tee_v1.py --timeout 500
#
# Prereq: Lena avatar imported at true scale. If GetAvatarCount() == 0:
# op = ApiTypes.ImportExportOption(); op.scale = 10.0
# op.bAddArrangementPoints = True; op.bAutoTranslate = True
# import_api.ImportFBX(r"...\tools\tailor\avatar\Lena_QuatSkin_Avatar.fbx", op)
# (ImportAvatar() is for .avt files only -- returns False on FBX.)
#
# HARD-WON FACTS (do not rediscover):
# - 2D pattern space: units are mm, +y is UP in the 3D mapping. Straps/neck
# at HIGH y, hem at y=0. (Panels built y-down drape upside-down and tangle
# at the neck -- looked like seam bugs, wasn't.)
# - MD internal 3D unit is mm (gravity default -9800). Blender-exported FBX
# avatars land 10x small -- import with op.scale = 10.
# - CreatePatternWithPoints takes (x, y, type) triples; type 0 = corner.
# Returned id is the pattern index; line i = edge point[i] -> point[i+1].
# - Seams: AddSeamlinePairGroup(patA, lineA, patB, lineB, False, False),
# SAME line index both panels for front/back pairs (cross-pairing sews the
# garment over the face). Whole-edge sewing only -> build the neck gap and
# armholes into the outline as extra points.
# - Placement: SetArrangement(pattern, arrangementIndex) assigns, then
# utility_api.ResetClothArrangement() APPLIES it (ReDrape3DArrangement only
# materializes not-yet-draped cloth). Arrangement indices REGENERATE when
# the avatar changes -- always look up by name.
# - utility_api.Simulate(nFrames) is synchronous; ~1 min per 300 frames.
import os
import tempfile
REPO = r"C:\Users\Jeremy\tinqs\animation"
report = {}
n = pattern_api.GetPatternCount()
for i in range(n - 1, -1, -1):
pattern_api.DeletePatternPiece(i)
# Measurements: chest 1083 mm + ease -> 590 panel; shoulder line 440 wide
# (tips at x 75/515); neck gap 260 (x 165..425); front scoop 140 deep, back
# straight; armhole 165 tall (y 455 down to 290); hem->strap 480.
TOP = 480.0
def panel(scoop, dx, straight_back):
if straight_back:
neck = [(215.0, 455.0), (295.0, 455.0), (375.0, 455.0)]
ny = 455.0
else:
neck = [(215.0, TOP - scoop * 0.75), (295.0, TOP - scoop),
(375.0, TOP - scoop * 0.75)]
ny = TOP
pts = ([(75.0, 455.0), (165.0, ny)] + neck +
[(425.0, ny), (515.0, 455.0),
(590.0, 290.0), (590.0, 0.0), (0.0, 0.0), (0.0, 290.0)])
return pattern_api.CreatePatternWithPoints([(x + dx, y, 0) for (x, y) in pts])
front = panel(140.0, 0.0, False)
back = panel(0.0, 800.0, True)
report["ids"] = [front, back]
# Lines: 0 shoulder_L | 1-4 neckline (open) | 5 shoulder_R | 6 armhole_R
# 7 side_R | 8 hem | 9 side_L | 10 armhole_L
for line in (0, 5, 7, 9):
pattern_api.AddSeamlinePairGroup(front, line, back, line, False, False)
arr = {a["ArrangementName"]: int(a["ArrangementIndex"])
for a in pattern_api.GetArrangementList()}
pattern_api.SetArrangement(front, arr["Body_Front_Center_1"])
pattern_api.SetArrangement(back, arr["Body_Back_Center_1"])
pattern_api.SetArrangementPosition(front, 50, 55, 50)
pattern_api.SetArrangementPosition(back, 0, 55, 50)
utility_api.ResetClothArrangement()
report["sim"] = utility_api.Simulate(300)
utility_api.Refresh3DWindow()
snap = os.path.join(tempfile.gettempdir(), "tinqs_md_tee_final.png")
export_api.ExportSnapshot3D(snap)
report["snap"] = snap
result = report