Important information: this site is currently scheduled to go offline indefinitely by end of the year.

Pepakura .PBO to Metasequoia .MQO Conversion Script

Post questions about game models here, or help out others!
Ninja
veteran
Posts: 84
Joined: Sat Feb 26, 2011 3:44 am
Has thanked: 1 time
Been thanked: 20 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by Ninja »

LOL - it's my old script.....

Anyway, the dump = f.read(148) line near the top isn't always correct.
For most western locales it's 148 bytes, guessing the file uses a different locale and/or font.
For the files you posted it needs f.read(149) to work.

Should really get around to fixing it at some point, can't find my format specs atm, from memory the locale and font name length is given, the names are plain ascii + value.
finale00
M-M-M-Monster veteran
M-M-M-Monster veteran
Posts: 2382
Joined: Sat Apr 09, 2011 1:22 am
Has thanked: 170 times
Been thanked: 307 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by finale00 »

lol I was wondering why your BRS script looked familiar.

I don't have any pepakura models for that particular format (they have different versions), but the version I have gives string lengths.

Now that I look at it...it's a very simple format. I think last year I thought it was really complicated. Now it's just...cool, header + vertices + indices
Well, version 3 anyways. They probably have an option for compression though, based on what you had.

I'm sure when they moved from whatever version to version 3, they decided compression was silly...
Nintendude
advanced
Posts: 57
Joined: Wed Oct 19, 2011 4:25 am
Has thanked: 5 times
Been thanked: 2 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by Nintendude »

Ahem, I've been doing pepakura, longer than just about anyone else on the web. Here's the thing, if you have the unlocked version of Pepakura Designer 3 you can export the pepakura model to a OBJ format which Metasequoia will open and you can either work with it in Metasequoia or you can export it from there in the MQO format. No coding needed. And I get a unlimited supply of codes from Tamasoft to give away at panels that I teach pepakura on.
finale00
M-M-M-Monster veteran
M-M-M-Monster veteran
Posts: 2382
Joined: Sat Apr 09, 2011 1:22 am
Has thanked: 170 times
Been thanked: 307 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by finale00 »

I guess whoever wants free licenses they know where to go lol.

I'm guessing pepakura allows obj importing (and maybe other formats)?
Ninja
veteran
Posts: 84
Joined: Sat Feb 26, 2011 3:44 am
Has thanked: 1 time
Been thanked: 20 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by Ninja »

Yeah, did the script for the old version as well.
It is a simple format for the 3D model anyway, the locale strings in the header are simply masked, there isn't any compression except for the texures, which is where it gets silly, there's no checking for repeated textures - makes compressing them redundant......
Got a 32 byte MD5 key in the header, for security - lol

I'll find my older versions and upload them.

@Nintendude, not if the file is locked, you'd need a cracked version of pepakura for that.
I don't see any problem ripping files from software that encourages the (mostly illegal) distribution of game content.
You got any old tenkai versions? Think I got 1.5 somewhere.
Nintendude
advanced
Posts: 57
Joined: Wed Oct 19, 2011 4:25 am
Has thanked: 5 times
Been thanked: 2 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by Nintendude »

I just use Pepakura Designer 3, Pepakura Designer allows for .3ds, .obj, .mqo, and a few others. It's not able to open everything out there and high-poly models in pepakura designer are not advisable. Pepakura Designer is pretty much a over glorified UV coordinate program it converts 3D to 2D so the 2D pattern can be created out of paper in 3D.
Actually if a pepakura file is locked there's not really any possible way I know of to crack the file except for getting the password from the original artist. I've tried, although I have'nt tried everything.
Whenever I make a pepakura file I usually get it from someplace like here, Facepunch, Jedi Knight 3 Mods, before I'll try to get it from the game myself if I can't get it from the game there's usually someone like a person on here who can help with that, all my pepakura models come from sites like this and the ones I mentioned above, I've ripped a few models but about 75% comes from sources.
User avatar
youngmark
veteran
Posts: 145
Joined: Thu Sep 02, 2010 1:38 pm
Has thanked: 30 times
Been thanked: 6 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by youngmark »

finale00 wrote:I guess whoever wants free licenses they know where to go lol.
That's not what I want.
This is just difference version of Pepakura, by the way.
Ninja
veteran
Posts: 84
Joined: Sat Feb 26, 2011 3:44 am
Has thanked: 1 time
Been thanked: 20 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by Ninja »

