# Measures left/right UV overlap for arms and legs (mirror-mapping check). extends SceneTree const GLB_PATH := "C:/Users/CAN/tinqs-ltd/tattoo-test/lena_demirrored.glb" const GRID := 256 var skel: Skeleton3D var uvs: PackedVector2Array var vbones: PackedInt32Array var vweights var bind_bone: PackedInt32Array var nverts: int var influences: int 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 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) var mesh = body.mesh if mesh is ImporterMesh: mesh = mesh.get_mesh() var arrays: Array = mesh.surface_get_arrays(0) uvs = arrays[Mesh.ARRAY_TEX_UV] vbones = arrays[Mesh.ARRAY_BONES] vweights = arrays[Mesh.ARRAY_WEIGHTS] nverts = (arrays[Mesh.ARRAY_VERTEX] as PackedVector3Array).size() influences = int(float(vbones.size()) / float(nverts)) var skin: Skin = body.skin 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) _overlap("ARM", ["upperarm_r", "lowerarm_r", "hand_r"], ["upperarm_l", "lowerarm_l", "hand_l"]) _overlap("LEG", ["thigh_r", "calf_r", "foot_r"], ["thigh_l", "calf_l", "foot_l"]) quit() func _mask(bones: Array) -> PackedByteArray: var ids := {} for bn in bones: 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 return mask func _overlap(tag: String, bones_r: Array, bones_l: Array) -> void: var r := _mask(bones_r) var l := _mask(bones_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("%s UV overlap: %d/%d cells (%.0f%%)" % [tag, ov, cr, 100.0 * ov / maxf(cr, 1)])