home *** CD-ROM | disk | FTP | other *** search
- import array
- import xentax
-
- class Vertex3D:
- def __init__(self, vx, vy, vz, nx, ny, nz, tu, tv):
- self.vx = vx;
- self.vy = vy;
- self.vz = vz;
- self.nx = nx;
- self.ny = ny;
- self.nz = nz;
- self.tu = tu;
- self.tv = tv;
-
- class SurfaceInfo:
- def __init__(self, ti, si, sl):
- self.textureIndex = ti;
- self.startIndex = si;
- self.stripLength = sl;
-
- class TextureInfo:
- def __init__(self, p1, p2, p3, p4):
- self.p1 = p1; # width
- self.p2 = p2; # height
- self.p3 = p3; # size of data
- self.p4 = p4; # offset to data
-
- #
- # SPECIFY FILENAME WITHOUT EXTENSION
- # MODIFY THIS TO LOAD ANOTHER MODEL
- #
- filename = 'law1u';
-
- #
- # OPEN CHR FILE
- #
- ifile = open(filename + '.chr', 'rb');
-
- #
- # OPEN OBJ FILE
- #
- ofile = open(filename + '.obj', 'wt');
-
- #
- # OPEN MTL FILE
- #
- mfile = open(filename + '.mtl', 'wt');
-
- #
- # SAVE OBJ HEADER
- #
- ofile.write('o ' + filename + '.obj\n');
- ofile.write('mtllib ' + filename + '.mtl\n');
- ofile.write('\n');
-
- #
- # READ OFFSETS
- #
- ifile.seek(0x14);
- offset1 = xentax.LE_read_uint32(ifile); # vertex buffer offset
- offset2 = xentax.LE_read_uint32(ifile); # index buffer offset
- offset3 = xentax.LE_read_uint32(ifile); # texture data offset
- offset4 = xentax.LE_read_uint32(ifile); # skeleton data offset
-
- #
- # CALCULATE VERTEX BUFFER PROPERTIES
- #
- vbuffer_size = offset2 - offset1;
- vertices = int(vbuffer_size/0x20);
-
- #
- # CALCULATE INDEX BUFFER PROPERTIES
- #
- ibuffer_size = offset3 - offset2;
- indices = int(ibuffer_size/0x2);
-
- #
- # READ SURFACE DATA
- #
- surface_array = [];
- ifile.seek(0x40);
- while True:
- type = xentax.LE_read_uint32(ifile);
- if type == 0:
- param02 = xentax.LE_read_uint32(ifile);
- param03 = xentax.LE_read_uint16(ifile);
- param04 = xentax.LE_read_uint16(ifile);
- param05 = xentax.LE_read_float16(ifile);
- param06 = xentax.LE_read_float16(ifile);
- param07 = xentax.LE_read_float16(ifile);
- param08 = xentax.LE_read_float16(ifile);
- param09 = xentax.LE_read_float16(ifile);
- param10 = xentax.LE_read_float16(ifile);
- param11 = xentax.LE_read_float16(ifile);
- param12 = xentax.LE_read_float16(ifile);
- elif type == 1:
- d02 = xentax.LE_read_uint32(ifile);
- d03 = xentax.LE_read_uint32(ifile);
- d04 = xentax.LE_read_uint16(ifile);
- d05 = xentax.LE_read_uint16(ifile);
- d06 = xentax.LE_read_uint32(ifile);
- d07 = xentax.LE_read_uint32(ifile);
- d08 = xentax.LE_read_uint32(ifile);
- d09 = xentax.LE_read_uint32(ifile);
- d10 = xentax.LE_read_uint32(ifile);
- d11 = xentax.LE_read_uint32(ifile);
- d12 = xentax.LE_read_uint32(ifile);
- d13 = xentax.LE_read_uint32(ifile);
- d14 = xentax.LE_read_uint32(ifile);
- d15 = xentax.LE_read_uint32(ifile);
- surface_array.append(SurfaceInfo(d12, d14, d15));
- elif type == 2:
- u02 = xentax.LE_read_uint32(ifile);
- u03 = xentax.LE_read_uint32(ifile);
- u04 = xentax.LE_read_uint32(ifile);
- u05 = xentax.LE_read_uint32(ifile);
- surface_array.append(SurfaceInfo(u02, u04, u05));
- elif type == 0xFFFFFFFF:
- if ifile.tell() == offset4:
- break;
- else:
- print('UNKNOWN ENTRY TYPE:');
- print(type);
- print(ifile.tell());
- break;
-
- #
- # MOVE TO VERTEX DATA
- #
- ifile.seek(offset1);
-
- #
- # READ VERTEX DATA
- #
- vbuffer = [];
- for i in range(vertices):
-
- # read vertex
- vx = xentax.LE_read_float16(ifile);
- vy = xentax.LE_read_float16(ifile);
- vz = xentax.LE_read_float16(ifile);
- u1 = xentax.LE_read_float16(ifile);
- nx = xentax.LE_read_float16(ifile);
- ny = xentax.LE_read_float16(ifile);
- nz = xentax.LE_read_float16(ifile);
- u2 = xentax.LE_read_float16(ifile);
- tu = xentax.LE_read_float16(ifile);
- tv = 1.0 - xentax.LE_read_float16(ifile);
- u3 = xentax.LE_read_float16(ifile);
- u4 = xentax.LE_read_float16(ifile);
- u5 = xentax.LE_read_float16(ifile);
- u6 = xentax.LE_read_float16(ifile);
- u7 = xentax.LE_read_float16(ifile);
- u8 = xentax.LE_read_float16(ifile);
-
- # save vertex
- vbuffer.append(Vertex3D(vx, vy, vz, nx, ny, nz, tu, tv));
-
- # save vertex
- strlist = []
- strlist.append('v ');
- strlist.append(str(vx));
- strlist.append(' ');
- strlist.append(str(vy));
- strlist.append(' ');
- strlist.append(str(vz));
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- # save normal
- strlist = []
- strlist.append('vn ');
- strlist.append(str(nx));
- strlist.append(' ');
- strlist.append(str(ny));
- strlist.append(' ');
- strlist.append(str(nz));
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- # save UV
- strlist = []
- strlist.append('vt ');
- strlist.append(str(tu));
- strlist.append(' ');
- strlist.append(str(tv));
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- # extra newline
- ofile.write('\n');
-
- #
- # MOVE TO INDEX DATA
- #
- ifile.seek(offset2);
-
- #
- # PROCESS SURFACES
- #
- for index in range(len(surface_array)):
-
- # save group
- ofile.write('g ' + filename + '_' + str(surface_array[index].textureIndex) + '\n');
- ofile.write('usemtl ' + filename + '_' + str(surface_array[index].textureIndex) + '\n');
-
- # read first triangle in triangle strip
- a = xentax.LE_read_uint16(ifile) + 1;
- b = xentax.LE_read_uint16(ifile) + 1;
- c = xentax.LE_read_uint16(ifile) + 1;
-
- # vertex and normals
- v1 = [ vbuffer[a - 1].vx, vbuffer[a - 1].vy, vbuffer[a - 1].vz ];
- v2 = [ vbuffer[b - 1].vx, vbuffer[b - 1].vy, vbuffer[b - 1].vz ];
- v3 = [ vbuffer[c - 1].vx, vbuffer[c - 1].vy, vbuffer[c - 1].vz ];
- n1 = [ vbuffer[a - 1].nx, vbuffer[a - 1].ny, vbuffer[a - 1].nz ];
- n2 = [ vbuffer[b - 1].nx, vbuffer[b - 1].ny, vbuffer[b - 1].nz ];
- n3 = [ vbuffer[c - 1].nx, vbuffer[c - 1].ny, vbuffer[c - 1].nz ];
-
- # save points to OBJ file
- if xentax.is_face_flipped(v1, v2, v3, n1, n2, n3) == False:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
- else:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- for i in range(3, surface_array[index].stripLength):
-
- # read one more point
- a = b;
- b = c;
- c = xentax.LE_read_uint16(ifile) + 1;
-
- # do not output degenerate triangles
- if a == b or a == c or b == c:
- continue;
-
- # save triangles to OBJ file
- if ((i % 2) == 0):
-
- # vertex and normals
- v1 = [ vbuffer[a - 1].vx, vbuffer[a - 1].vy, vbuffer[a - 1].vz ];
- v2 = [ vbuffer[b - 1].vx, vbuffer[b - 1].vy, vbuffer[b - 1].vz ];
- v3 = [ vbuffer[c - 1].vx, vbuffer[c - 1].vy, vbuffer[c - 1].vz ];
- n1 = [ vbuffer[a - 1].nx, vbuffer[a - 1].ny, vbuffer[a - 1].nz ];
- n2 = [ vbuffer[b - 1].nx, vbuffer[b - 1].ny, vbuffer[b - 1].nz ];
- n3 = [ vbuffer[c - 1].nx, vbuffer[c - 1].ny, vbuffer[c - 1].nz ];
-
- # save points to OBJ file
- if xentax.is_face_flipped(v1, v2, v3, n1, n2, n3) == False:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
- else:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- else:
-
- # vertex and normals
- v1 = [ vbuffer[a - 1].vx, vbuffer[a - 1].vy, vbuffer[a - 1].vz ];
- v2 = [ vbuffer[c - 1].vx, vbuffer[c - 1].vy, vbuffer[c - 1].vz ];
- v3 = [ vbuffer[b - 1].vx, vbuffer[b - 1].vy, vbuffer[b - 1].vz ];
- n1 = [ vbuffer[a - 1].nx, vbuffer[a - 1].ny, vbuffer[a - 1].nz ];
- n2 = [ vbuffer[c - 1].nx, vbuffer[c - 1].ny, vbuffer[c - 1].nz ];
- n3 = [ vbuffer[b - 1].nx, vbuffer[b - 1].ny, vbuffer[b - 1].nz ];
-
- # save points to OBJ file
- if xentax.is_face_flipped(v1, v2, v3, n1, n2, n3) == False:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
- else:
- strlist = []
- strlist.append('f ');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append('/');
- strlist.append(str(a));
- strlist.append(' ');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append('/');
- strlist.append(str(b));
- strlist.append(' ');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append('/');
- strlist.append(str(c));
- strlist.append(' ');
- strlist.append('\n');
- ofile.write(''.join(strlist));
-
- # separate groups
- ofile.write('\n');
-
- #
- # READ NUMBER OF TEXTURES
- #
- ifile.seek(0x2C);
- n_textures = xentax.LE_read_uint32(ifile);
-
- #
- # MOVE TO TEXTURE DATA
- #
- ifile.seek(offset3);
-
- #
- # READ TEXTURE INFORMATION
- #
- texture_info = [];
- for i in range(n_textures):
- p1 = xentax.LE_read_uint32(ifile);
- p2 = xentax.LE_read_uint32(ifile);
- p3 = xentax.LE_read_uint32(ifile);
- p4 = xentax.LE_read_uint32(ifile);
- texture_info.append(TextureInfo(p1, p2, p3, p4));
-
- #
- # READ TEXTURES
- #
- for i in range(n_textures):
- # move to texture offset
- ifile.seek(texture_info[i].p4);
- # read texture data
- data = array.array('B');
- data.fromfile(ifile, texture_info[i].p3);
- # save data
- tfile = open(filename + '_' + str(i) + '.dds', 'wb');
- xentax.WriteUncompressedDDSHeader(tfile, texture_info[i].p1, texture_info[i].p2, False, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
- data.tofile(tfile);
- tfile.close();
-
- #
- # SAVE MATERIAL DATA
- #
- for i in range(n_textures):
- mfile.write('newmtl ' + filename + '_' + str(i) + '\n');
- mfile.write('Ka 0 0 0' + '\n');
- mfile.write('Kd 0.784314 0.784314 0.784314' + '\n');
- mfile.write('Ks 0 0 0' + '\n');
- mfile.write('Ni 1' + '\n');
- mfile.write('Ns 400' + '\n');
- mfile.write('Tf 1 1 1' + '\n');
- mfile.write('d 1' + '\n');
- mfile.write('map_Kd ' + filename + '_' + str(i) + '.dds' + '\n');
- mfile.write('\n');
-
- #
- # CLOSE FILE
- #
- ofile.close();
- ifile.close();