• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a faction for Warcraft 3 and enter Hive's 19th Techtree Contest: Co-Op Commanders! Click here to enter!
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 21st Texturing Contest: Upgrade is now concluded, time to vote for your favourite set of icons! Click here to vote!

mdx question

Status
Not open for further replies.
Level 25
Joined
Mar 31, 2004
Messages
4,471
I can't understand what you're asking, but I think you should be asking if anyone has made a file for 3DS Max that can handle Warcraft

And I think one was made, but it doesn't work 100%. Do yourself a favour and grab 3DS Max 4 or 5
 
Level 8
Joined
Oct 12, 2004
Messages
186
I wish I could even find a copy of 3DS Max 4 o 5 on bit torrent, but they only have version 6 and 7.

What I want to know is what am I allowed to use in my models on 3DS Max 7. and if my model has stuff not allowed in warcraft 3 models how do i remove it and still keep my animations.
 
Level 8
Joined
Oct 12, 2004
Messages
186
MDX importer/exporter script:
Code:
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>

Screenshots of error messages download link:
http://files.filefront.com/error_screenshotszip/;4253083;;/fileinfo.html
 
Level 25
Joined
Mar 31, 2004
Messages
4,471
Oh, so you want to know what things in 3DS Max are used in Warcraft?

I'll just say "None" because I doubt the particle emitters, lights and other such things are the same as in Warcraft, and making them in .mdl for you will result in less questions about a program which I'm surprised even HAS an exporter and no one who's anyone in the Warcraft moddding world actually uses
 
Level 8
Joined
Oct 12, 2004
Messages
186
well my tools don't work with anything but 3DS Max 6 and 7. If know of any way to convert 3ds 7 files to 3ds 4 or 5 and can get me a FREE copy of 3ds 4 or 5 then I'll switch to 3ds max 4 or 5, otherwise i need a way to export 3ds 7 models to mdx or mdl with no problems.
 
Status
Not open for further replies.
Top