feat(characters): ship lena_leafbikini_base_v01 as female Ariki default
Lena with the leaf bikini sculpted into the mesh — a separate character descending from her own Tripo original, not a lena_base_v02. Full-res (1,029,360 v) at 1.777 m, now Ariki_Female_QuatSkin.glb + LOD1. First nearest-surface graft in the rig lane: AccuRig had to be fed a 20:1 decimated bait, so the index-exact graft the two earlier ships used was impossible. The bait recovers AccuRig's 9.346 mm offset in closed form, which makes it a required input forever — copied into the ship folder, and rig-work's "disposable" rule amended to say so. Mesh moved 0 mm, 0 unweighted verts. lena_base_v01 goes superseded, not rolled-back: she lost the default slot but Ariki_Female_QuatSkin_Nude.glb is untouched, so per rule 9 her folder stays put. Also lands the leaf-cut lane (work/lena_leafbikini): hue-keyed seam detection that removes the leaf shell and leaves both holes open by request, registered as a lane milestone with its sha256. Corrects the rig-work trap note — baits do carry embedded textures; it is AccuRig that strips them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# lena_leafbikini lane, stage 06: open a lane mesh in the Blender GUI, framed and shaded.
|
||||
#
|
||||
# blender --python 06_open_in_blender.py -- <mesh.glb>
|
||||
#
|
||||
# Runs inside a GUI session, NOT --background, and deliberately NOT --factory-startup: the
|
||||
# TinqsBlenderBridge autostarts from scripts/startup (tools/install_blender_bridge.ps1), and
|
||||
# factory startup would skip it, leaving the session undriveable from the terminal afterwards.
|
||||
#
|
||||
# TWO THINGS THIS SCRIPT LEARNED THE HARD WAY, both consequences of `--python` running BEFORE
|
||||
# Blender's window exists:
|
||||
# 1. `bpy.context.screen` is None at this point, so any viewport setup here dies with
|
||||
# AttributeError. All of it is deferred onto an app timer, which first fires once the UI
|
||||
# is up and can therefore see the 3D View.
|
||||
# 2. `bpy.ops.wm.read_homefile()` kills the bridge — the startup module has already
|
||||
# registered its socket server by now, and reloading the file takes it down with no
|
||||
# autostart to bring it back. The default cube/light/camera are removed by hand instead.
|
||||
#
|
||||
# Material Preview, not Solid: the point of looking at this file is the boundary between the
|
||||
# holes and her skin, and in Solid shading the baked leaf contact shadows in the albedo are
|
||||
# invisible — which is half of what makes the rim read the way it does.
|
||||
import bpy, sys, os
|
||||
|
||||
GLB = os.path.abspath(sys.argv[sys.argv.index("--") + 1:][0])
|
||||
|
||||
for o in list(bpy.data.objects):
|
||||
if o.name in {"Cube", "Light", "Camera"}:
|
||||
bpy.data.objects.remove(o, do_unlink=True)
|
||||
|
||||
bpy.ops.import_scene.gltf(filepath=GLB)
|
||||
body = max([o for o in bpy.data.objects if o.type == 'MESH'], key=lambda o: len(o.data.vertices))
|
||||
bpy.context.view_layer.objects.active = body
|
||||
for o in bpy.data.objects:
|
||||
o.select_set(o is body)
|
||||
print(f"[open] {os.path.basename(GLB)}: {len(body.data.vertices)}v {len(body.data.polygons)}f",
|
||||
flush=True)
|
||||
|
||||
|
||||
def setup_viewport():
|
||||
"""Fires once, after the window exists."""
|
||||
screen = getattr(bpy.context, "screen", None)
|
||||
if screen is None:
|
||||
return 0.25 # UI not up yet — ask the timer to call again
|
||||
for area in screen.areas:
|
||||
if area.type != 'VIEW_3D':
|
||||
continue
|
||||
sp = area.spaces.active
|
||||
sp.shading.type = 'MATERIAL'
|
||||
sp.shading.use_scene_lights = False
|
||||
sp.shading.use_scene_world = False
|
||||
sp.overlay.show_floor = False
|
||||
sp.overlay.show_axis_x = sp.overlay.show_axis_y = False
|
||||
sp.overlay.show_relationship_lines = False
|
||||
sp.clip_start = 0.001
|
||||
sp.clip_end = 100.0
|
||||
region = next((r for r in area.regions if r.type == 'WINDOW'), None)
|
||||
if region:
|
||||
with bpy.context.temp_override(area=area, region=region, space_data=sp):
|
||||
# BACK, not FRONT. These lane GLBs are exported with export_yup=True and come
|
||||
# back in facing +Y, so Blender's FRONT view (looking from -Y) puts you behind
|
||||
# her — which is the wrong side for judging a cut that is mostly on her front.
|
||||
bpy.ops.view3d.view_axis(type='BACK')
|
||||
bpy.ops.view3d.view_selected()
|
||||
print("[open] viewport ready — Material Preview, framed on her front", flush=True)
|
||||
return None # done; unregister
|
||||
|
||||
|
||||
bpy.app.timers.register(setup_viewport, first_interval=0.5)
|
||||
Reference in New Issue
Block a user