# Measurements for the full-body Lena bake: bone heights, leg UV overlap, # torso half-width, and fabric (bra/underwear) color stats. extends SceneTree const GLB_PATH := "C:/Users/CAN/tinqs-ltd/ariki-game/assets/quaternius/derived-bodies/Ariki_Female_QuatSkin.glb" const GRID := 256 func _init() -> void: var doc := GLTFDocument.new() var state := GLTFState.new() if doc.append_from_file(GLB_PATH, state) != OK: quit(1) return var scene := doc.generate_scene(state) var skel: Skeleton3D = null var body: Node = null var stack: Array = [scene] while not stack.is_empty(): var n: Node = stack.pop_back() if n is Skeleton3D and skel == null: skel = n if (n is MeshInstance3D or n.get_class() == "ImporterMeshInstance3D") \ and String(n.name).to_lower().contains("lena"): body = n for c in n.get_children(): stack.push_back(c) for bn in ["neck_01", "spine_03", "spine_02", "spine_01", "pelvis", "thigh_r", "calf_r", "foot_r", "clavicle_r"]: print("bone %s: %s" % [bn, skel.get_bone_global_rest(skel.find_bone(bn)).origin]) var mesh = body.mesh if mesh is ImporterMesh: mesh = mesh.get_mesh() var arrays: Array = mesh.surface_get_arrays(0) var verts: PackedVector3Array = arrays[Mesh.ARRAY_VERTEX] var uvs: PackedVector2Array = arrays[Mesh.ARRAY_TEX_UV] var normals: PackedVector3Array = arrays[Mesh.ARRAY_NORMAL] var vbones: PackedInt32Array = arrays[Mesh.ARRAY_BONES] var vweights = arrays[Mesh.ARRAY_WEIGHTS] var nverts := verts.size() var influences := int(float(vbones.size()) / float(nverts)) var skin: Skin = body.skin var bind_bone := PackedInt32Array() for i in skin.get_bind_count(): var b := skin.get_bind_bone(i) if b < 0: b = skel.find_bone(skin.get_bind_name(i)) bind_bone.append(b) # leg UV overlap (same method that showed 100% for arms) var sets := {} for side in [["r", ["thigh_r", "calf_r", "foot_r"]], ["l", ["thigh_l", "calf_l", "foot_l"]]]: var ids := {} for bn in side[1]: ids[skel.find_bone(bn)] = true var binds := {} for i in bind_bone.size(): if ids.has(bind_bone[i]): binds[i] = true var mask := PackedByteArray() mask.resize(GRID * GRID) for v in nverts: var w := 0.0 for k in influences: if binds.has(vbones[v * influences + k]): w += vweights[v * influences + k] if w > 0.3: var gx := clampi(int(uvs[v].x * GRID), 0, GRID - 1) var gy := clampi(int(uvs[v].y * GRID), 0, GRID - 1) mask[gy * GRID + gx] = 1 sets[side[0]] = mask var r: PackedByteArray = sets["r"] var l: PackedByteArray = sets["l"] var cr := 0 var ov := 0 for i in GRID * GRID: if r[i] == 1: cr += 1 if l[i] == 1: ov += 1 print("LEG UV overlap: %d/%d cells (%.0f%%)" % [ov, cr, 100.0 * ov / maxf(cr, 1)]) # arm weights (to exclude arms when measuring torso width) var arm_ids := {} for bn in ["upperarm_l", "lowerarm_l", "hand_l", "upperarm_r", "lowerarm_r", "hand_r"]: arm_ids[skel.find_bone(bn)] = true var arm_binds := {} for i in bind_bone.size(): if arm_ids.has(bind_bone[i]): arm_binds[i] = true # torso extents + fabric stats: front-facing verts in the chest band var mat: Material = mesh.surface_get_material(0) var img: Image = (mat as BaseMaterial3D).albedo_texture.get_image() img.clear_mipmaps() img.convert(Image.FORMAT_RGBA8) var tw := img.get_width() var th := img.get_height() var neck_y: float = skel.get_bone_global_rest(skel.find_bone("neck_01")).origin.y var pelvis_y: float = skel.get_bone_global_rest(skel.find_bone("pelvis")).origin.y var maxx_front := 0.0 var maxx_back := 0.0 var n_fab := 0 var n_skin := 0 var sat_fab := 0.0 var sat_skin := 0.0 var lum_fab := 0.0 var lum_skin := 0.0 for v in nverts: var aw := 0.0 for k in influences: if arm_binds.has(vbones[v * influences + k]): aw += vweights[v * influences + k] if aw > 0.3: continue var p := verts[v] if p.y < pelvis_y or p.y > neck_y: continue if normals[v].z > 0.25: maxx_front = maxf(maxx_front, absf(p.x)) elif normals[v].z < -0.25: maxx_back = maxf(maxx_back, absf(p.x)) var px := clampi(int(uvs[v].x * tw), 0, tw - 1) var py := clampi(int(uvs[v].y * th), 0, th - 1) var c := img.get_pixel(px, py) var mx := maxf(c.r, maxf(c.g, c.b)) var mn := minf(c.r, minf(c.g, c.b)) var sat := (mx - mn) / maxf(mx, 0.001) var lum := (c.r + c.g + c.b) / 3.0 # crude split: bra/underwear are pale + desaturated if sat < 0.15 and lum > 0.55: n_fab += 1 sat_fab += sat lum_fab += lum else: n_skin += 1 sat_skin += sat lum_skin += lum print("torso band y %.2f..%.2f half-width front=%.3f back=%.3f" % [pelvis_y, neck_y, maxx_front, maxx_back]) print("fabric-ish verts: %d (avg sat %.3f lum %.3f)" % [n_fab, sat_fab / maxf(n_fab, 1), lum_fab / maxf(n_fab, 1)]) print("skin-ish verts: %d (avg sat %.3f lum %.3f)" % [n_skin, sat_skin / maxf(n_skin, 1), lum_skin / maxf(n_skin, 1)]) quit()