www.xbdev.net
xbdev - software development
Sunday March 30, 2025
Home | Contact | Support | 3D File Formats The bits and bytes...
     
 

3D File Formats

The bits and bytes...

 

X File (DirectX Max Exporter) Binary

by bkenwright@xbdev.net



3D Studio max is a fantastic modelling environment I think.... it allows you to create stunning effects and animate full skeleton characters...you could spend hours and weeks lost in the amount of functionality in that package. It also has the added advantage of allowing you to write plugins for it.


There are various ways of writing plugs, either using the max sdk or MaxScript, I decided to use maxscript (.ms) files, as there text editable, so its easy to just open them up and see how they work...they mostly work across most versions of 3d studio max...as long as you know which functions to use and which are only for the latest versions.


When you see how simple it is to create a directx .x maxscript exporter plug-in you won't believe it... with only a single page of script you can export all the mesh data.

The following gives some .ms scripts (max script) examples you can look at for exporting:

Export .x Header Only (Download)
Export .x Static Mesh (Download)
Export . Misc Templates (Download)


Inside '.ms' Exporter MaxScript


The following lets you see the full exporter code (exporter.ms).

-- --------------------------------------------------------------------------------------
--
-- .
x Exporter
-- Kenwright
-- Emailbkenwright@xbdev.net
--
-- --------------------------------------------------------------------------------------

fn 
writeTOKEN_NAME f str=
(
    
writeshort f 1               -- // U16 - token ID  1
    
writelong  f str.count     -- // U32 - Length of name field, in bytes 
                            
    
for 1 to str.count do  -- // Array U8 - array count ASCII name
    
(
           
bit.charAsInt(str[i])
        
writebyte f c    
    
)
)

fn 
writeTOKEN_OBRACE f=
(
    
writeshort f 10               -- // U16 - token ID  1
)

fn 
writeTOKEN_CBRACE f=
(
    
writeshort f 11               -- // U16 - token ID  11
)

fn 
writeTOKEN_TEMPLATE f=
(
    
writeshort f 31               -- // U16 - token ID  31
)

fn 
writeTOKEN_DWORD f=
(
    
writeshort f 41               -- // U16 - token ID
)

fn 
writeTOKEN_SEMICOLON f=
(
    
writeshort f 20               -- // U16 - token ID
)

fn 
writeTOKEN_ARRAY f=
(
    
writeshort f 52               -- // U16 - token ID
)

fn 
writeTOKEN_OBRACKET f=
(
    
writeshort f 14               -- // U16 - token ID
)

fn 
writeTOKEN_CBRACKET f=
(
    
writeshort f 15               -- // U16 - token ID
)

fn 
writeTOKEN_SEMICOLON f=
(
    
writeshort f 20               -- // U16 - token ID
)

fn 
writeTOKEN_LPSTR f=
(
    
writeshort f 49               -- // U16 - token ID
)

fn 
writeTOKEN_DOT f=
(
    
writeshort f 18               -- // U16 - token ID
)

fn 
writeTOKEN_FLOAT f=
(
    
writeshort f 42               -- // U16 - token ID
)


fn 
writeTOKEN_INTEGER_LIST f iList iSize=
(
    
writeshort f 6               -- // U16 - token ID  1
    
writelong  f iSize         -- // U32 - Number of integers in list field
    
    
for 1 to iSize do      -- // Array U32 - array integers
    
(
        
writelong f iList[i]
    ) 
)

fn 
writeTOKEN_FLOAT_LIST f fList iSize=
(
    
writeshort f 7               -- // U16 - token ID  7
    
writelong  f iSize         -- // U32 - Number of integers in list field
    
    
for 1 to iSize do      -- // Array U32 - array integers
    
(
        
writefloat f fList[i]
    ) 
)

