In this post I will write a script that reads the uklogo.pak file.
The first four bytes of the uklogo.pak file are an integer while the rest of the file is the red, green and blue pixel data.
The pixel data is zlib compressed and the integer at the start of the file gives the size of the pixel data when it is decompressed.
The pixel data is stored as 24 bit colour which means one byte for each colour.
The uklogo.pak graphic has dimensions (width x height) 512px x 256px and black pixels (r=0,g=0,b=0) are transparent when the title is displayed in game.
With this information we can read the uklogo.pak and visualise it in Metasequoia.
Firstly use the Primitive command to create a plane in Metasequoia with the following properties.
Change the colour of the material used for the plane to black.
Enter the following Python script into Metasequoia’s Script Editor. The Script Editor is only available from the Panel menu in registered copies of Metasequoia.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Metasequoia 4 Python script | |
# Title | |
''' | |
Reads uklogo.pak from Tomb Raider games. | |
''' | |
# imports | |
# import Python's os.path module so can extract filename | |
# and filename extension from full path | |
import os.path | |
#import zlib to decompress pixel data | |
import zlib | |
#import module to read binary structures | |
import struct | |
#import io to use file methods on data in memory | |
import io | |
# global variables | |
doc = MQSystem.getDocument() | |
# function definitions | |
def mqprint(message): | |
try: | |
print(message) | |
except: | |
MQSystem.println(repr(message)) | |
return | |
def readFile(filepath): | |
with open(filepath, "rb") as f: | |
d = f.read(4) | |
size, = struct.unpack('I',d) | |
mqprint(size) | |
comp_data = f.read() | |
uncomp_data = zlib.decompress(comp_data) | |
return uncomp_data | |
# main script function | |
def main(): | |
# create the OpenFile dialog as a child control of Metasequoia | |
od = MQWidget.OpenFileDialog(MQWidget.getMainWindow()) | |
od.addFilter("TR4 pak files (*.pak)|*.pak") | |
# apparently good practise to always have All Files option | |
od.addFilter("All Files (*.*)|*.*") | |
# show the dialog | |
if od.execute(): | |
# user selected a file and clicked ok | |
# store path string in variable named f | |
f = od.filename | |
# extract file's extension using an os.path function | |
path,ext = os.path.splitext(f) | |
if ext.lower() in [".pak"]: | |
# correct extension so extract filename and store in name | |
path,name = os.path.split(f) | |
# print path to file | |
mqprint(f) | |
# read the file | |
data = readFile(f) | |
g=io.BytesIO(data) | |
matlist=[] | |
k=0 | |
msg="Have you created a 512 x 256 segmented plane?" | |
if doc.numObject==0: | |
mqprint("No object. "+msg) | |
return | |
ob=doc.object[doc.currentObjectIndex] | |
if ob.numFace<(512*256): | |
mqprint("Too few faces. "+msg) | |
return | |
for i in range(256): | |
for j in range(512): | |
mat = MQSystem.newMaterial() | |
s= "mat%i"%(k) #give each material a unique name | |
k += 1 | |
mat.name=s | |
rd=struct.unpack('B',g.read(1))[0] | |
gr=struct.unpack('B',g.read(1))[0] | |
bl=struct.unpack('B',g.read(1))[0] | |
if (rd !=0) and (gr !=0) and (bl !=0): | |
mat.color=MQSystem.newColor(rd/255.0,gr/255.0 ,bl/255.0) | |
idx = doc.addMaterial(mat) #add material to document | |
ob.face[512*i+j].material=idx #set material to face | |
ob.face[512*i+j].select=1 #select the face | |
else: | |
# user select incorrect file type | |
mqprint("Not a *.pak file") | |
else: | |
# user clicked "Cancel" | |
mqprint("No file selected") | |
return | |
if __name__ == "__main__": | |
# clear output window | |
MQSystem.clearLog() | |
# run main function | |
main() | |
# let user know script finished | |
mqprint("Script finished") |
Make sure the plane object is the current object by selecting it in the Object Panel and that nothing of the mesh is selected before running the script using Script>Run in the Script Editor.
Note that because of the high number iterations through the loop the script takes a few minutes to finish.
You may have to set Metasequoia to show only faces and not lines or points to see the logo properly.
After running the script the non black pixels should be selected so you can use extrude to make the title 3D.
No comments:
Post a Comment