123 lines
5.7 KiB
Python
123 lines
5.7 KiB
Python
|
|
# Armhole-scoop sweep for topTest1. Diagnostic, exports nothing.
|
||
|
|
#
|
||
|
|
# python tools/md_bridge.py --file tools/tailor/md_pari_armsweep.py --timeout 880
|
||
|
|
#
|
||
|
|
# HYPOTHESIS (Jeremy's): the persistent diagonal crease across the back is surplus
|
||
|
|
# WIDTH bunching where the two panels meet. The numbers say he's right, but not at
|
||
|
|
# the bust or hem — those are matched:
|
||
|
|
# bust 570 + 510 = 1080 vs bust 1083 (matched)
|
||
|
|
# hem 380 + 320 = 700 vs waist 675 (+25 ease)
|
||
|
|
# The surplus is ABOVE the bust. The panels stay near-full width up to the armhole
|
||
|
|
# while the body narrows, giving ~968 mm of cloth around a much smaller torso at
|
||
|
|
# underarm height. And the side seam only runs y 0..185, so above that the front and
|
||
|
|
# back edges are FREE — nothing stops the surplus from overlapping and pushing a
|
||
|
|
# diagonal fold across the back, which is exactly where the crease sits.
|
||
|
|
#
|
||
|
|
# Fix under test: a concave ARMHOLE SCYE. Insert one mid-point per armhole, pulled
|
||
|
|
# inward by ARM, so the upper panel narrows without touching bust width, hem taper,
|
||
|
|
# or strap position (moving the straps would re-expose the body's baked-in bra
|
||
|
|
# straps, which is the whole reason the straps exist).
|
||
|
|
#
|
||
|
|
# Inserting points SHIFTS THE LINE INDICES, so indices are computed here rather than
|
||
|
|
# hardcoded — hardcoded 0/5/7/9 has bitten this recipe twice already.
|
||
|
|
#
|
||
|
|
# 4 values x Simulate(250) ~= 4 min. PLAIN so shape is judged, not motif.
|
||
|
|
import os
|
||
|
|
import shutil
|
||
|
|
import tempfile
|
||
|
|
|
||
|
|
AVATAR_FBX = r"C:\Users\Jeremy\tinqs\animation\tools\tailor\avatar\Lena_QuatSkin_Avatar.fbx"
|
||
|
|
ZFAB = r"C:\Users\Public\Documents\MarvelousDesigner\New Assets\Fabric\(Default for Simulation).zfab"
|
||
|
|
|
||
|
|
W_FRONT, W_BACK = 570.0, 510.0
|
||
|
|
TOP = 350.0
|
||
|
|
SCOOP_FRONT, SCOOP_BACK = 105.0, 15.0
|
||
|
|
SIDE_Y = 185.0
|
||
|
|
TAPER = 95.0
|
||
|
|
ARM_H = 70.0 # mid-point sits ARM_H above SIDE_Y, i.e. y = 255
|
||
|
|
SWEEP = [0.0, 30.0, 55.0, 80.0] # mm pulled inward per side. 0 == current shape.
|
||
|
|
SIDE_FLAGS = (True, True)
|
||
|
|
SHOULDER_FLAGS = (False, False)
|
||
|
|
ARR_X = 50
|
||
|
|
|
||
|
|
report = {"combos": {}, "hypothesis": "surplus width ABOVE the bust, free edges above SIDE_Y"}
|
||
|
|
|
||
|
|
def build(width, scoop, dx, arm):
|
||
|
|
"""Return (pattern_id, idx) where idx names the line indices we must sew."""
|
||
|
|
c = width / 2.0
|
||
|
|
pts = [(c - 210.0, TOP - 25.0), # 0 strapL_outer
|
||
|
|
(c - 120.0, TOP), # 1 strapL_inner line0 = SHOULDER_L
|
||
|
|
(c - 70.0, TOP - scoop * 0.75), # 2 neck
|
||
|
|
(c, TOP - scoop), # 3 neck
|
||
|
|
(c + 70.0, TOP - scoop * 0.75), # 4 neck
|
||
|
|
(c + 120.0, TOP), # 5 strapR_inner line5 = SHOULDER_R
|
||
|
|
(c + 210.0, TOP - 25.0)] # 6 strapR_outer
|
||
|
|
if arm:
|
||
|
|
pts.append((width - arm, SIDE_Y + ARM_H)) # 7 armhole R mid (concave scye)
|
||
|
|
pts += [(width, SIDE_Y), # sideR_top
|
||
|
|
(width - TAPER, 0.0), # hemR
|
||
|
|
(TAPER, 0.0), # hemL
|
||
|
|
(0.0, SIDE_Y)] # sideL_top
|
||
|
|
if arm:
|
||
|
|
pts.append((arm, SIDE_Y + ARM_H)) # armhole L mid
|
||
|
|
# line i runs pts[i] -> pts[i+1]; derive the seam indices from the layout
|
||
|
|
n_arm = 1 if arm else 0
|
||
|
|
side_r = 6 + n_arm + 1 # sideR_top -> hemR
|
||
|
|
hem = side_r + 1
|
||
|
|
side_l = hem + 1 # hemL -> sideL_top
|
||
|
|
idx = {"shoulder_l": 0, "shoulder_r": 5, "side_r": side_r, "side_l": side_l,
|
||
|
|
"hem": hem, "n_points": len(pts)}
|
||
|
|
pid = pattern_api.CreatePatternWithPoints([(x + dx, y, 0) for (x, y) in pts])
|
||
|
|
return pid, idx
|
||
|
|
|
||
|
|
for arm in SWEEP:
|
||
|
|
key = "arm%02d" % int(arm)
|
||
|
|
utility_api.NewProject()
|
||
|
|
op = ApiTypes.ImportExportOption()
|
||
|
|
op.scale = 10.0
|
||
|
|
op.bAddArrangementPoints = True
|
||
|
|
op.bAutoTranslate = True
|
||
|
|
import_api.ImportFBX(AVATAR_FBX, op)
|
||
|
|
|
||
|
|
pf, ixf = build(W_FRONT, SCOOP_FRONT, 0.0, arm)
|
||
|
|
pb, ixb = build(W_BACK, SCOOP_BACK, 900.0, arm)
|
||
|
|
|
||
|
|
pattern_api.AddSeamlinePairGroup(pf, ixf["shoulder_l"], pb, ixb["shoulder_l"], *SHOULDER_FLAGS)
|
||
|
|
pattern_api.AddSeamlinePairGroup(pf, ixf["shoulder_r"], pb, ixb["shoulder_r"], *SHOULDER_FLAGS)
|
||
|
|
pattern_api.AddSeamlinePairGroup(pf, ixf["side_r"], pb, ixb["side_r"], *SIDE_FLAGS)
|
||
|
|
pattern_api.AddSeamlinePairGroup(pf, ixf["side_l"], pb, ixb["side_l"], *SIDE_FLAGS)
|
||
|
|
|
||
|
|
# Verify the computed indices actually point at the edges we think: shoulders
|
||
|
|
# ~93 mm, sides ~208 mm. If these drift, the index math is wrong, not the cloth.
|
||
|
|
lens = {k: [round(pattern_api.GetLineLength(pf, ixf[k]), 1),
|
||
|
|
round(pattern_api.GetLineLength(pb, ixb[k]), 1)]
|
||
|
|
for k in ("shoulder_l", "shoulder_r", "side_r", "side_l")}
|
||
|
|
|
||
|
|
fab = fabric_api.AddFabric(ZFAB)
|
||
|
|
for p in (pf, pb):
|
||
|
|
pattern_api.SetPatternPieceFabricIndex(p, fab)
|
||
|
|
|
||
|
|
arr = {a["ArrangementName"]: int(a["ArrangementIndex"])
|
||
|
|
for a in pattern_api.GetArrangementList()}
|
||
|
|
pattern_api.SetArrangement(pf, arr["Body_Front_Center_1"])
|
||
|
|
pattern_api.SetArrangement(pb, arr["Body_Back_Center_1"])
|
||
|
|
pattern_api.SetArrangementPosition(pf, ARR_X, 55, 50)
|
||
|
|
pattern_api.SetArrangementPosition(pb, ARR_X, 55, 50)
|
||
|
|
utility_api.ResetClothArrangement()
|
||
|
|
|
||
|
|
ok = utility_api.Simulate(250)
|
||
|
|
utility_api.Refresh3DWindow()
|
||
|
|
|
||
|
|
shots = export_api.ExportTurntableImages(4)
|
||
|
|
saved = {}
|
||
|
|
for i, label in ((0, "front"), (2, "back")):
|
||
|
|
if i < len(shots) and os.path.exists(shots[i]):
|
||
|
|
dst = os.path.join(tempfile.gettempdir(),
|
||
|
|
"tinqs_armsweep_%s_%s.png" % (key, label))
|
||
|
|
shutil.copyfile(shots[i], dst)
|
||
|
|
saved[label] = dst
|
||
|
|
report["combos"][key] = {"sim": ok, "arm": arm, "idx_front": ixf,
|
||
|
|
"seam_lengths": lens, "shots": saved}
|
||
|
|
|
||
|
|
result = report
|