fn 
writeTOKEN_GUID f data=
(
    
writeshort  f 5               -- // U16 - token ID  5
    
writeshort  f data[1]
    
writeshort  f data[2

    
writeshort  f data[3]
    
writeshort  f data[4]

    for 
1 to 8 do
    (
        
writebyte f data[i]
    )
)

-- --------------------------------------------------------------------------------------

fn 
writeTemplateFVF f=
(
    
writeTOKEN_TEMPLATE     f
    writeTOKEN_NAME         f     
"FVFData"
    
writeTOKEN_OBRACE       f

    guid 
#(0x0a0e, 0xb6e7, 0x8ef9, 0x4e83, 0x94, 0xad, 0xec, 0xc8, 0xb0, 0xc0, 0x48, 0x97)
    
writeTOKEN_GUID            f     guid
    writeTOKEN_DWORD        f
    writeTOKEN_NAME            f    
"dwFVF"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_DWORD        f
    writeTOKEN_NAME            f    
"nDWords"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_ARRAY        f
    writeTOKEN_DWORD        f
    writeTOKEN_NAME            f    
"data"    
    
writeTOKEN_OBRACKET        f
    writeTOKEN_NAME            f    
"nDWords"
    
writeTOKEN_CBRACKET        f
    writeTOKEN_SEMICOLON    f
    writeTOKEN_CBRACE        f
)

fn 
writeTemplateEffectInstance f=
(
    
writeTOKEN_TEMPLATE     f
    writeTOKEN_NAME            f    
"EffectInstance"
    
writeTOKEN_OBRACE        f
    
    guid 
#(0xf7e4, 0xe331, 0x0559, 0x4cc2, 0x8e, 0x99, 0x1c, 0xec, 0x16, 0x57, 0x92, 0x8f)
    
writeTOKEN_GUID            f     guid
    writeTOKEN_LPSTR        f
    writeTOKEN_NAME            f    
"EffectFilename"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_OBRACKET        f
    writeTOKEN_DOT            f
    writeTOKEN_DOT            f
    writeTOKEN_DOT            f
    writeTOKEN_CBRACKET        f
    writeTOKEN_CBRACE        f
)


fn 
writeTemplateEffectParamFloats f=
(
    
writeTOKEN_TEMPLATE        f
    writeTOKEN_NAME            f    
"EffectParamFloats"
    
writeTOKEN_OBRACE        f
    
    guid 
#(0xb9a0, 0x3014, 0x62f5, 0x478c, 0x9b, 0x86, 0xe4, 0xac, 0x9f, 0x4e, 0x41, 0x8b)
    
writeTOKEN_GUID            f     guid
    writeTOKEN_LPSTR        f
    writeTOKEN_NAME            f    
"ParamName"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_DWORD        f
    writeTOKEN_NAME            f    
"nFloats"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_ARRAY        f
    writeTOKEN_FLOAT        f
    writeTOKEN_NAME            f    
"Floats"
    
writeTOKEN_OBRACKET        f
    writeTOKEN_NAME            f    
"nFloats"
    
writeTOKEN_CBRACKET        f
    writeTOKEN_SEMICOLON    f
    writeTOKEN_CBRACE        f
)


fn 
writeTemplateEffectParamString f=
(

    
writeTOKEN_TEMPLATE        f
    writeTOKEN_NAME            f    
"EffectParamString"
    
writeTOKEN_OBRACE        f

    guid 
#(0x4c88, 0x1dbc, 0x94c1, 0x46ee, 0x90, 0x76, 0x2c, 0x28, 0x81, 0x8c, 0x94, 0x81)
    
writeTOKEN_GUID            f     guid
    writeTOKEN_LPSTR        f
    writeTOKEN_NAME            f    
"ParamName"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_LPSTR        f
    writeTOKEN_NAME            f    
"Value"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_CBRACE        f
)


fn 
writeTemplateEffectParamDWord f=
(
    
writeTOKEN_TEMPLATE        f
    writeTOKEN_NAME            f    
"EffectParamDWord"
    
writeTOKEN_OBRACE        f

    guid 
#(0x63bc, 0xe139, 0xae51, 0x4c5d, 0xb0, 0x0f, 0xcf, 0xa3, 0xa9, 0xd9, 0x7c, 0xe5)
    
writeTOKEN_GUID            f     guid
    writeTOKEN_LPSTR        f
    writeTOKEN_NAME            f    
"ParamName"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_DWORD        f
    writeTOKEN_NAME            f    
"Value"
    
writeTOKEN_SEMICOLON    f
    writeTOKEN_CBRACE        f
)

-- --------------------------------------------------------------------------------------


fn 
writemesh f obj=
(
    
writeTOKEN_NAME           f "Mesh"
    
writeTOKEN_NAME           f "Box01"
    
writeTOKEN_OBRACE         f
    
    
    a 
#()
    
a[1] = obj.numverts
    writeTOKEN_INTEGER_LIST f a 1
    
    j 
1
    verts 
#()
    
for i=1 to obj.numverts do
    (
        
local v=in coordsys world(getvert obj i)
        
verts[j] = v.x
        j
+=1
        verts
[j] = v.y
        j
+=1
        verts
[j] = v.z
        j
+=1
    
)
    
writeTOKEN_FLOAT_LIST f verts (j-1)
    
    
    
1
    indices 
#()
    
    
indices[j] = obj.numfaces
    j
+=1
    
    
for i=1 to obj.numfaces do
    (
        
indices[j] = 3
        j
+=1
        
        i1
=((getFace obj i).z)-1
        i2
=((getFace obj i).y)-1
        i3
=((getFace obj i).x)-1
        
        indices
[j] = i1
        j
+=1
        indices
[j] = i2
        j
+=1
        indices
[j] = i3
        j
+=1
    
)
    
writeTOKEN_INTEGER_LIST f indices (j-1)
    
    
    
writeTOKEN_CBRACE f
)

fn 
writex obj xfilename=
(
    if 
obj==undefined do return"No object"
    
if (classof obj)!=editable_mesh do return "Object is not a mesh"
    
    
f=fopen xfilename "wb"

    
magic  0x20666F78 -- "xof "
    
version0x33303330 -- "0303"
    
type   0x206E6962 -- "bin "
    
acc    0X32333030 -- "0032"

    
writelong f magic
    writelong f version
    writelong f type
    writelong f acc    
    
    writeTemplateFVF f
    writeTemplateEffectInstance f
    writeTemplateEffectParamFloats f
    writeTemplateEffectParamString f
    writeTemplateEffectParamDWord  f
    
    writemesh f obj
    
    fclose f
)

-- --------------------------------------------------------------------------------------

fn 
addcheck cb=
(
     if 
classof cb==string do messagebox cb title:"DirectX .X Export Error"
)

-- --------------------------------------------------------------------------------------

utility XExport ".x Mesh Exporter"
(
    
group "Export"
    
(
        
button bexport "     Export    "
    
)
    
group "About"
    
(
        
label titleLabel    ".x Mesh Exporter v0.01"
        
HyperLink addy "by Ben Kenwright" align:#center address:"mailto:bkenwright@xbdev.net" color:(color 0 100 0) hoverColor:(color 0 0 100)
        
HyperLink me "HomePage" align:#center address:"www.xbdev.net" color:(color 0 100 0) hoverColor:(color 0 0 100)

    
)
    
    
on bexport pressed do
    ( 
        
xfilename=getsavefilename caption:"Save .x" \
            
filename:xlastfile \
            
types:"DirectX .X (*.x)|*.x|All Files (*.*)|*.*|"
        
if xfilename!=undefined do 
        (                
            
addcheck (writex xfilename)
            
xlastfile=xfilename
        
)
    )
)










 
Advert (Support Website)

 
 Visitor:
Copyright (c) 2002-2025 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.