"""Scratch test: build the sculpted bodies alone and render them in clay, to judge the anatomy before plates go on.""" import bpy, sys, os from mathutils import Vector, Matrix HERE = os.path.dirname(os.path.abspath(__file__)); sys.path.insert(0, HERE) from lib_geo import Builder, finish import convict_parts as cp OUT = os.path.join(os.path.dirname(HERE), 'previews'); os.makedirs(OUT, exist_ok=True) ARGS = sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else [] ga = float(ARGS[0]) if ARGS else 1.0; gl = float(ARGS[1]) if len(ARGS) > 1 else 1.0 bpy.ops.wm.read_factory_settings(use_empty=True); sc = bpy.context.scene J = cp.make_joints(); BONES = [b[0] for b in cp.bone_table(J)] clay = bpy.data.materials.new('clay'); clay.use_nodes = True b = next(n for n in clay.node_tree.nodes if n.type == 'BSDF_PRINCIPLED'); b.inputs['Base Color'].default_value = (.55, .55, .56, 1); b.inputs['Roughness'].default_value = .55 MAT = {m: clay for m in cp.MATS} B = Builder(BONES, cp.MATS); B.wfn = cp.spine_w bvh, low = cp.body('torso', J); B.add_mesh(low, 'torso_base') for sg in (1, -1): with B.side(sg): B.wfn = cp.hinge_w(B, J['EL'], J['DF'], 'upperarm', 'lowerarm'); B.add_mesh(cp.body('arm', J, ga)[1], 'arm_base', J['FU']) B.wfn = cp.hinge_w(B, J['KNEE'], J['DC'], 'thigh', 'calf'); B.add_mesh(cp.body('leg', J, gl)[1], 'leg_base', J['FT']) ob, a = finish(B, 'bases', None, sc.collection, MAT); print('AUDIT', a['verts'], a['quads'], a['tris'], a['ngons'], a['open_edges']) w = bpy.data.worlds.new('w'); sc.world = w; w.use_nodes = True; w.node_tree.nodes['Background'].inputs[0].default_value = (.5, .5, .5, 1); w.node_tree.nodes['Background'].inputs[1].default_value = .6 for nm, loc, pw in (('k', (-3, -5, 4), 1500), ('f', (4, -4, 2), 500), ('r', (2, 5, 3), 1500)): ld = bpy.data.lights.new(nm, 'AREA'); ld.energy = pw; ld.size = 4; o = bpy.data.objects.new(nm, ld); sc.collection.objects.link(o); o.location = loc o.rotation_euler = (Vector((0, 0, 1)) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler() cd = bpy.data.cameras.new('c'); cam = bpy.data.objects.new('c', cd); sc.collection.objects.link(cam); sc.camera = cam; cd.lens = 85 sc.render.engine = 'BLENDER_EEVEE'; sc.render.resolution_x = 700; sc.render.resolution_y = 1150 import numpy as np ps = [] for nm, loc in (('front', (0, -7.2, 1.0)), ('q', (-4.6, -5.4, 1.2)), ('side', (-7.2, 0, 1.0)), ('back', (1.5, 7.0, 1.2))): cam.location = loc; cam.rotation_euler = (Vector((0, 0, .93)) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler() p = os.path.join(OUT, f'_base_{nm}.png'); sc.render.filepath = p; bpy.ops.render.render(write_still=True); ps.append(p) arrs = [] for p in ps: im = bpy.data.images.load(p); wd, ht = im.size; a_ = np.empty(wd * ht * 4, dtype=np.float32); im.pixels.foreach_get(a_); arrs.append(a_.reshape(ht, wd, 4)); bpy.data.images.remove(im); os.remove(p) a_ = np.concatenate(arrs, axis=1); im = bpy.data.images.new('s', a_.shape[1], a_.shape[0]); im.pixels.foreach_set(a_.ravel()); im.file_format = 'PNG' im.filepath_raw = os.path.join(OUT, f'_base_g{ga}.png'); im.save(); print('SHEET', im.filepath_raw)