Found lots of older version files, but better than that I found the older software zips and installers.
Got tenkai (old name) versions 123a and 140a, and pepakura designer versions 1.01, 2.01 and 2.17.
Zipped them up together if anyone wants them as a curiosity, pm me.
alon
mega-veteran
mega-veteran
Posts: 163
Joined: Mon Nov 29, 2010 10:38 am
Has thanked: 32 times
Been thanked: 2 times

Re: Pepakura .PBO to Metasequoia .MQO Conversion Script

Post by alon »

Available to convert PDO file ->PDO 00_.pdo, PDO 01_.pdo, PDO 02_.pdo, PDO 03_.pdo
Unable to convert PDO file ->PDO 00.pdo, PDO 01.pdo, PDO 02.pdo, PDO 03.pdo
http://www.mediafire.com/?4my9bt4hg2uw8y6
There is a distinct difference between the two.
But, i don't know exactly that.
Seventyseven
ultra-n00b
Posts: 2
Joined: Thu Sep 13, 2007 10:28 am
Been thanked: 1 time

Re: Pepakura .PDO to Metasequoia .MQO Conversion Script

Post by Seventyseven »

A bit late but had to fix the errors.

Code: Select all

# pepakura3 (.PDO) to metasequoia (.MQO) converter
# by MrPotatoHead using python 2.6

# You must specify the imput file with the full directory
# You must also specify the output directory AND filename (no extension)
# Also remember to change the scale

# I couldn't be bothered to invert the face orientation
# Just select all the faces in your cad program and invert them

import struct
import zlib
import codecs
from array import array
import sys
#saveout = sys.stdout
#outfile = open('C:/output.txt', 'w')
#sys.stdout = outfile

h1=codecs.decode('424d','hex')
h2=codecs.decode('000000003600000028000000','hex')
h3=codecs.decode('010018000000000000000000120B0000120B00000000000000000000','hex')
h4=codecs.decode('0000','hex')

#***** Change the Scale here *****
scale = 1
#*********************************


f = open("C:/testfile.pdo", "rb")
outputname = "testfile"
outputdirectory = "C:/temp/"


metafile = outputdirectory+outputname
of = open(metafile+".mqo", 'w')

of.write("Metasequoia Document\n")
of.write("Format Text Ver 1.0\n")
of.write("\n")
of.write("Scene {\n")
of.write("pos -30.5374 -301.0406 878.7299\n")
of.write("lookat 0.0000 0.0000 0.0000\n")
of.write("head -6.8400\n")
of.write("pich 0.1908\n")
of.write("ortho 0\n")
of.write("zoom2 10.0094\n")
of.write("amb 0.490 0.490 0.490\n")
of.write("}\n")



try:
   dump = f.read(148)
   print ("dump")
   nobj = f.read(4)
   numobj = struct.unpack("i", nobj)
   kk1 = numobj[0]
   print ("number of objects =" ,kk1)
   if kk1 > 10000: kk1=1
   #loop number of objects
   for i in range(0,kk1):
      dump = f.read(4)
      namelen = struct.unpack("i", dump)
      dump = f.read(namelen[0])
      dump = f.read(1)
      dump = f.read(4)
      numvert = struct.unpack("i", dump)
      kk2 = numvert[0]
      if kk2 > 10000: kk2 = 0
      #loop number of vertices
      for j in range(0, kk2):
         x = f.read(8)
         y = f.read(8)

         z = f.read(8)
      dump = f.read(4)
      numfaces = struct.unpack("i", dump)
      kk3 = numfaces[0]
      if kk3 > 10000: kk3 = 0
      #loop number of faces
      for j in range(0, kk3):
         dump = f.read(40)
         nvif = f.read(4)
         numvif = struct.unpack("i", nvif)
         kk4 = numvif[0]
         if kk4 > 10: kk4 = 0
         #loop number of verticies in face
         for k in range(0, kk4):
            vnum = f.read(4)
            vnumber = struct.unpack("i", vnum)
            dump = f.read(8)
            dump = f.read(8)
            u1 = f.read(8)
            uu = struct.unpack("d", u1)
            v1 = f.read(8)
            vv = struct.unpack("d", v1)
            dump = f.read(49)
      dump = f.read(4)
      numlines = struct.unpack("i", dump)
      kk5 = numlines[0]
      print ("number of lines", kk5)
      if kk5 > 20000: kk5 = 0
      for l in range(0, kk5):
         dump = f.read(22)
      position = f.tell();

   #now get materials
   print ("position")
   dump = f.read(4)
   numtx = struct.unpack("i", dump)

   numtex = numtx[0]
   tstr1 = ("Material "+str(numtex)+" {\n") #error fixed - added space after Material
   of.write(tstr1)
   for m in range(0, numtex):
      print ("processing material", m+1, "of", numtex)
      tstr1 = "\"mat"+str(m+1)+"\" shader(3) col("
      of.write(tstr1)
      dump = f.read(4)
      nameln = struct.unpack("i", dump)
      namelen = nameln[0]
      dump = f.read(namelen)
      dump = f.read(4)
      rrrr = struct.unpack("f", dump)
      dump = f.read(4)
      gggg = struct.unpack("f", dump)
      dump = f.read(4)
      bbbb = struct.unpack("f", dump)
      dump = f.read(4)
      aaaa = struct.unpack("f", dump)
      tstr1 = ("%.3f" % rrrr)+" "+("%.3f" % gggg)+" "+("%.3f" % bbbb)+" "+("%.3f" % aaaa)
      tstr1 += ") dif(0.800) amb(0.600) emi(0.160) spc(0.000) power(5.00)"
      of.write(tstr1)
      dump = f.read(64)
      dump = f.read(1)
      d2 = struct.unpack("B", dump[0])
      print ("d2[0]")
      if d2[0] == 1:
         tstr1 = " tex(\""+outputname+str(m)+"tex.bmp\")" #error fixed - was text instead of tex and added space
         of.write(tstr1)
         print ("texture found")
         dump = f.read(4)
         bmpw = struct.unpack("i", dump)
         bmpwidth = bmpw[0]
         dump = f.read(4)
         bmph = struct.unpack("i", dump)


         bmpheight = bmph[0]
         dump = f.read(4)
         zlibl = struct.unpack("i", dump)
         zliblen = zlibl[0] # error fixed - was zlib
         numpixels = bmpwidth*bmpheight
         print ("numpixels")
         #decompress zlib data
         dump = f.read(zliblen)
      of.write("\n")



