utility ImpExpMDX "MDX Importer/Exporter"
(
----------
-- Vars --
----------
local DwarfFemale
local impTypes
local seqs -- Sequences
local mtls -- Materials
local geos -- Geometry
local objs -- Bones, Helpers, Lights, Attachments
local pivot
local geobones
local notes -- Note Track
----------------
-- Structures --
----------------
struct trackPoint
(
time, point, inTan, outTan
)
struct gVert
(
no, verts = #(), nrmls = #(), txtrs = #(), group = #()
)
struct gPvtx
(
crns, faces = #()
)
struct Bone
(
type=#bone, name, parent, mesh, tr, rt, sc, id, aid, end, no = #()
)
struct Helper
(
type=#helper, name, parent, mesh, tr, rt, sc, no = #()
)
struct Light
(
type=#light, name, parent, mesh, vis, ltype, aStart, aEnd, col, int, ambCol, ambInt, no = #()
)
struct Attachment
(
type=#attach, name, parent, mesh, tr, rt, sc, vis, no = #()
)
struct PartEmitter
(
type=#pemit, name, parent, mesh, tr, rt, sc, vis,
speed, variation, latitude, gravity, lifespan, emissionrate,
length, width, rows, columns, taillength, time, segCol = #(), alpha,
partSc, LifeSpanUVAnim, DecayUVAnim, TailUVAnim, TailDecayUVAnim,
TextureID, no = #()
)
struct Geometry
(
pnts = gVert(), pvtx = gPvtx(), mesh,
bRad, minExt, maxExt, name,
groups = #(), bones = #(), bonegroups = #()
)
struct Sequence
(
name, intStart, intEnd, moveSpeed, noloop, rarity, long,
bRad, minExt, maxExt
)
struct Material
(
bytes, layers = #()
)
struct Layer
(
fmode,shade,texture,alpha
)
struct File
(
pos, end, bstream,
-- Helper function to init the top-level chunk rover
fn Init stream=
(
bstream = stream
pos = ftell bstream
fseek bstream 0 #seek_end
end = ftell bstream
),
fn fReadHead=
(
fseek bstream pos #seek_set
local id = ReadLong bstream #unsigned
local tag = File.GetName id
pos += 4
tag
),
fn fReadFloat=
(
local id
local i = 0
while (id == undefined) and (i < 10) do
(
fseek bstream pos #seek_set
id = ReadFloat bstream
i += 1
)
if i == 10 then
(
print ("problem: " + (pos as string))
)
pos += 4
id
),
fn fReadLong=
(
fseek bstream pos #seek_set
local id = ReadLong bstream
pos += 4
id
),
fn fReadShort=
(
fseek bstream pos #seek_set
local id = ReadShort bstream
pos += 2
id
),
fn fReadByte=
(
fseek bstream pos #seek_set
local id = ReadByte bstream
pos += 1
id
),
fn fReadString n=
(
fseek bstream pos #seek_set
local id = ReadString bstream
pos += n*80
id
),
fn GetName id=
(
case id of
(
--MDLX HEAD
0x584C444D: #MDLX
0x53524556: #VERS
0x4C444F4D: #MODL
0x53514553: #SEQS
0x53424C47: #GLBS
--MATERIALS
0x534C544D: #MTLS
0x41544D4B: #KMTA
0x53584554: #TEXS
--GEOMETRY
0x534F4547: #GEOS
0x58545256: #VRTX
0x534D524E: #NRMS
0x50595450: #PTYP
0x544E4350: #PCNT
0x58545650: #PVTX
0x58444E47: #GNDX
0x4347544D: #MTGC
0x5354414D: #MATS
0x53415655: #UVAS
0x53425655: #UVBS
--GEOMETRY ANIMATION
0x414F4547: #GEOA
--BONE
0x454E4F42: #BONE
--LIGHT
0x4554494C: #LITE
--HELPER
0x504C4548: #HELP
--ATTACHMENT
0x48435441: #ATCH
--PIVOT
0x54564950: #PIVT
--PARTICLE EMITTER
0x32455250: #PRE2
--EVENT
0x53545645: #EVTS
0x5456454B: #KEVT
--COLLISION
0x44494C43: #CLID
--KEYFRAME TRACK
0x4F41474B: #KGAO
0x5254474B: #KGTR
0x5452474B: #KGRT
0x4353474B: #KGSC
0x56414C4B: #KLAV
0x5654414B: #KATV
0x5632504B: #KP2V
0x5632504B: #KP2E
--UNKNOWN
default: #UNKNOWN
)
)
)
fn pseqs mdx i=
(
seqs[i] = Sequence()
seqs[i].name = mdx.fReadString 1
seqs[i].intStart = mdx.fReadLong()
seqs[i].intEnd = mdx.fReadLong()
seqs[i].moveSpeed = mdx.fReadFloat()
seqs[i].noloop = mdx.fReadLong()
seqs[i].rarity = mdx.fReadFloat()
seqs[i].long = mdx.fReadLong()
mdx.pos += 28
animationRange = Interval 0 seqs[i].intEnd
)
fn pmtls mdx i=
(
mtls[i] = Material()
local bytes = mdx.fReadLong()
--long ???, ???
mdx.pos += 8
if mdx.fReadHead() == #LAYS then
(
local nlays = mdx.fReadLong()
for j=1 to nlays do
(
mtls[i].layer[j] = Layer()
local bytesi = mdx.fReadLong()
local endpos = mdx.pos + bytesi - 4;
mtls[i].layer[j].fmode = mdx.fReadLong()
mtls[i].layer[j].shade = mdx.fReadLong()
mtls[i].layer[j].texture = mdx.fReadLong()
--0xFFFFFFFF, long ???
mdx.pos += 8
mtls[i].layer[j].alpha = mdx.fReadFloat()
if mdx.pos == endpos then
(
--KMTA
mdx.pos += 4
local nunks = mdx.fReadLong()
local ltype = mdx.fReadLong()
--0xFFFFFFFF
mdx.pos += 4
for k=1 to nunks do
(
--keyframe, state
mdx.pos += 8
--intan,outtan
if ltype > 1 then mdx.pos += 8
)
)
if mdx.pos != endpos then
(
print mdx.pos
print endpos
)
)
)
)
fn pgeos mdx i=
(
geos[i] = Geometry()
local pnts = gVert()
local pvtx = gPvtx()
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
local curChunk = mdx.fReadHead()
local j = 0
while (mdx.pos < endpos) and (curChunk != #GEOA) and (j < 1) do
(
--print curChunk
--print mdx.pos
case curChunk of
(
#VRTX:
(
geos[i].pnts.no = mdx.fReadLong()
for k=1 to geos[i].pnts.no do
(
local x = mdx.fReadFloat()
local y = mdx.fReadFloat()
local z = mdx.fReadFloat()
pnts.verts[k] = [y,-x,z]
)
)
#NRMS:
(
geos[i].pnts.no = mdx.fReadLong()
for k=1 to geos[i].pnts.no do
(
local x = mdx.fReadFloat()
local y = mdx.fReadFloat()
local z = mdx.fReadFloat()
pnts.nrmls[k] = [y,-x,z]
)
)
#PTYP:
(
mdx.pos += 8
)
#PCNT:
(
mdx.pos += 8
)
#PVTX:
(
geos[i].pvtx.crns = mdx.fReadLong()
for k=1 to (geos[i].pvtx.crns/3) do
(
local x = 1 + mdx.fReadShort()
local y = 1 + mdx.fReadShort()
local z = 1 + mdx.fReadShort()
pvtx.faces[k] = [x,y,z]
)
)
#GNDX:
(
geos[i].pnts.no = mdx.fReadLong()
for k=1 to geos[i].pnts.no do
(
geos[i].pnts.group[k] = (1 + mdx.fReadByte())
)
)
#MTGC:
(
local num = mdx.fReadLong()
for k=1 to num do
(
geos[i].bonegroups[k] = mdx.fReadLong()
)
)
#MATS:
(
local num = mdx.fReadLong()
local n = 0
local o = 0
for k=1 to num do
(
if (n == 0) or (o == geos[i].bonegroups[n]) then
(
n +=1
o = 0
geos[i].bones[n] = #()
)
o += 1
geos[i].bones[n][o] = 1 + mdx.fReadLong()
local bool = true
for l=1 to geos[i].groups.count do
(
if geos[i].groups[l] == geos[i].bones[n][o] then
(
bool = false
exit
)
)
if bool == true then
(
local index = 1 + geos[i].groups.count
geos[i].groups[index] = geos[i].bones[n][o]
)
sort geos[i].groups
)
mdx.pos += 12
)
#UVAS:
(
mdx.fReadLong()
)
#UVBS:
(
geos[i].pnts.no = mdx.fReadLong()
for k=1 to geos[i].pnts.no do
(
local x = mdx.fReadFloat()
local y = 1 - mdx.fReadFloat()
pnts.txtrs[k] = [x,y,0]
)
j+=1
)
default:
(
local x
local y
local z
mdx.pos -= 4;
geos[i].bRad = mdx.fReadFloat()
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
geos[i].minExt = [y,-x,z]
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
geos[i].maxExt = [y,-x,z]
local nanim = mdx.fReadLong()
for j=1 to nanim do
(
mdx.pos += 28
)
)
)
curChunk = mdx.fReadHead()
)
geos[i].mesh = mesh vertices:pnts.verts \
faces:pvtx.faces
setNumTVerts geos[i].mesh pnts.txtrs.count
for k = 1 to pnts.txtrs.count do
(
setTVert geos[i].mesh k pnts.txtrs[k]
)
buildTVFaces geos[i].mesh
for k = 1 to pvtx.faces.count do
(
setTVFace geos[i].mesh k pvtx.faces[k]
)
for k = 1 to geos[i].pnts.no do
(
setNormal geos[i].mesh k pnts.nrmls[k]
)
geos[i].mesh.name = modelName + (i as string)
geobones[i] = #()
)
fn pgeoa mdx i=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
mdx.pos += 20
local frame = #()
local state = #()
local num
local ltype
local j = 1 + mdx.fReadLong()
if mdx.fReadHead() == #KGAO then
(
num = mdx.fReadLong()
ltype = mdx.fReadLong()
mdx.pos += 4
for k=1 to num do
(
frame[k] = mdx.fReadLong()
state[k] = mdx.fReadFloat()
)
)
animate on at time 0 geos[j].mesh.visibility = on
local c = bezier_float()
geos[j].mesh[1].controller = c
for k=1 to seqs.count do
(
local d = addNewKey c seqs[k].intStart
d.value = 1
d.inTangentType = #step
d.outTangentType = #step
)
for k=1 to frame.count do
(
local d = addNewKey c frame[k]
d.value = state[k]
d.inTangentType = #step
d.outTangentType = #step
)
)
fn fKG mdx head=
(
local x
local y
local z
local w
local pt
local prev
local time
local array = #()
local num = mdx.fReadLong()
local LineType = mdx.fReadLong()
mdx.pos += 4;
if head == #KGRT then
(
prev = quat 0 0 0 1
)
for j = 1 to num do
(
array[j] = trackPoint()
time = mdx.fReadLong()
array[j].time = time
if head == #KGRT then
(
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
w = mdx.fReadFloat()
pt = (quat y -x z w) - prev
prev = quat y -x z w
)
else
(
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
if head == #KGSC then pt = [y,x,z]
else pt = [y,-x,z]
)
array[j].point = pt
if LineType > 1 then
(
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
if head == #KGRT then
(
w = mdx.fReadFloat()
pt = ((quat y -x z w) as angleAxis)
)
else pt = [y,-x,z]
array[j].inTan = pt
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
if head == #KGRT then
(
w = mdx.fReadFloat()
pt = ((quat y -x z w) as angleAxis)
)
else pt = [y,-x,z]
array[j].outTan = pt
)
)
return array
)
fn fKV mdx head=
(
local array = #()
local num = mdx.fReadLong()
local LineType = mdx.fReadLong()
mdx.pos += 4;
for j = 1 to num do
(
array[j] = trackPoint()
mdx.pos += 4;
array[j].point = mdx.fReadFloat()
if LineType > 1 then
(
array[j].inTan = mdx.fReadFloat()
array[j].outTan = mdx.fReadFloat()
)
)
return array
)
fn pbone mdx=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
local name = mdx.fReadString 1
local i = 1 + mdx.fReadLong()
objs[i] = Bone()
objs[i].name = name
objs[i].parent = 1 + mdx.fReadLong()
mdx.pos += 4
while mdx.pos < endpos do
(
local curChunk = mdx.fReadHead()
case curChunk of
(
#KGTR:
(
objs[i].tr = fKG mdx curChunk
)
#KGRT:
(
objs[i].rt = fKG mdx curChunk
)
#KGSC:
(
objs[i].sc = fKG mdx curChunk
)
)
)
objs[i].id = 1 + mdx.fReadLong()
objs[i].aid = 1 + mdx.fReadLong()
if objs[i].id > 0 then geobones[objs[i].id][geobones[objs[i].id].count+1] = i
else
(
for k=1 to geobones.count do
(
append geobones[k] i
)
)
)
fn plite mdx=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
mdx.fReadLong()
local name = mdx.fReadString 1
local i = 1 + mdx.fReadLong()
objs[i] = Light()
objs[i].name = name
objs[i].parent = 1 + mdx.fReadLong()
mdx.pos += 4
objs[i].ltype = mdx.fReadLong()
objs[i].aStart = mdx.fReadFloat()
objs[i].aEnd = mdx.fReadFloat()
local r = mdx.fReadFloat()
local g = mdx.fReadFloat()
local b = mdx.fReadFloat()
objs[i].col = [255*r,255*g,255*b]
objs[i].int = mdx.fReadFloat()
local r = mdx.fReadFloat()
local g = mdx.fReadFloat()
local b = mdx.fReadFloat()
objs[i].ambCol = [255*r,255*g,255*b]
objs[i].ambInt = mdx.fReadFloat()
if mdx.fReadHead() == #KLAV then
objs[i].vis = fKV mdx #KLAV
else mdx.pos -= 4
)
fn phelp mdx=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
local name = mdx.fReadString 1
local i = 1 + mdx.fReadLong()
objs[i] = Helper()
objs[i].name = name
objs[i].parent = 1 + mdx.fReadLong()
mdx.pos += 4
while mdx.pos < endpos do
(
local curChunk = mdx.fReadHead()
case curChunk of
(
#KGTR:
(
objs[i].tr = fKG mdx curChunk
)
#KGRT:
(
objs[i].rt = fKG mdx curChunk
)
#KGSC:
(
objs[i].sc = fKG mdx curChunk
)
)
)
)
fn patch mdx=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
mdx.fReadLong()
local name = mdx.fReadString 1
local i = 1 + mdx.fReadLong()
objs[i] = Attachment()
objs[i].name = name
objs[i].parent = 1 + mdx.fReadLong()
mdx.pos += 4
mdx.pos += 264
while mdx.pos < endpos do
(
local curChunk = mdx.fReadHead()
case curChunk of
(
#KGTR:
(
objs[i].tr = fKG mdx curChunk
)
#KGRT:
(
objs[i].rt = fKG mdx curChunk
)
#KGSC:
(
objs[i].sc = fKG mdx curChunk
)
#KATV:
(
objs[i].vis = fKV mdx curChunk
)
)
)
)
fn ppre2 mdx=
(
local bytes = mdx.fReadLong()
local endpos = mdx.pos + bytes - 4
mdx.fReadLong()
local name = mdx.fReadString 1
local i = 1 + mdx.fReadLong()
objs[i] = PartEmitter()
objs[i].name = name
objs[i].parent = 1 + mdx.fReadLong()
mdx.pos += 4
mdx.pos += 264
while mdx.pos < endpos do
(
local curChunk = mdx.fReadHead()
case curChunk of
(
#KGTR:
(
objs[i].tr = fKG mdx curChunk
)
#KGRT:
(
objs[i].rt = fKG mdx curChunk
)
#KGSC:
(
objs[i].sc = fKG mdx curChunk
)
#KP2E:
(
objs[i].emissionrate = fKV mdx #KP2E
)
#KP2V:
(
objs[i].vis = fKV mdx curChunk
)
default:
(
mdx.pos -= 4
objs[i].speed = mdx.fReadFloat()
objs[i].variation = mdx.fReadFloat()
objs[i].latitude = mdx.fReadFloat()
objs[i].gravity = mdx.fReadFloat()
objs[i].lifespan = mdx.fReadFloat()
objs[i].emissionrate = mdx.fReadFloat()
objs[i].length = mdx.fReadFloat()
objs[i].width = mdx.fReadFloat()
mdx.pos += 4
objs[i].rows = mdx.fReadLong()
objs[i].columns = mdx.fReadLong()
mdx.pos += 4
objs[i].taillength = mdx.fReadFloat()
objs[i].time = mdx.fReadFloat()
objs[i].segCol[1] = [255*mdx.fReadFloat(),255*mdx.fReadFloat(),255*mdx.fReadFloat()]
objs[i].segCol[2] = [255*mdx.fReadFloat(),255*mdx.fReadFloat(),255*mdx.fReadFloat()]
objs[i].segCol[3] = [255*mdx.fReadFloat(),255*mdx.fReadFloat(),255*mdx.fReadFloat()]
objs[i].alpha = [mdx.fReadByte(),mdx.fReadByte(),mdx.fReadByte()]
objs[i].partSc = [mdx.fReadFloat(),mdx.fReadFloat(),mdx.fReadFloat()]
objs[i].LifeSpanUVAnim = [mdx.fReadLong(),mdx.fReadLong(),mdx.fReadLong()]
objs[i].DecayUVAnim = [mdx.fReadLong(),mdx.fReadLong(),mdx.fReadLong()]
objs[i].TailUVAnim = [mdx.fReadLong(),mdx.fReadLong(),mdx.fReadLong()]
objs[i].TailDecayUVAnim = [mdx.fReadLong(),mdx.fReadLong(),mdx.fReadLong()]
objs[i].TextureID = mdx.fReadLong()
mdx.pos += 12
)
)
)
)
fn makeBones rotState=
(
for i=1 to objs.count do
(
case objs[i].type of
(
#bone:
(
objs[i].end = pivot[i] + [10,0,0]
for j=1 to objs.count do
(
if objs[j] != undefined then
(
if objs[j].parent == i then
(
--objs[i].end = pivot[j]
exit
)
)
)
objs[i].mesh = BoneSys.createBone pivot[i] objs[i].end [0,10,0]
objs[i].mesh.name = objs[i].name
objs[i].mesh.boneScaleType = #none
)
#helper:
(
objs[i].mesh = point pos:pivot[i]
objs[i].mesh.name = objs[i].name
)
#light:
(
objs[i].mesh = omniLight pos:pivot[i] rgb:objs[i].col multiplier:objs[i].int
objs[i].mesh.name = objs[i].name
)
#attach:
(
objs[i].mesh = point pos:pivot[i]
objs[i].mesh.name = objs[i].name
)
)
)
max views redraw
for i=1 to objs.count do
(
if objs[i].parent != 0 then
(
objs[i].mesh.parent = objs[objs[i].parent].mesh
objs[i].mesh.pivot = pivot[objs[i].parent]
)
if (objs[i].type == #bone) or (objs[i].type == #helper) then
(
animate on
(
if objs[i].tr != undefined then
(
local c = bezier_position()
objs[i].mesh.pos.controller = c
for j=1 to objs[i].tr.count do
(
local pos = pivot[i] + objs[i].tr[j].point
local k = addNewKey c objs[i].tr[j].time
k.value = pos
if objs[i].tr == undefined then -- objs[i].tr[1].inTan != undefined then
(
k.inTangentType = #custom
k.inTangent = objs[i].tr[j].inTan
k.outTangentType = #custom
k.outTangent = objs[i].tr[j].outTan
)
else
(
k.inTangentType = #linear
k.outTangentType = #linear
)
)
)
if objs[i].sc != undefined then
(
local c = bezier_scale()
objs[i].mesh.scale.controller = c
for j=1 to objs[i].sc.count do
(
local k = addNewKey c objs[i].sc[j].time
k.value = objs[i].sc[j].point
if objs[i].sc == undefined then --objs[i].sc[1].inTan != undefined then
(
k.inTangentType = #custom
k.inTangent = objs[i].sc[j].inTan
k.outTangentType = #custom
k.outTangent = objs[i].sc[j].outTan
)
else
(
k.inTangentType = #linear
k.outTangentType = #linear
)
)
)
if (objs[i].rt != undefined) and (rotState == true) then
(
local c = tcb_rotation()
--if objs[i].rt[1].inTan == undefined then
--(
--c = linear_rotation()
--)
objs[i].mesh.rotation.controller = c
for j=1 to objs[i].rt.count do
(
local k = addNewKey c objs[i].rt[j].time
--local val = 0
--if j != 1 then
--val = objs[i].rt[j-1].point.angle
--k.value = (angleAxis (objs[i].rt[j].point.angle - val) objs[i].rt[j].point.axis)
k.value = objs[i].rt[j].point
)
)
)
)
)
)
fn skinning=
(
for i=1 to geos.count do
(
if geos[i].groups.count == 1 then
(
geos[i].mesh.parent = objs[geos[i].groups[1]].mesh
)
else
(
max modify mode
select geos[i].mesh
local gskin = skin()
addModifier geos[i].mesh gskin
local boneno = 0
for k=1 to geos[i].groups.count do
(
local index = geos[i].groups[k]
boneno += 1
skinops.addBone gskin objs[index].mesh 0
objs[index].no[i] = boneno
local no = skinOps.getNumberCrossSections gskin boneno
for l=1 to no do
(
skinOps.SetInnerRadius gskin boneno l 0
skinOps.SetOuterRadius gskin boneno l 0
)
)
for j=1 to geos[i].pnts.no do
(
local index = geos[i].pnts.group[j]
local n = geos[i].bones[index].count
local bones_arr = #()
local wghts_arr = #()
for k=1 to n do
(
append bones_arr objs[geos[i].bones[index][k]].no[i]
append wghts_arr ((1 as float)/n)
)
skinOps.SetVertexWeights gskin j bones_arr wghts_arr
)
)
)
)
fn fwriteString file string n=
(
arr = #(0x50,0x100,0x150)
for i=1 to arr[n] do
(
if i <= string.count then writeByte file (bit.charAsInt string[i])
else writeByte file 0
)
)
fn fwriteHead file string=
(
for i=1 to 4 do
(
writeByte file (bit.charAsInt string[i])
)
)
fn fileToPath file=
(
local array = filterString file "_"
local string = array[1]
for i=1 to array.count do
(
if i != 1 then
(
string += "\\" + array[i]
)
)
string
)
--------------------
-- User Interface --
--------------------
group "Import MDX"
(
radiobuttons geom "Animation:" labels:#("Static *","Object Visibility *", "No Skinning", "All") default:4 columns:1 align:#left
checkbox rotateCheck "Bone Rotation" checked:true
button importButton "Import MDX..."
label asterisk1 "* Renderable objects only" align:#left
)
group "Export MDX"
(
button exportButton "Export Selected as MDX..."
)
group "About"
(
label test "--Test Version--" align:#center
label pr "--for kdub & PR team--" align:#center
label version "MDX Importer/Exporter v2.0.1" align:#center
label author "Copyright \xa9 2002, Philip Laing" align:#center
)
--------------------------
-- Main Import Function --
--------------------------
on importButton pressed do
(
-- Show open file dialog box
local objFileName = getOpenFileName caption:"Import MDX" types:"WarCraft III MDX File (*.mdx)|*.mdx|All Files (*.*)|*.*|"
impTypes = geom.state
local isValid = true
if objFileName != undefined then
(
-- If user made a selection, begin importing
if doesFileExist objFileName then
(
seqs = #()
mtls = #()
geos = #()
objs = #()
pivot = #()
geobones = #()
-- currentPath = getFilenamePath objFileName
-- Open up the file as a binary stream
local bstream = fopen objFileName "rb"
local mdx = File()
mdx.Init bstream
if mdx.fReadHead() == #MDLX then
(
frameRate = 250
mdx.pos += 12
local curChunk = mdx.fReadHead()
local bytes = 0;
while (curChunk != undefined) and (mdx.pos < mdx.end) and (isValid) do
(
case curChunk of
(
#MODL:
(
--long nbytes
mdx.pos += 4
--ASCII Name (0x150 bytes)
modelName = mdx.fReadString 3
--long ???, ???
mdx.pos += 8
--float MinExtx, MinExty, MinExtz;
--float MaxExtx, MaxExty, MaxExtz;
--long BlendTime;
mdx.pos += 28
)
#SEQS:
(
bytes = mdx.fReadLong()
local nseqs = bytes/0x84
notes = NoteTrack "Sequences"
addNoteTrack trackViewNodes notes
for i=1 to nseqs do
(
pseqs mdx i
)
for i=1 to nseqs do
(
local k = addNewNoteKey notes seqs[i].intStart
k.value = seqs[i].name +
"\r\n" + (seqs[i].moveSpeed as string) +
"\r\n" + (seqs[i].noloop as string) +
"\r\n" + (seqs[i].rarity as string) +
"\r\n//KEY:\r\n//Sequence Name\r\n//Move Speed (0:static)\r\n//Loop (0:loop; 1:no loop)\r\n//Rarity (0:no rarity)"
k = addNewNoteKey notes seqs[i].intEnd
k.value = "<--"
)
)
#GLBS:
(
bytes = mdx.fReadLong()
local nglbs = bytes/4
for i=1 to nglbs do
(
local duration = mdx.fReadLong()
)
)
#MTLS:
(
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
local i=1
do
(
pmtls mdx i
i+=1;
) while mdx.pos < endpos
)
#GEOS:
(
max views redraw
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
local i=1
while mdx.pos < endpos do
(
pgeos mdx i
mdx.pos -= 4
i+=1;
)
)
#GEOA:
(
max views redraw
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 1 then
(
local i=1
while mdx.pos < endpos do
(
pgeoa mdx i
i+=1;
)
)
else
(
mdx.pos = endpos
)
max views redraw
)
#BONE:
(
max views redraw
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
while (mdx.pos < endpos) and isValid do
(
pbone mdx
)
)
else
(
mdx.pos = endpos
)
)
#LITE:
(
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
while (mdx.pos < endpos) and isValid do
(
plite mdx
)
)
else
(
mdx.pos = endpos
)
)
#HELP:
(
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
while (mdx.pos < endpos) and isValid do
(
phelp mdx
)
)
else
(
mdx.pos = endpos
)
)
#ATCH:
(
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
while (mdx.pos < endpos) and isValid do
(
patch mdx
)
)
else
(
mdx.pos = endpos
)
)
#PIVT:
(
max views redraw
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
local i = 1;
local x
local y
local z
while mdx.pos < endpos do
(
x = mdx.fReadFloat()
y = mdx.fReadFloat()
z = mdx.fReadFloat()
pivot[i] = [y,-x,z]
i += 1
)
makeBones rotateCheck.state
if impTypes > 3 then
(
skinning()
)
)
else
(
mdx.pos = endpos
)
)
#PRE2:
(
bytes = mdx.fReadLong()
local endpos = bytes + mdx.pos
if impTypes > 2 then
(
while (mdx.pos < endpos) and isValid do
(
ppre2 mdx
mdx.pos = endpos
)
)
else
(
mdx.pos = endpos
)
)
)
curChunk = mdx.fReadHead()
)
)
else messagebox "not MDX File"
if isValid == false then
messagebox "Error meant bones did not load"
fclose bstream
max views redraw
)
)
)
on exportButton pressed do
(
if selection.count == 0 then
messagebox "No objects selected" title:"Error"
else
(
-- Show open file dialog box
local objSaveFileName = getSaveFileName caption:"Import MDX" filename:(selection[1].name + ".mdx") types:"WarCraft III MDX File (*.mdx)|*.mdx|All Files (*.*)|*.*|"
-- If user made a selection, begin exporting
if objSaveFileName != undefined then
(
seqs = #()
mtls = #()
geos = #()
objs = #()
pivot = #()
geobones = #()
local geoa = #()
local geoInd = #()
local gmatId = #()
local mats = #()
local maps = #()
-- Open up the file as a binary stream
local mdx = fopen objSaveFileName "wb"
local ngeos = 0
local ngeoa = 0
local ngeoakeys = 0
local nobjs = 0
local mapOffset = 0
local nblend = 0
local bytes
local error = "" -- Notes & Errors in conversion
if (numnotetracks trackviewNodes) > 0 then
(
local notes = getNoteTrack trackviewNodes 1
for i=1 to (notes.keys.count/2) do
(
seqs[i] = Sequence()
local value = filterString notes.keys[(i*2)-1].value "\n\r"
seqs[i].name = value[1]
seqs[i].moveSpeed = if value[2] == undefined then 0
else (value[2] as integer)
seqs[i].noloop = if value[3] == undefined then 0
else (value[3] as integer)
seqs[i].rarity = if value[4] == undefined then 0
else (value[4] as integer)
local frame = (notes.keys[(i*2)-1].time as string)
replace frame frame.count 1 ""
seqs[i].intStart = frame as integer
frame = (notes.keys[i*2].time as string)
replace frame frame.count 1 ""
seqs[i].intEnd = frame as integer
)
)
else
(
error += "Sequences not found"
)
print "selection"
for i=1 to selection.count do
(
case classOf selection[i] of
(
Omnilight: --LITE
(
)
targetSpot: --CAMS
(
)
Point: --ATCH
(
)
default: --GEOS
(
ngeos += 1
geoa[ngeos] = undefined
local matId
if ngeos > 1 then
(
for j=1 to mats.count do
(
if selection[i].material == selection[mats[j][1]].material then
(
matId = j-1
)
)
)
if matId == undefined then
(
local fmode = 0
local shading = 0
local mapId
if selection[i].material != undefined then
(
if selection[i].material.opacityMap != undefined then
(
fmode = 1
)
else
(
if selection[i].material.diffuseMap != undefined then
(
if selection[i].material.diffuseMap.alphasource == 0 then
(
fmode = 2
nblend += 1
)
)
)
if selection[i].material.twoSided == true then
(
shading += 16
)
if ngeos > 1 then
(
if selection[i].material.diffuseMap == undefined then
(
mapId = 0
mapOffset = 1
)
else
(
for j=1 to maps.count do
(
if selection[i].material.diffuseMap.filename == maps[j] then
(
mapId = j
)
)
)
)
)
else
(
mapId = 0
mapOffset = 1
)
if mapId == undefined then
(
mapId = maps.count + 1
if selection[i].material.diffuseMap != undefined then
(
append maps selection[i].material.diffuseMap.filename
)
)
matId = mats.count
append mats #(ngeos,fmode,shading,mapId)
)
gmatId[ngeos] = matId
if (selection[i][1].controller != undefined) and (selection[i][1].controller.keys.count > 1) then
(
local visKeys = #()
local keyArr = selection[i][1].controller.keys
for j=1 to keyArr.count do
(
if keyArr[j].value != 1 then
(
if geoa[ngeos] == undefined then
(
geoa[ngeos] = #()
ngeoa += 1
)
for k=1 to seqs.count do
(
if (keyArr[j].time < seqs[k].intEnd) and
(keyArr[j].time > seqs[k].intStart) then
(
if keyArr[j-1].time < seqs[k].intStart then
(
append geoa[ngeos] keyArr[j]
geoa[ngeos][geoa[ngeos].count].time = seqs[k].intStart
geoa[ngeos][geoa[ngeos].count].value = 1
)
)
)
append geoa[ngeos] keyArr[j]
ngeoakeys += 1
)
else
(
local bool = true
for k=1 to seqs.count do
(
if (keyArr[j].time == seqs[k].intStart) and
((j == keyArr.count) or
(keyArr[j+1].time > seqs[k].intEnd)) then
(
bool = false
)
)
if keyArr[j].time == 0 then
(
bool = false
)
if bool == true then
(
if geoa[ngeos] == undefined then
(
geoa[ngeos] = #()
ngeoa += 1
)
append geoa[ngeos] keyArr[j]
ngeoakeys += 1
)
)
)
)
geoInd[ngeos] = i
geos[ngeos] = Geometry()
geos[ngeos].pnts.no = selection[i].mesh.numverts
geos[ngeos].pvtx.crns = 3*selection[i].mesh.numfaces
geos[ngeos].minExt = #()
geos[ngeos].maxExt = #()
geos[ngeos].bRad = #()
geos[ngeos].minExt[1] = selection[i].min
geos[ngeos].maxExt[1] = selection[i].max
geos[ngeos].bRad[1] = length selection[i].mesh.verts[1].pos
for j=1 to selection[i].mesh.numverts do
(
if length selection[i].mesh.verts[j].pos > geos[ngeos].bRad[1] then
geos[ngeos].bRad[1] = length selection[i].mesh.verts[j].pos
)
for j=1 to seqs.count do
(
geos[ngeos].minExt[j+1] = geos[ngeos].minExt[1]
geos[ngeos].maxExt[j+1] = geos[ngeos].maxExt[1]
geos[ngeos].bRad[j+1] = geos[ngeos].bRad[1]
if 1 == 0 then --for k=seqs[j].intStart to seqs[j].intEnd do
(
geos[ngeos].bRad[j+1] = at time k length selection[i].mesh.verts[1].pos
if at time k selection[i].min.x < geos[ngeos].minExt[j+1].x then
geos[ngeos].minExt[j+1].x = at time k selection[i].min.x
if at time k selection[i].min.y < geos[ngeos].minExt[j+1].y then
geos[ngeos].minExt[j+1].y = at time k selection[i].min.y
if at time k selection[i].min.z < geos[ngeos].minExt[j+1].z then
geos[ngeos].minExt[j+1].z = at time k selection[i].min.z
if at time k selection[i].max.x > geos[ngeos].maxExt[j+1].x then
geos[ngeos].maxExt[j+1].x = at time k selection[i].max.x
if at time k selection[i].max.y > geos[ngeos].maxExt[j+1].y then
geos[ngeos].maxExt[j+1].y = at time k selection[i].max.y
if at time k selection[i].max.z > geos[ngeos].maxExt[j+1].z then
geos[ngeos].maxExt[j+1].z = at time k selection[i].max.z
for l=2 to selection[i].mesh.numverts do
(
if at time k length selection[i].mesh.verts[l].pos > geos[ngeos].bRad[j+1] then
geos[ngeos].bRad[j+1] = length selection[i].mesh.verts[l].pos
)
)
)
)
)
)
for i=1 to seqs.count do
(
seqs[i].minExt = geos[1].minExt[i+1]
seqs[i].maxExt = geos[1].maxExt[i+1]
seqs[i].bRad = geos[1].bRad[i+1]
for j=2 to geos.count do
(
if geos[j].minExt[i+1].x < seqs[i].minExt.x then
seqs[i].minExt.x = geos[j].minExt[i+1].x
if geos[j].minExt[i+1].y < seqs[i].minExt.y then
seqs[i].minExt.y = geos[j].minExt[i+1].y
if geos[j].minExt[i+1].z < seqs[i].minExt.z then
seqs[i].minExt.z = geos[j].minExt[i+1].z
if geos[j].maxExt[i+1].x > seqs[i].maxExt.x then
seqs[i].maxExt.x = geos[j].maxExt[i+1].x
if geos[j].maxExt[i+1].y > seqs[i].maxExt.y then
seqs[i].maxExt.y = geos[j].maxExt[i+1].y
if geos[j].maxExt[i+1].z > seqs[i].maxExt.z then
seqs[i].maxExt.z = geos[j].maxExt[i+1].z
if geos[j].bRad[i+1] > seqs[i].bRad then
seqs[i].bRad = geos[j].bRad[i+1]
)
)
-----------------
-- MDX Writing --
-----------------
print "MDX Writing"
-- MDLX: MDX Header
fwriteHead mdx "MDLX"
-- VERS: Version
fwriteHead mdx "VERS"
writeLong mdx 4 -- byte count
writeLong mdx 800
-- MODL: Model Info
fwriteHead mdx "MODL"
writeLong mdx 372 -- byte count
-- Name
local parse = filterString objSaveFileName "\/."
name = parse[parse.count-1]
fwriteString mdx name 3
writeLong mdx 0 -- unknown (0)
writeFloat mdx 0 -- Bounds Radius (0 for units)
-- Minimum Extent
writeFloat mdx (-selection.max.y)
writeFloat mdx selection.min.x
writeFloat mdx selection.min.z
-- Maximum Extent
writeFloat mdx (-selection.min.y)
writeFloat mdx selection.max.x
writeFloat mdx selection.max.z
writeLong mdx 150 -- Blend Time (150)
-- SEQS: Sequences
fwriteHead mdx "SEQS"
writeLong mdx (132*seqs.count) -- byte count
for i=1 to seqs.count do
(
fwriteString mdx seqs[i].name 1
writeLong mdx seqs[i].intStart
writeLong mdx seqs[i].intEnd
writeFloat mdx seqs[i].moveSpeed
writeLong mdx seqs[i].noloop
writeFloat mdx seqs[i].rarity
writeLong mdx 0 -- unknown (0)
writeFloat mdx seqs[i].bRad -- Bounds Radius
-- Minimum Extent
writeFloat mdx (-seqs[i].maxExt.y)
writeFloat mdx seqs[i].minExt.x
writeFloat mdx seqs[i].minExt.z
-- Maximum Extent
writeFloat mdx (-seqs[i].minExt.y)
writeFloat mdx seqs[i].maxExt.x
writeFloat mdx seqs[i].maxExt.z
)
-- GLBS: Globals
-- 0x53424C47
-- MTLS: Materials
fwriteHead mdx "MTLS"
writeLong mdx (48*mats.count + 28*nblend) -- byte count
for i=1 to mats.count do
(
if mats[i][2] > 1 then
(
writeLong mdx 76 -- byte count
writeLong mdx 0
writeLong mdx 0
-- LAYS: Layers
fwriteHead mdx "LAYS"
writeLong mdx 2 -- Layers Count
writeLong mdx 28 -- byte count (inclusive)
-- FilterMode (0:none;1:trans;2:blend;3:add)
writeLong mdx 0
-- Shading (1:unshaded;+16:two sided;+32:unfogged)
writeLong mdx 1
writeLong mdx 0 -- TextureID
writeLong mdx -1
writeLong mdx 0
writeFloat mdx 1
)
else
(
writeLong mdx 48 -- byte count
writeLong mdx 0
writeLong mdx 0
-- LAYS: Layers
fwriteHead mdx "LAYS"
writeLong mdx 1 -- Layers Count
)
writeLong mdx 28 -- byte count (inclusive)
-- FilterMode (0:none;1:trans;2:blend;3:add)
writeLong mdx mats[i][2]
-- Shading (1:unshaded;+16:two sided;+32:unfogged)
writeLong mdx mats[i][3]
writeLong mdx (mats[i][4]+mapOffset-1) -- TextureID
writeLong mdx -1
writeLong mdx 0
writeFloat mdx 1
-- KMTA: Alpha
-- 0x41544D4B
)
-- TEXS: Textures
fwriteHead mdx "TEXS"
writeLong mdx (268*(1+maps.count))-- byte count
writeLong mdx 1
fwriteString mdx "" 2
writeLong mdx 0
writeLong mdx 0
if mapOffset == 10 then
(
writeLong mdx 0
fwriteString mdx ("Textures\\"+name+".blp") 2
writeLong mdx 0
writeLong mdx 0
)
for i=1 to maps.count do
(
writeLong mdx 0
local old_path = filterString maps[i] "\/."
local blp_path = fileToPath old_path[old_path.count-1]
fwriteString mdx (blp_path + ".blp") 2
writeLong mdx 0
writeLong mdx 0
)
max modify mode
-- GEOS: Geometry Sets
fwriteHead mdx "GEOS"
local bytepos = ftell mdx
local gbytes = #()
bytes = 0
for i=1 to geos.count do
(
gbytes[i] = 136+(33*geos[i].pnts.no)+(2*geos[i].pvtx.crns)+(28*seqs.count)
bytes += gbytes[i]
)
writeLong mdx bytes -- byte count
for i=1 to geos.count do
(
local ibytepos = ftell mdx
local texVerts = #()
writeLong mdx gbytes[i] -- byte count (inclusive)
-- VRTX: Vertices
fwriteHead mdx "VRTX"
writeLong mdx geos[i].pnts.no
for j=1 to geos[i].pnts.no do
(
local point = selection[geoInd[i]].mesh.verts[j].pos
writeFloat mdx -point.y
writeFloat mdx point.x
writeFloat mdx point.z
)
-- NRMS: Normals
fwriteHead mdx "NRMS"
writeLong mdx geos[i].pnts.no
for j=1 to geos[i].pnts.no do
(
local point = getNormal selection[geoInd[i]].mesh j
writeFloat mdx -point.y
writeFloat mdx point.x
writeFloat mdx point.z
)
-- PTYP: Primitive Type
fwriteHead mdx "PTYP"
writeLong mdx 1 -- unknown (0)
writeLong mdx 4 -- unknown (0)
-- PCNT: Primitive Corners
fwriteHead mdx "PCNT"
writeLong mdx 1 -- unknown (0)
writeLong mdx geos[i].pvtx.crns -- No of Corners
-- PVTX: Primitive Vertices
fwriteHead mdx "PVTX"
writeLong mdx geos[i].pvtx.crns -- No of Corners
for j=1 to (geos[i].pvtx.crns/3) do
(
local point = getFace selection[geoInd[i]].mesh j
local texFace = getTVFace selection[geoInd[i]].mesh j
texVerts[point.x] = texFace.x
texVerts[point.y] = texFace.y
texVerts[point.z] = texFace.z
writeShort mdx (point.x-1)
writeShort mdx (point.y-1)
writeShort mdx (point.z-1)
)
-- GNDX: Vertex Groups
fwriteHead mdx "GNDX"
writeLong mdx geos[i].pnts.no
local grouplist = #()
local numgroups = 0
local numbones = 0
for j=1 to geos[i].pnts.no do
(
try
(
local nbones = skinOps.GetVertexWeightCount selection[geoInd[i]].skin j
local ids = #()
for k=1 to nbones do
(
if (skinOps.GetVertexWeight selection[geoInd[i]].skin j k) > (1/(2*nbones)) then
(
local boneid = skinOps.GetVertexWeightBoneID selection[geoInd[i]].skin j k
local bonename = skinOps.GetBoneName selection[geoInd[i]].skin boneid 0
if findItem geobones bonename == 0 do
(
append geobones bonename
)
append ids (findItem geobones bonename)
)
)
sort ids
local idstring = ""
for id in ids do
(
idstring += (id as string) + ","
)
if findItem grouplist idstring == 0 do
(
append grouplist idstring
numgroups += 1
numbones += nbones
)
writeByte mdx (findItem grouplist idstring - 1) -- Group Byte
)
catch
(
numgroups = 1
numbones = 1
writeByte mdx 0 --geos[i].pnts.group[j] -- Group Byte
if (j == 1) then
(
if (selection[geoInd[i]].parent != undefined) then
(
if findItem geobones selection[geoInd[i]].parent.name == 0 then
(
append geobones selection[geoInd[i]].parent.name
)
append grouplist ((findItem geobones selection[geoInd[i]].parent.name) as string)
)
else
(
if findItem geobones "" == 0 do
(
append geobones ""
)
append grouplist ((findItem geobones "") as string)
)
)
)
)
-- MTGC: Matrices Group Count
fwriteHead mdx "MTGC"
writeLong mdx numgroups -- No of Matrices
for matrix in grouplist do
(
local split = filterString matrix ","
writeLong mdx split.count -- No of Bones in Group
)
gbytes[i] += (numgroups * 4)
bytes += (numgroups * 4)
-- MATS: Matrices
fwriteHead mdx "MATS"
writeLong mdx numbones -- No of Bones
for matrix in grouplist do
(
local split = filterString matrix ","
for part in split do
(
writeLong mdx ((part as integer)-1) -- Bone No
)
)
gbytes[i] += (numbones * 4)
bytes += (numbones * 4)
writeLong mdx gmatId[i] -- MaterialID
writeLong mdx 0
writeLong mdx 0
writeFloat mdx geos[i].bRad[1] -- BoundsRadius
-- Minimum Extent
writeFloat mdx -geos[i].maxExt[1].y
writeFloat mdx geos[i].minExt[1].x
writeFloat mdx geos[i].minExt[1].z
-- Maximum Extent
writeFloat mdx -geos[i].minExt[1].y
writeFloat mdx geos[i].maxExt[1].x
writeFloat mdx geos[i].maxExt[1].z
writeLong mdx seqs.count -- Bone No
for j=1 to seqs.count do
(
writeFloat mdx geos[i].bRad[j+1] -- BoundsRadius
-- Minimum Extent
writeFloat mdx -geos[i].maxExt[j+1].y
writeFloat mdx geos[i].minExt[j+1].x
writeFloat mdx geos[i].minExt[j+1].z
-- Maximum Extent
writeFloat mdx -geos[i].minExt[j+1].y
writeFloat mdx geos[i].maxExt[j+1].x
writeFloat mdx geos[i].maxExt[j+1].z
)
-- UVAS: ???
fwriteHead mdx "UVAS"
writeLong mdx 1 -- unknown (0)
-- UVBS: Texture Coordinates
fwriteHead mdx "UVBS"
writeLong mdx geos[i].pnts.no
for j=1 to geos[i].pnts.no do
(
local point = getTVert selection[geoInd[i]].mesh texVerts[j]
writeFloat mdx point.x
writeFloat mdx (1 - point.y)
)
local cpos = ftell mdx
fseek mdx ibytepos #seek_set
writeLong mdx gbytes[i]
fseek mdx cpos #seek_set
)
local cpos = ftell mdx
fseek mdx bytepos #seek_set
writeLong mdx bytes
fseek mdx cpos #seek_set
-- GEOA: Geometry Animation
fwriteHead mdx "GEOA"
writeLong mdx ((44*geos.count)+(8*ngeoakeys)+(8*(geos.count-ngeoa))) -- byte count
for i=1 to geos.count do
(
if geoa[i] != undefined then
(
writeLong mdx (44+(8*geoa[i].count))
writeFloat mdx 1
writeFloat mdx 0
writeFloat mdx 1
writeFloat mdx 1
writeFloat mdx 1
writeLong mdx (i-1)
-- KGAO: Animated Opacity Track
fwriteHead mdx "KGAO"
writeLong mdx geoa[i].count
writeLong mdx 0
writeLong mdx -1
for j=1 to geoa[i].count do
(
local frame = (geoa[i][j].time as string)
replace frame frame.count 1 ""
writeLong mdx (frame as integer)
writeFloat mdx geoa[i][j].value
)
)
else
(
writeLong mdx 52
writeFloat mdx 1
writeFloat mdx 0
writeFloat mdx 1
writeFloat mdx 1
writeFloat mdx 1
writeLong mdx (i-1)
-- KGAO: Animated Opacity Track
fwriteHead mdx "KGAO"
writeLong mdx 1
writeLong mdx 0
writeLong mdx -1
-- Single Key
writeLong mdx 0
writeFloat mdx 1
)
)
-- BONE: Bones
fwriteHead mdx "BONE"
local xbytes = 0
for bonename in geobones do
(
xbytes += 104
if bonename != "" then
(
local cbone = getNodeByName bonename exact:true
if cbone.pos.controller.keys.count != 0 then
(
xbytes += 16 + (16*cbone.pos.controller.keys.count)
)
if cbone.rotation.controller.keys.count != 0 then
(
xbytes += 16 + (20*cbone.rotation.controller.keys.count)
)
if cbone.scale.controller.keys.count != 0 then
(
xbytes += 16 + (16*cbone.scale.controller.keys.count)
)
)
)
writeLong mdx xbytes -- byte count
-- struct Bones
local obID = 0
for bonename in geobones do
(
local incbytes = 96
if bonename == "" then
(
writeLong mdx incbytes -- byte count (inclusive)
fwriteString mdx "Default" 1 -- Name (0x50 bytes)
writeLong mdx obID
writeLong mdx -1
writeLong mdx 256
)
else
(
local cbone = getNodeByName bonename exact:true
if cbone.pos.controller.keys.count != 0 then
(
incbytes += 16 + (16*cbone.pos.controller.keys.count)
)
if cbone.rotation.controller.keys.count != 0 then
(
incbytes += 16 + (20*cbone.rotation.controller.keys.count)
)
if cbone.scale.controller.keys.count != 0 then
(
incbytes += 16 + (16*cbone.scale.controller.keys.count)
)
writeLong mdx incbytes -- byte count (inclusive)
fwriteString mdx cbone.name 1 -- Name (0x50 bytes)
writeLong mdx obID
writeLong mdx -1
writeLong mdx 256
-- KGTR: Translation Track
if cbone.pos.controller.keys.count != 0 then
(
fwriteHead mdx "KGTR"
writeLong mdx cbone.pos.controller.keys.count
writeLong mdx 1
writeLong mdx -1
for key in cbone.pos.controller.keys do
(
local frame = (key.time as string)
replace frame frame.count 1 ""
writeLong mdx (frame as integer)
writeFloat mdx (-key.value.y + cbone.pos.y)
writeFloat mdx (key.value.x - cbone.pos.x)
writeFloat mdx (key.value.z - cbone.pos.z)
)
)
-- KGRT: Rotation Track
if cbone.rotation.controller.keys.count != 0 then
(
fwriteHead mdx "KGRT"
writeLong mdx cbone.rotation.controller.keys.count
writeLong mdx 1
writeLong mdx -1
local prev = (quat 0 0 0 1)
for key in cbone.rotation.controller.keys do
(
local frame = (key.time as string)
replace frame frame.count 1 ""
writeLong mdx (frame as integer)
kquat = (key.value as quat) + prev
writeFloat mdx -kquat.y
writeFloat mdx kquat.x
writeFloat mdx kquat.z
writeFloat mdx kquat.w
prev = kquat
)
)
-- KGSC: Scale Track
if cbone.scale.controller.keys.count != 0 then
(
fwriteHead mdx "KGSC"
writeLong mdx cbone.scale.controller.keys.count
writeLong mdx 1
writeLong mdx -1
for key in cbone.scale.controller.keys do
(
local frame = (key.time as string)
replace frame frame.count 1 ""
writeLong mdx (frame as integer)
writeFloat mdx key.value.y
writeFloat mdx key.value.x
writeFloat mdx key.value.z
)
)
)
writeLong mdx -1
writeLong mdx 0
obID += 1
)
-- LITE: Lights
-- KLAV: Visibility Track
-- HELP: Helpers
-- KGTR: Translation Track
-- KGRT: Rotation Track
-- KGSC: Scale Track
-- ATCH: Attachments
-- KATV: Visibility Track
-- PIVT: Pivots
fwriteHead mdx "PIVT"
writeLong mdx (geobones.count*12)
for bonename in geobones do
(
if bonename == "" then
(
writeFloat mdx 0 --writeFloat mdx pivot[i].x
writeFloat mdx 0 --writeFloat mdx pivot[i].y
writeFloat mdx 0 --writeFloat mdx pivot[i].z
)
else
(
local cbone = getNodeByName bonename exact:true
writeFloat mdx -cbone.pos.y
writeFloat mdx cbone.pos.x
writeFloat mdx cbone.pos.z
)
)
-- PRE2: Particle Emitters
-- KGTR: Translation Track
-- KGRT: Rotation Track
-- KGSC: Scale Track
-- KP2V: Visibility Track
-- CAMS: Cameras
-- EVTS: Events
-- KEVT: Event Track
-- CLID: Collision Shapes
-- KGTR: Translation Track
-- KGRT: Rotation Track
-- KGSC: Scale Track
messagebox "Model exported successfully!" title:"MDX Output" beep:false
fclose mdx
)
)
)
)
--getNodeByName <string> exact:<boolean>