Merge remote-tracking branch 'n64_models/master'
This commit is contained in:
commit
999da5ac53
1 changed files with 139 additions and 0 deletions
139
pot3d.py
Normal file
139
pot3d.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
# hi this is super hacky and only converts a tiny segment of display lists.
|
||||
# it's really just to get a feel for how the formats work.
|
||||
# after extracting/decompressing OoT, run this script on object_tsubo.
|
||||
# the top of the pot is missing, i know. see the comment above.
|
||||
|
||||
import array
|
||||
import io
|
||||
import struct
|
||||
import sys
|
||||
|
||||
name = "pot"
|
||||
tw, th = 32, 64 # hardcoded texture width and height
|
||||
viscale = 256 # inverted scale, this is arbitrary
|
||||
v_base = 0x1838 # offset to first G_VTX command
|
||||
|
||||
with open(sys.argv[1], "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
f = io.BytesIO(data)
|
||||
|
||||
# hardcoded for a rga5a1 texture at the start of the file:
|
||||
pix = array.array('H', f.read(tw * th * 2))
|
||||
pix.byteswap()
|
||||
rgbs = []
|
||||
for p in pix:
|
||||
r = (p & 0xF800) >> 11
|
||||
g = (p & 0x07C0) >> 6
|
||||
b = (p & 0x003E) >> 1
|
||||
a = p & 1
|
||||
# TODO: round color calculations. or not? i don't imagine the N64 bothers.
|
||||
rgb = (r * 255 // 31, g * 255 // 31, b * 255 // 31)
|
||||
rgbs.append(rgb)
|
||||
|
||||
verts = []
|
||||
texes = []
|
||||
norms = [] # unimplemented
|
||||
polys = []
|
||||
|
||||
vi = 0 # vertex index to offset by (incremented after each chunk)
|
||||
|
||||
f.seek(v_base)
|
||||
opcode = ord(f.read(1))
|
||||
|
||||
while opcode == 0x01: # G_VTX
|
||||
counts = f.read(3)
|
||||
numv = ((counts[0] & 0xF) << 4) | ((counts[1] & 0xF0) >> 4)
|
||||
vbidx = counts[2] // 2 - numv
|
||||
vaddr = struct.unpack(">i", f.read(4))[0]
|
||||
|
||||
back = f.tell()
|
||||
f.seek(vaddr & 0xFFFFFF)
|
||||
|
||||
for i in range(numv):
|
||||
if 0:
|
||||
# colored vertices
|
||||
vertex = struct.unpack(">hhhHhhBBBB", f.read(16))
|
||||
x, y, z, w, tx, ty, r, g, b, a = vertex
|
||||
else:
|
||||
# lit vertices
|
||||
vertex = struct.unpack(">hhhHhhbbbB", f.read(16))
|
||||
x, y, z, w, tx, ty, n, p, q, a = vertex
|
||||
|
||||
pos = (x / viscale, y / viscale, z / viscale)
|
||||
# FIXME: texture coordinates are slightly off
|
||||
tpos = ((tx / 32 / tw), 1 - (ty / 32 / th))
|
||||
verts.append(pos)
|
||||
texes.append(tpos)
|
||||
|
||||
f.seek(back)
|
||||
|
||||
while 1:
|
||||
opcode = ord(f.read(1))
|
||||
if opcode not in (6, 5):
|
||||
break
|
||||
if opcode == 5:
|
||||
indices = struct.unpack('>bbbbbbb', f.read(7))
|
||||
a0, a1, a2, _, _, _, _ = indices
|
||||
atri = a0 // 2 + 1 + vi, a1 // 2 + 1 + vi, a2 // 2 + 1 + vi
|
||||
polys.append(atri)
|
||||
elif opcode == 6:
|
||||
indices = struct.unpack('>bbbbbbb', f.read(7))
|
||||
a0, a1, a2, _, b0, b1, b2 = indices
|
||||
# TODO: assert all indices are in range(32)
|
||||
atri = a0 // 2 + 1 + vi, a1 // 2 + 1 + vi, a2 // 2 + 1 + vi
|
||||
btri = b0 // 2 + 1 + vi, b1 // 2 + 1 + vi, b2 // 2 + 1 + vi
|
||||
polys.append(atri)
|
||||
polys.append(btri)
|
||||
|
||||
vi = len(verts)
|
||||
|
||||
# write the model file
|
||||
with open("{}.obj".format(name), "w") as f:
|
||||
fprint = lambda *args, **kwargs: print(*args, file=f, **kwargs)
|
||||
|
||||
fprint("mtllib {}.mtl".format(name))
|
||||
|
||||
fprint("o {}".format(name))
|
||||
|
||||
for vert in verts:
|
||||
fprint("v", *("{:.8f}".format(v) for v in vert))
|
||||
|
||||
for tex in texes:
|
||||
fprint("vt", *("{:.8f}".format(v) for v in tex))
|
||||
|
||||
#fprint("g {}".format(name))
|
||||
fprint("usemtl {}".format(name))
|
||||
fprint("s off")
|
||||
|
||||
for poly in polys:
|
||||
fprint("f", *("{}/{}".format(i, i) for i in poly))
|
||||
|
||||
# write the material file
|
||||
with open("{}.mtl".format(name), "w") as f:
|
||||
fprint = lambda *args, **kwargs: print(*args, file=f, **kwargs)
|
||||
|
||||
fprint("newmtl {}".format(name))
|
||||
fprint("Ns 0.0")
|
||||
# i don't know what any of these do but they all look terrible
|
||||
fprint("Ka 1.0 1.0 1.0")
|
||||
fprint("Kd 0.8 0.8 0.8")
|
||||
fprint("Ks 0.0 0.0 0.0")
|
||||
fprint("Ke 0.0 0.0 0.0")
|
||||
fprint("d 1.0")
|
||||
fprint("illum 0")
|
||||
|
||||
fprint("map_Kd {}.bmp".format(name))
|
||||
#fprint("map_Ka {}.bmp".format(name))
|
||||
|
||||
# write the texture file
|
||||
with open("{}.bmp".format(name), "wb") as f:
|
||||
f.write(b'BM')
|
||||
# format: 32-bit BGRA
|
||||
# everything else: sane default
|
||||
f.write(struct.pack("<ihhi", len(rgbs) * 4 + 14, 0, 0, 14 + 40))
|
||||
f.write(struct.pack("<iiihhiiiiii", 40, tw, th, 1, 32, 0, 0, 0, 0, 0, 0))
|
||||
for rgb in reversed(rgbs):
|
||||
r, g, b = rgb
|
||||
a = 0xFF
|
||||
f.write(struct.pack("<BBBB", b, g, r, a))
|
Loading…
Reference in a new issue