3

A game called Forsaken (1998) has models in .mx and .mxa format. Although I'm not sure what's the difference between them, I'd like to know if there's some import script available for them.

enter image description here

I searched for md3 importing scripts before, I bet there should be some for mx too.

Fabián
  • 193
  • 5

2 Answers2

4

Now there is a at least partially implemented importer (prints a lot of stuff to the console) All you need to do is copy the script in the editor and
edit this (last) line before pressing the run button:

importMX("c:\\path\\avatar.mx", 'Avatar')

The first argument is the path to the file to import, second the object name in Blender.

import bpy
import mathutils
import struct

def read_n_items(file, n, func):
    for i in range(n):
        func(i, file)

def read_struct_from_file(file, fmt):
    return struct.unpack(fmt, file.read(struct.calcsize(fmt)))

def skip_string(file):
    s=''
    while True:
        c = struct.unpack('c', file.read(1))[0]
        s = s + c.decode("utf-8")
        if c == b'\x00':
            print(s)
            return       

def importMX(filename, obj_name):
    verts=[]
    faces=[]
    with open(filename, 'rb') as file:
        prjx = read_struct_from_file(file, '8ch')
        print(prjx)
        num_texture_files = prjx[8]
        print(num_texture_files)
        while num_texture_files > 0:
            num_texture_files = num_texture_files - 1
            skip_string(file)
            groups = read_struct_from_file(file, 'h')[0]
            exec_lists = read_struct_from_file(file, 'I')[0]
            exec_type = read_struct_from_file(file, 'h')[0]
            vertices = read_struct_from_file(file, 'h')[0]
            #groups,exec_lists,exec_type,vertices = read_struct_from_file(file, 'hIhh')
        print( 'vertices=%d' % vertices )
        idx=0 
        while idx < vertices:
            x,y,z,reserved,colour,specular,tu,tv = read_struct_from_file(file,'fffIIIII')
            print('%d %f %f %f' % (idx,x,y,z))   
            verts.append((x,y,z))
            idx = idx + 1

        num_tex_groups = read_struct_from_file(file, 'h')[0]
        print(num_tex_groups)

        while num_tex_groups > 0:
            texture_type,start_vertex,num_vertices,texture_no,num_triangles = read_struct_from_file( file, 'hhhhh' )
            num_tex_groups = num_tex_groups - 1
            print( "tt=%d sv=%d nv=%d tno=%d tria=%d" % (texture_type,start_vertex,num_vertices,texture_no,num_triangles ))
            while num_triangles > 0:
                v0,v1,v2,pa = read_struct_from_file( file, 'hhhh' )
                nx,ny,nz = read_struct_from_file( file, 'fff' )
                print('%d,%d,%d %f %f %f' %  (v0,v1,v2,nx,ny,nz))
                num_triangles = num_triangles - 1
                faces.append((v0,v1,v2))                
        print(verts)
        print(faces)
        mesh = bpy.data.meshes.new( obj_name )
        object = bpy.data.objects.new( obj_name, mesh)
        object.location = (0,0,0)  
        bpy.context.scene.objects.link(object)
        mesh.from_pydata(verts,[],faces)

if __name__ == "__main__":
    importMX("c:\\path\\avatar.mx", 'Avatar')

Result:

avatar.mx

enter image description here

airmoble.mx

enter image description here

To get started you can extend on the following code, there is also an undocumented 8 byte "PRJX...." id at beginning of the file besides that the format seems to match.

See https://docs.python.org/3.4/library/struct.html for the format strings like: h=uint16 and I=uint32 etc. enter image description here

stacker
  • 38,549
  • 31
  • 141
  • 243
2

The .mx format and the animated variant .mxa are documented in the sources:

The binary format looks different to the Blender supported formats (at least the ones I have seen so far). You would need to write a custom importer.

num_texture_files : uint16
texture_file_name[num_texture_files] : '\\0' separated strings
num_groups : uint16
{
    num_exec_lists : uint16
    {
      exec_type : uint32 // 0 = entirely opaque, 1 = contains transparencies
      num_vertices : uint16
      vertex(x,y,z,reserved,colour,specular,tu,tv)[num_vertices] : x, y, z float, others uint32
      num_texture_groups : uint16
      {
        texture_type : uint16 // 0 = normal, 1 = environment mapped
        start_vertex : uint16
        num_vertices : uint16
        texture_no : uint16
        num_triangles : uint16
        triangles(v0,v1,v2,pad16,nx,ny,nz)[num_triangles] : v? uint16, pad16 uint16, n? float
      }[num_texture_groups]
    }[num_exec_lists]
}[num_groups]
mxtype : uint16 // always 0 for mx format

The sources of the .MD3 addon show that this format has a at least comparable structure.

stacker
  • 38,549
  • 31
  • 141
  • 243
  • @Fabián the itself format isn't C it is pseudo code. To import the mesh only you would need to skip the texture names and read the vertices num_vertices times. The .MD3 addon has all the code snippets you would need. – stacker Mar 01 '15 at 21:19
  • Yeah I've seen that, although I'm not within the import/export scripting subject, I'm still noob at programming. I was just hoping to insert one file in which makes Blender be able to import the model to begin work with. – Fabián Mar 01 '15 at 21:19
  • ok I recently saw the new comment, I'll give it a try – Fabián Mar 01 '15 at 21:20