maxscript rewrite to python?

hey guys, I have a maxscript I would like translated (if possible) to python for use as an importer. The maxscript was written for me by someone on another forum but unfortunately he didn’t know anything about python and wasn’t able to write a version for blender.

hope to hear some replies and thanks ahead of time!

if (heapSize < 20000000) then
   heapSize = 200000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \ 
caption:"Open C3 Model File" \
types:"C3 Model File(*.c3)|*.c3" \
historyCategory:"C3ObjectPresets"
f = fopen fname "rb"

fn PrintOffset Var =
(
   local Var = Var
print ("This is the offset 0x" + (bit.intAsHex Var) as string)
   Var
)
fn PrintCount Var =
(
   local Var = Var
print ("This is the Count 0x" + (bit.intAsHex Var) as string)
   Var
)

fn Readword fstream = (
return readshort fstream #unsigned
)

fn ReadFixedString bstream fixedLen =
(
   local str = ""
   for i = 1 to fixedLen do
   (
      str += bit.intAsChar (ReadByte bstream #unsigned)
   )
   str
)
    fn convertTo32 input16 = (
       inputAsInt = input16
       sign = bit.get inputAsInt 16
       exponent = (bit.shift (bit.and inputAsInt (bit.hexasint "7C00")) -10) as integer - 16
       fraction = bit.and inputAsInt (bit.hexasint "03FF")
       if sign==true then sign = 1 else sign = 0
       exponentF = exponent + 127
       --Ouput 32 bit integer representing a 32 bit float
       outputAsFloat = bit.or (bit.or (bit.shift fraction 13) (bit.shift exponentF 23)) (bit.shift sign 31)
       --Output Check   
       return bit.intasfloat outputasfloat
    )

fn ReadHalfFloat fstream = (
return convertTo32(Readshort fstream)
)
maxlen=(getfilesize fname)

Magic1 = ReadFixedString f 0x10
Magic2 == "PHY"
do (
Magic2 = ReadFixedString f 0x3
Magic = readbyte f#unsigned
SectSize = readlong f
test = (ftell f)
nsize = readlong f
MeshName = ReadFixedString f nsize
null = readlong f
vertcount = readlong f
null = readlong f

Vert_array = #()
UV_array = #()
Face_array = #()
if magic == 0x20 Do (
for a = 1 to vertcount Do (
vx = readfloat f 
vy = readfloat f
vz = readfloat f
fseek f 0x24#seek_cur
tu = (readfloat f) * 1
tv = (readfloat f) * -1
fseek f 0x14#seek_cur
append Vert_array [vx,vz,vy]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)   
)
if magic == 0x34 Do (
for a = 1 to vertcount Do (
vx = readfloat f 
vy = readfloat f
vz = readfloat f
tu = (readfloat f) * 1
tv = (readfloat f) * -1
fseek f 0x14#seek_cur
append Vert_array [vx,vz,vy]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
)
if magic == 0x33 Do (
for a = 1 to vertcount Do (
vx = readfloat f 
vy = readfloat f
vz = readfloat f
tu = (readfloat f) * 1
tv = (readfloat f) * -1
fseek f 0x20#seek_cur
append Vert_array [vx,vz,vy]
--append Normal_array [nx,ny,nz]
append UV_array [tu,tv,0]
)
)

FaceCount = readlong f
null = readlong f
for a = 1 to FaceCount Do (
f1 = (readshort f) + 1
f2 = (readshort f) + 1
f3 = (readshort f) + 1
append Face_array [f1,f2,f3] --save faces to Face_array
)

msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count     do setTVert  msh j UV_array[j]
for j = 1 to Face_array.count   do setTVFace msh j Face_array[j]
for j = 1 to Normal_array.count do setNormal msh j Normal_array[j]
printoffset (ftell f)
fseek f (test + SectSize)#seek_set
printoffset (ftell f)
Magic2 = ReadFixedString f 0x3
fseek f -3#seek_cur
) while Magic2 == "PHY" 
fclose f     --close file
actionMan.executeAction 0 "311"  -- Tools: Zoom Extents All Selected 

You can’t directly translate a max script to python…

It’d be easier if you provide a description of what it’s supposed to do

looks like it reads in a file (is it an image/ some custom text format?) and then sets uvs, faces and vertices based on that file… with a couple of options…

If so, one needs an (small) example file (to open and read) and what it should produce …

The script is just an importer for .c3 file types which are used by the MMO conquer online to store their 3d assets used in the game. I beleive the script adjusts hex offsets? or … something to that effect.

The writer of the script pretty much just decoded their file format posted the script and an screen shot of an asset he was able to successfully import into Max.

Unfortunately I don’t have max to be able to use his script. Ill post a link to
the thread maybe that might help clarify things, already posted a sample file there
as well.

forum.xentax.com/viewtopic.php?f=10&t=5582

Thank you in advance!

I now realize, that the script is not Python, containing ‘strange’ functions (I thaught, looked not carefully)… nothing for me, sorry …

Any sort of code is ‘strange’ to me, lol. Ah, well thanks anyhow.

[/closed]

Here’s my best-guess translation into Python. This version doesn’t run within Blender; instead, it translates the data to WaveFront OBJ format and writes it to standard output, which you can then save to a file and import into Blender.

I also tested it on one or two of the sample files, and hit some errors which I was able to patch up as indicated by the parts marked “LDO change”. But there are definitely still files it cannot read; they seem to be in a completely different format, possibly compressed.

#!/usr/bin/python
#+
# Invoke this script as follows:
#
#     C3Decode infile
#
# where infile is the path to the .C3 file to be decoded. The geometry will
# be written to standard output in .OBJ format.
#
# Written 2010 December 29 by Lawrence D'Oliveiro.
#-

import sys
import os
import struct

#+
# Useful stuff
#-

def structread(fromfile, decode_struct) :
    """reads sufficient bytes from fromfile to be unpacked according to
    decode_struct, and returns the unpacked results."""
    return struct.unpack(decode_struct, fromfile.read(struct.calcsize(decode_struct)))
#end structread

nr_decimals = 3

def fmtvec(outfile, prefix, coords, postfix) :
    outfile.write \
      (
            prefix
        +
            " ".join("%%.%df" % nr_decimals % f for f in coords)
        +
            postfix
      )
#end fmtvec

#+
# Following are my best guess as to what these seemingly predefined functions do
#-

def readlong(f) :
    return structread(f, "<L")[0]
#end readlong

def readshort(f) :
    return structread(f, "<H")[0]
#end readshort

def readfloat(f) :
    return structread(f, "<f")[0]
#end readfloat

#+
# Mainline
#-

if len(sys.argv) != 2 :
    raise RuntimeError("usage: %s file_to_decode" % sys.argv[0])
#end if
fname = sys.argv[1]
f = open(fname, "rb")

maxlen = os.path.getsize(fname)

Magic1 = f.read(0x10)
while True :
    Magic2 = f.read(0x3)
    magic = ord(f.read(1))
    SectSize = readlong(f)
    test = f.tell()
    nsize = readlong(f)
    MeshName = f.read(nsize)
    null = readlong(f)
    # LDO change: files seem to have either one of the following longwords zero, so I add them
    vertcount = readlong(f)
    vertcount += readlong(f)

    Vert_array = []
    UV_array = []
    Face_array = []
    if magic == 0x20 :
        for a in range(0, vertcount) :
            vx = readfloat(f)
            vy = readfloat(f)
            vz = readfloat(f)
            f.seek(0x24, os.SEEK_CUR)
            tu = readfloat(f) * 1
            tv = readfloat(f) * -1
            f.seek(0x14, os.SEEK_CUR)
            Vert_array.append((vx,vz,vy))
            UV_array.append((tu,tv,0))
        #end for
    elif magic == 0x34 :
        for a in range(0, vertcount) :
            vx = readfloat(f)
            vy = readfloat(f)
            vz = readfloat(f)
            tu = readfloat(f) * 1
            tv = readfloat(f) * -1
            f.seek(0x14, os.SEEK_CUR)
            Vert_array.append((vx,vz,vy))
            UV_array.append((tu,tv,0))
        #end for
    elif magic == 0x33 :
        for a in range(0, vertcount) :
            vx = readfloat(f)
            vy = readfloat(f)
            vz = readfloat(f)
            tu = readfloat(f) * 1
            tv = readfloat(f) * -1
            f.seek(0x20, os.SEEK_CUR)
            Vert_array.append((vx,vz,vy))
            UV_array.append((tu,tv,0))
        #end for
    #end if
    sys.stderr.write("FaceCount at offset 0x%08x
" % f.tell())

    # LDO change: files seem to have either one of the following longwords zero, so I add them
    FaceCount = readlong(f)
    FaceCount += readlong(f)
    for a in range(0, FaceCount) :
        f1 = readshort(f) + 1
        f2 = readshort(f) + 1
        f3 = readshort(f) + 1
        Face_array.append((f1,f2,f3))
    #end for

    assert len(Vert_array) == len(UV_array)
    for j in range(0, len(Vert_array)) :
        fmtvec(sys.stdout, "v ", Vert_array[j], "
")
        fmtvec(sys.stdout, "vt ", UV_array[j], "
")
    #end for
    for face in Face_array :
        sys.stdout.write \
          (
                "f %(x)d/%(x)d %(y)d/%(y)d %(z)d/%(z)d
"
            %
                {
                    "x" : face[0],
                    "y" : face[1],
                    "z" : face[2],
                }
          )
    #end for

    sys.stderr.write("File offset: 0x%08x
" % f.tell())
    f.seek(test + SectSize, os.SEEK_SET)
    sys.stderr.write("File offset: 0x%08x
" % f.tell())
    Magic2 = f.read(0x3)
    f.seek(-3, os.SEEK_CUR)
    if Magic2 != "PHY" :
        break
#end while
f.close()