Skip to content

Instantly share code, notes, and snippets.

@ArdWar
Last active February 23, 2024 08:38
Show Gist options
  • Save ArdWar/8005c155ce03bb75408b35fa0f86e925 to your computer and use it in GitHub Desktop.
Save ArdWar/8005c155ce03bb75408b35fa0f86e925 to your computer and use it in GitHub Desktop.
# Based on Goodjooy/AzurLane-PaintingExtract
# this assumes that the mesh transform is in sorted four line corner pairs
import unitypack, os, re
from unitypack.export import OBJMesh
from PIL import Image, ImageOps
VR = re.compile(r'v ')
TR = re.compile(r'vt ')
SR = re.compile(r' ')
def recon(src, mesh):
sx, sy = src.size
c = map(SR.split, list(filter(TR.match, mesh))[1::2])
p = map(SR.split, list(filter(VR.match, mesh))[1::2])
c = [(round(float(a[1])*sx), round((1-float(a[2]))*sy)) for a in c]
p = [(-int(float(a[1])), int(float(a[2]))) for a in p]
my = max(y for x, y in p)
p = [(x, my-y) for x, y in p[::2]]
cp = [(l+r, p) for l, r, p in zip(c[::2], c[1::2], p)]
ox, oy = zip(*[(r-l+p, b-t+q) for (l, t, r, b), (p, q) in cp])
out = Image.new('RGBA', (max(ox), max(oy)))
for c, p in cp: out.paste(src.crop(c), p)
return out
for i in os.scandir(os.getcwd()+'\.'):
if i.is_file() and len(i.name.split('.'))==1:
with open(os.getcwd()+'\\'+i.name, "rb") as f:
try: bundle = unitypack.load(f)
except: continue
for asset in bundle.assets:
for id, obj in asset.objects.items():
if obj.type == "Mesh":
try: mesh = OBJMesh(obj.read()).export().splitlines()
except: continue
elif obj.type == "Texture2D":
try: img = ImageOps.flip(obj.read().image)
except: continue
try:
recon(img, mesh).save(os.getcwd()+'\\'+i.name+'.png', optimize=True)
del img, mesh
except: continue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment