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>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Which image datablocks exist, and which ones the body material actually SAMPLES.
|
||||
# blender --background --python 16b_images.py -- <blend> [<blend2> ...]
|
||||
import bpy, sys
|
||||
import numpy as np
|
||||
|
||||
for BLEND in sys.argv[sys.argv.index("--") + 1:]:
|
||||
bpy.ops.wm.open_mainfile(filepath=BLEND)
|
||||
print(f"\n===== {BLEND} =====")
|
||||
ob = max([o for o in bpy.data.objects if o.type == 'MESH'],
|
||||
key=lambda o: len(o.data.vertices))
|
||||
print(f"body '{ob.name}' {len(ob.data.vertices)}v materials="
|
||||
f"{[ms.material.name if ms.material else None for ms in ob.material_slots]}")
|
||||
for i in bpy.data.images:
|
||||
b = np.empty(i.size[0] * i.size[1] * 4, dtype=np.float32)
|
||||
try:
|
||||
i.pixels.foreach_get(b)
|
||||
m = b.reshape(-1, 4)[:, :3]
|
||||
stat = f"mean {m.mean(axis=0).round(4)} std {m.std(axis=0).round(4)}"
|
||||
except Exception as e:
|
||||
stat = f"(no pixels: {e})"
|
||||
print(f" IMG '{i.name}' {i.size[0]}x{i.size[1]} packed={bool(i.packed_file)} "
|
||||
f"file='{i.filepath}' {stat}")
|
||||
for ms in ob.material_slots:
|
||||
mat = ms.material
|
||||
if not mat or not mat.node_tree:
|
||||
continue
|
||||
print(f" MAT '{mat.name}':")
|
||||
bsdf = next((n for n in mat.node_tree.nodes if n.type == 'BSDF_PRINCIPLED'), None)
|
||||
for n in mat.node_tree.nodes:
|
||||
if n.type == 'TEX_IMAGE':
|
||||
tgt = []
|
||||
for o in n.outputs:
|
||||
for lk in o.links:
|
||||
tgt.append(f"{lk.to_node.name}.{lk.to_socket.name}")
|
||||
print(f" TEX_IMAGE node '{n.name}' image='{n.image.name if n.image else None}'"
|
||||
f" -> {tgt if tgt else 'UNCONNECTED'}")
|
||||
if bsdf:
|
||||
for sock in ("Base Color", "Normal", "Roughness", "Metallic"):
|
||||
if sock in bsdf.inputs:
|
||||
lk = bsdf.inputs[sock].links
|
||||
src = lk[0].from_node.name if lk else "(unlinked)"
|
||||
if lk and lk[0].from_node.type == 'TEX_IMAGE':
|
||||
src += f" image='{lk[0].from_node.image.name if lk[0].from_node.image else None}'"
|
||||
print(f" BSDF.{sock} <- {src}")
|
||||
print("IMAGES_DONE")
|
||||
Reference in New Issue
Block a user