except EOFError:
   print ("oops")

finally:
   f.seek(0,0);


#just to make sure
f.seek(0,0);
of.write("}\n")
out_str = ""
try:
   dump = f.read(148)
   nobj = f.read(4) #error fixed - minus sign should be equals sign
   numobj = struct.unpack("i", nobj)
   #print numobj[0]
   kk1 = numobj[0]
   if kk1 > 10000: kk1 = 1
   for i in range(0, kk1):
      dump = f.read(4)
      namelen = struct.unpack("i", dump)
      dump = f.read(namelen[0])
      dump = f.read(1)
      print ("processing object", i+1)
      name = "obj"+str(i+1)
      of.write("Object \""+name+"\" {\n")

      of.write(" depth 0\n")
      of.write(" folding 0\n")
      of.write(" scale 1.000000 1.000000 1.000000\n")
      of.write(" rotation 0.000000 0.000000 0.000000\n")
      of.write(" translation 0.000000 0.000000 0.000000\n")
      of.write(" visible 15\n")
      of.write(" locking 0\n")
      of.write(" shading 1\n")
      of.write(" facet 59.5\n")
      of.write(" color 0.000 0.000 0.000\n")
      of.write(" color_type 0\n")
      of.write(" vertex ") #error fixed should be vertex
      dump = f.read(4)
      numvert = struct.unpack("i", dump)
      of.write(str(numvert[0])),
      of.write("{\n")
      kk2 = numvert[0]
      if kk2 > 10000: kk2 = 0
      for j in range(0, kk2):
         x = f.read(8)
         y = f.read(8)
         z = f.read(8)
         outx = struct.unpack("d",x)
         outy = struct.unpack("d",y)
         outz = struct.unpack("d",z)
         ox = outx[0] * scale
         oy = outy[0] * scale
         oz = outz[0] * scale
         tmpstr = "\t"+("%.4f" % ox)+" "+("%.4f" % oy)+" "+("%.4f" % oz)
         of.write(tmpstr+"\n")
      of.write(" }\n")
      dump = f.read(4)
      numfaces = struct.unpack("i", dump)
      tmpstr = "\t face"+" "+str(numfaces[0])+" {\n"
      of.write(tmpstr)
      kk3 = numfaces[0]

      if kk3 > 10000: kk3 = 0
      for j in range(0, kk3):
         mtid = f.read(4)
         matid = struct.unpack("i", mtid)
         matid2 = matid[0]
         matstr = ""
         if matid2 != -1:
            matstr = "M("+str(matid2)+")"
         dump = f.read(36)
         nvif = f.read(4)
         numvif = struct.unpack("i", nvif)
         tmpstr = str(numvif[0])+" V("
         of.write(tmpstr)
         kk4 = numvif[0]
         if kk4 > 10: kk4 = 0
         #redo this to reverse the faces: either 3 or 4
         for k in range(0, kk4):
            vnum = f.read(4)
            vnumber = struct.unpack("i", vnum)
            of.write(str(vnumber[0])+" "),
            dump = f.read(8)
            dump = f.read(8)
            u1 = f.read(8)
            uu = struct.unpack("d", u1)
            out_str += ("%.5f" % uu[0])
            out_str += " "
            v1 = f.read(8)
            vv = struct.unpack("d", v1)
            out_str += ("%.5f" % vv[0])
            out_str += " "
            dump = f.read(49)
         of.write(")"+matstr+" UV( "+out_str+" )\n")
         out_str = ""
      of.write("}\n")
      of.write("}\n")
      dump = f.read(4)

      numlines = struct.unpack("i", dump)
      kk5 = numlines[0]
      if kk5 > 20000: kk5 = 0
      for l in range(0, kk5):
         dump = f.read(22)
      position = f.tell();
   of.write("Eof\n")
   of.close()
   #read number of materials
   dump = f.read(4)
   numtx = struct.unpack("i", dump)
   numtex = numtx[0]
   #for k = 1 to numtex do
   for m in range(0, numtex):
      print ("processing materials",m)
      dump = f.read(4)
      nameln = struct.unpack("i", dump)
      namelen = nameln[0]
      dump = f.read(namelen)#error fixed was nameln instead of namelen
      dump = f.read(80)
      dump = f.read(1)
      d2 = struct.unpack("B", dump[0])
      print ("d2[0]")
      if d2[0] == 1:
         print ("doing bitmap")
         dump = f.read(4)
         bmpw = struct.unpack("i", dump)
         bmpwidth = bmpw[0]
         dump = f.read(4)
         bmph = struct.unpack("i", dump)
         bmpheight = bmph[0]
         dump = f.read(4)
         zlibl = struct.unpack("i", dump)
         zliblen = zlibl[0] #error fixed - was zlib instead of zlibl
         numpixels = bmpwidth*bmpheight
         print ("numpixels")

         #decompress zlib data
         dump = f.read(zliblen)
         out = zlib.decompress(dump)
         out = out[::-1]
         out2 = ""
         for n in range(0, bmpheight):
            pstart = int(n*bmpwidth*3)
            pend = int((pstart)+(bmpwidth*3))
            tout = out[pstart:pend]
            outk = ""
            for knn in range(0, bmpwidth):
               myoutk = ""
               kstart = (knn*3)
               kend = (knn*3)+3
               myoutk = tout[kstart:kend]
               outk += myoutk[::-1]
            out2 += outk[::-1]
         print ("n")
         #write bitmap image to file
         of2name = metafile+str(m)+"tex.bmp"
         of2 = open(of2name, 'wb')
         of2.write(h1)
         bmpfilesize = "%08x" % ((bmpwidth*bmpheight*3)+56)
         print ("bmpfilesize, bmpwidth, bmpheight")
         bmpfs = codecs.decode(bmpfilesize,'hex')
         bmpfs = bmpfs[::-1]
         of2.write(bmpfs)
         of2.write(h2)
         bmpws = "%08x" % (bmpwidth)
         bmpws2 = codecs.decode(bmpws,'hex')
         bmpws2 = bmpws2[::-1]
         of2.write(str(bmpws2))
         bmphs = "%08x" % (bmpheight)
         bmphs2 = codecs.decode(bmphs,'hex')
         bmphs2 = bmphs2[::-1]
         of2.write(str(bmphs2))

         of2.write(h3)
         of2.write(out2)
         of2.write(h4)
         of2.close()

except EOFError:
   print ("oops")

finally:
   f.close()

print ("finished")
Here is Python 2.7 code that can be used (imported) to provide a file dialog to get filename.

Code: Select all

#python 2.7 boilerplate code for a file dialog

from tkFileDialog import askopenfilename as tkFileGet
import tkMessageBox
import os.path, sys


def openFile(filetype,extension):
    fn = tkFileGet(title='Select a file',
                   #initialdir=os.path.split(sys.argv[0])[0],
                   filetypes=[(filetype,'*.'+extension),('All Files','*.*')])
    if fn:
        if fn[-4:].lower() in ['.'+extension]:
            return fn
        else:
            print ('Error.','Not a '+extension+' file.')
            tkMessageBox.showinfo('Error.','Not a '+extension+' file')
            return  
    else:
        print ('No file selected.')
        return  

if __name__ =='__main__':
    openFile('filetype','ext')
Post Reply