# Piupiu v3 — re-cut for leg clearance. # # python tools/md_bridge.py --file tools/tailor/md_piupiu_v3.py --timeout 600 # # WHY v3 (v2 stays untouched; backup in tools/tailor/backup/2026-07-31-pre-v3/): # v2's waist edge is 500 mm/panel = 1000 mm total, against Lena's 1095 mm hips — # cut TIGHTER than the hip it must pass over, so it drapes as a taut pencil wrap # on the thighs. Downstream measures the result: G3 finds 8 mm penetration AT # REST, and G5 finds 216-231 verts up to 8.5 cm deep across Idle/Walk, because # `weights: "dress"` leaves the sub-hip skirt pelvis-only — the thigh swings, the # skirt does not. # # WHAT THIS CHANGES vs md_piupiu.py: # 1. Waist cut to hip + ease (570/panel = 1140 mm) instead of hip - 95 mm, so the # skirt is not stretched over the hips, and waist ELASTIC holds it up instead # of tension. Doctrine: elastic mid-settle, never from frame 0. # 2. Hem flared 1640 -> 2300 mm circumference for standoff at the knee. # 3. Additional Thickness - Collision (10 mm) so MD physically resolves the cloth # standing off the skin. This is strictly better than the downstream `fit` # normal-push (shell_mm 4 / offset_mm 3), which self-intersects in concave # regions — i.e. exactly between Lena's touching thighs. # # HONEST LIMIT: a knee-length pelvis-locked skirt cannot be fixed by clearance # alone. Hem target 0.45 m sits 0.495 m below the hip pivot, so a 30 deg hip # flexion sweeps the leg ~25 cm forward — more than any believable piupiu # silhouette clears. This buys the runtime skirt-bone capsules (`weights: # "skirt_bones"`, the concurrent session's lane) room to work, and it should # eliminate the rest-pose failure outright. It is not a solo fix. # # QC targets (unchanged, tools/tailor/qc_placement.py verifies): # waistband top 1.05 m +-3 cm, hem 0.45 m +-4 cm (just below knee) # G1 measured v2 at +8 cm / +14 cm off these, so v3 should improve placement too. import os import tempfile # ── parameters — the whole point of this block is one-edit iteration ────────── W_TOP = 570.0 # mm per panel at the waist. x2 = 1140 = hip 1095 + 45 ease. W_HEM = 1150.0 # mm per panel at the hem. x2 = 2300 (v2 was 1640). HEIGHT = 600.0 # waist 1.05 m -> hem 0.45 m. COLLISION_MM = 10.0 # Additional Thickness - Collision. 0 disables. ELASTIC_TOTAL = 360.0 # mm per panel to cinch the waist edge to. x2 = 720 vs # measured waist 675. None disables elastic. ZFAB = r"C:\Users\Public\Documents\MarvelousDesigner\New Assets\Fabric\(Default for Simulation).zfab" # If the flare collapses into vertical folds, swap to a stiff woven — a real # piupiu is dried flax strands and holds a bell. Stiffest stock presets: # V2_Woven_Canvas_1.zfab < V2_Woven_Denim_1.zfab < V2_Non-Fabric_Tyvek_1.zfab EXPORT = False # flip to True only once a snapshot looks right. VERSION = "v3" AVATAR_FBX = r"C:\Users\Jeremy\tinqs\animation\tools\tailor\avatar\Lena_QuatSkin_Avatar.fbx" TEX = r"C:\Users\Jeremy\tinqs\animation\tools\tailor\textures\piupiu.png" # dpi 43.3 = 600 mm OUT = r"C:\Users\Jeremy\tinqs\animation\tools\tailor" SHOTS = r"C:\Users\Jeremy\tinqs\animation\tools\tailor\screenshots" report = {"params": {"W_TOP": W_TOP, "W_HEM": W_HEM, "HEIGHT": HEIGHT, "COLLISION_MM": COLLISION_MM, "ELASTIC_TOTAL": ELASTIC_TOTAL, "zfab": os.path.basename(ZFAB), "EXPORT": EXPORT}} utility_api.NewProject() # NB: this deletes the avatar — import after. op = ApiTypes.ImportExportOption() op.scale = 10.0 # Blender-exported FBX avatars import 10x small. op.bAddArrangementPoints = True # without this there is nowhere to hang cloth. op.bAutoTranslate = True report["avatar"] = import_api.ImportFBX(AVATAR_FBX, op) # Trapezoid, hem at y=0 and waist at y=HEIGHT: 2D y+ maps to UP in 3D. Drafting # y-down drapes the garment upside-down over the head. # Line indices that follow from this point order: 0 = waist, 1 = side, 2 = hem, # 3 = side. Side seams pair the SAME index on both panels with (False, False). def panel(dx): inset = (W_HEM - W_TOP) / 2.0 pts = [(inset, HEIGHT), (inset + W_TOP, HEIGHT), (W_HEM, 0.0), (0.0, 0.0)] return pattern_api.CreatePatternWithPoints([(x + dx, y, 0) for (x, y) in pts]) sf = panel(0.0) sb = panel(W_HEM + 400.0) report["ids"] = [sf, sb] pattern_api.AddSeamlinePairGroup(sf, 1, sb, 1, False, False) pattern_api.AddSeamlinePairGroup(sf, 3, sb, 3, False, False) fab = fabric_api.AddFabric(ZFAB) # never reuse index 0 fabric_api.SetBaseTextureMapImageGivenFilePath(TEX, fab) # path is arg0 for p in (sf, sb): pattern_api.SetPatternPieceFabricIndex(p, fab) # Collision thickness before the drape, so the settle resolves with it. if COLLISION_MM: try: for p in (sf, sb): pattern_api.SetAddlThicknessCollision(p, COLLISION_MM) report["collision"] = [pattern_api.GetAddlThicknessCollisionValue(p) for p in (sf, sb)] except Exception as e: report["collision_error"] = "%s: %s" % (type(e).__name__, e) arr = {a["ArrangementName"]: int(a["ArrangementIndex"]) for a in pattern_api.GetArrangementList()} # indices regenerate per import pattern_api.SetArrangement(sf, arr["Body_Front_Waist"]) pattern_api.SetArrangement(sb, arr["Body_Back_Waist"]) pattern_api.SetArrangementPosition(sf, 50, 30, 50) pattern_api.SetArrangementPosition(sb, 0, 30, 50) pattern_api.SetPatternStrengthen(sf, True) # stiff so cloth wraps, not crumples pattern_api.SetPatternStrengthen(sb, True) utility_api.ResetClothArrangement() # SetArrangement only assigns # The diagnostic that unsticks everything: where the panels actually start, before # physics muddies it. Zero simulation frames. utility_api.Refresh3DWindow() utility_api.SetCamViewPoint(2) # front view, comparable shots pre = os.path.join(tempfile.gettempdir(), "tinqs_md_piupiu_%s_presim.png" % VERSION) export_api.ExportSnapshot3D(pre) report["presim_snap"] = pre report["sim1"] = utility_api.Simulate(250) # main settle, still stiff # Elastic mid-settle: applied before the cloth has wrapped it cinches off one hip. if ELASTIC_TOTAL: try: for p in (sf, sb): pattern_api.SetPatternPieceElastic(p, 0, True) pattern_api.SetPatternPieceElasticTotalLength(p, 0, ELASTIC_TOTAL) report["sim_elastic"] = utility_api.Simulate(80) except Exception as e: report["elastic_error"] = "%s: %s" % (type(e).__name__, e) pattern_api.SetPatternStrengthen(sf, False) # relax into natural folds pattern_api.SetPatternStrengthen(sb, False) report["sim2"] = utility_api.Simulate(50) utility_api.Refresh3DWindow() utility_api.SetCamViewPoint(2) snap = os.path.join(SHOTS, "lena_piupiu_%s.png" % VERSION) export_api.ExportSnapshot3D(snap) # required repo review render report["snap"] = snap if EXPORT: base = os.path.join(OUT, "lena_piupiu_%s" % VERSION) eop = ApiTypes.ImportExportOption() eop.bExportGarment = True eop.bExportAvatar = False report["zprj"] = export_api.ExportZPrj(base + ".zprj") report["fbx"] = export_api.ExportFBX(base + "_garment.fbx", eop) report["obj"] = export_api.ExportOBJ(base + "_garment.obj", eop) report["zpac"] = export_api.ExportZPac(base + ".zpac") result = report