GMax2AC

From FlightGear wiki
Revision as of 19:00, 20 October 2008 by Fg (talk | contribs)
Jump to navigation Jump to search

This is an attempt to present my code in wiki. I will see if it comes through wikification.


--- gMAX2AC.ms
-- Steve Knoblock 2005
-- Developed from gMAX2OBJ.ms and the
-- Maxscript help documents.
-- AC3D File format specification:   
http://www.ac3d.org/ac3d/man/ac3dfileformat.html

global baseVertex = 0

function toDec f = (
  local i = f as integer
  return i
)

function outputHeader =(
   format "AC3Db\n"
   format "MATERIAL \"\" rgb 1 1 1  amb 0.2 0.2 0.2  emis 0 0 0  spec 0.5 0.5 0.5  shi 10  trans 0"
   format "\n";
   flushStringStream
)

function outputFooter =(
   format "\n"
   flushStringStream
)

function outputNode node = (

   format "OBJECT poly\n"
   format "name \"%\"\n" node.name

   local m = snapshotAsMesh node

   format "numvert %\n" m.numVerts

   -- ac format specifies a zero based index for vertex points
   -- however, gmax is one based index
   
   for v = 1 to m.numVerts do (
       local vert = m.verts[v]
       format "% % %\n" vert.pos.x vert.pos.y vert.pos.z
       flushStringStream
   )
  
   format "numsurf %\n" m.numFaces
          
   for f =1 to m.numFaces do (
   format "SURF 0x20\n"
   format "mat 0\n"
   format "refs 3\n"
  
   -- subtract one for zero based vertex index
   
   -- does not need base vertex because ac format
   -- each object starts over in index count
  
   local vface =getface m f
   local x = toDec(vface.x)
   x = x-1
   local y = toDec(vface.y)
   y = y-1
 
   local z = toDec(vface.z)
   z = z-1
  
   format "% 0.5 0.5\n" x
   format "% 0.5 0.5\n" y
   format "% 0.5 0.5\n" z
     
   )

   format "kids 0\n"

   -- Because this is iterating over all objects in the
   -- scene, it requires this base vertext code, which
   -- I think keeps the object's indexes separate.
  
   baseVertex = baseVertex + m.numVerts
)


function PrintObj = (
   outputHeader()
   for c in rootNode.children do outputNode c
    outputFooter()
) 

PrintObj()


I wrote this very quickly because I was in a hurry to get my 3d models out of GMAX and into Blender. My install of Blender did not come with import/export script library, so I could not use the OBJ export script I found on the web as I wanted. I started writing this and got far enough that it outputs a recognizable object in AC format. It seems to have some problems, so use it with caution and feel free to modify or correct it. I will probably not be working on it anymore, since I now have both Wavefront OBJ and AC3D import/export in Blender. I will continue using gMAX2OBJ script to export from GMAX (very tedious, although check out the resources in the main article for a script that supposedly makes this process easier).

The OBJ format is much more similar in structure to the internal GMAX data or at least the structures the API functions return. This makes it much easier to just output the GMAX vertices and faces separately. For AC format, I had to think a while how to output the SURF surfaces, from the GMAX faces. I decided to output a SURF for each GMAX face. There are no faces in GMAX that are not triangles.

In 3d data, there are vertices or points in space and faces. The faces are the polygons formed by connecting the vertices. A cube has 6 faces an 8 vertices. However, 3d applications store geometry data in triangles, so there are really twice as many faces. Each face of a cube is two triangles. This can make things a bit confusing (for me at least---this is the first time I've ever made a 3d format converter). The faces are composed of references to verticies. Like and index or list of vertices. Each face is defined by indices to three vertices.

The issue is that if a surface is the same thing as a GMAX face, the GMAX face always consists of three vertice index values. At least that is my interpretation. Feel free to correct this. -- Steve Knoblock