Skip to content

Instantly share code, notes, and snippets.

@The-Meth0d
Last active December 28, 2023 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save The-Meth0d/6d350f0654ed042bb11afb75a07dd0a9 to your computer and use it in GitHub Desktop.
Save The-Meth0d/6d350f0654ed042bb11afb75a07dd0a9 to your computer and use it in GitHub Desktop.
MX Vs ATV Unleashed DXG Importer - Maxscript
/*
Name: DXG Importer (v1.0)
Game: MX vs. ATV: Unleashed - PC
Author: Leo aka "Meth0d" / https://meth0d.org
--------------------------------------------------
Imports DXG (3D Models) from the game.
Usage: https://www.youtube.com/watch?v=aC6Rjfodhnw
--------------------------------------------------
It's an unfinished script, but it works with major DXG files.
*/
clearlistener()
global modelScale = 1
global debugMode = true
-- Right To Left Coord System
function R2L coord =
(
return ([coord.x,-coord.z,coord.y] * modelScale)
)
function WriteLog txt =
(
if debugMode then print (" " + txt)
)
function ReadFixedString stream len =
(
local str = ""
for x = 1 to len do
(
cbyte = readbyte stream
if cbyte != 0x00 then str += bit.intaschar(cbyte)
)
str
)
struct PolyMesh
(
ID = 0,
MatID = 0,
VertsCount = 0,
FacesCount = 0,
FacesArray = #(),
VertsArray = #(),
NormalsArray = #(),
VertexColors = #(),
UVsArray = #()
)
MeshArr = #()
MaterialsArr = #()
BonesArr = #()
-- file settings
filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\helmet.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\nat05_outhouse.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\alt-02_stadium-01.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\palm01.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\airider.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\rcacrowd.dxg"
--filepath = @"C:\Users\Leonardo\Desktop\Pratica\MX Unleashed\bike50.dxg"
WriteLog("File: " + filepath as string)
-- binary reader (open file)
f = fopen filepath "rb"
CurrentDir = getFilenamePath filepath
-- file header
Magic = readlong f
WriteLog("Magic: " + Magic as string)
if Magic == 6781028 then
(
Version = readlong f
WriteLog("Version: " + Version as string)
if Version == 5 then
(
-- [ BONES BLOCK ] --------------------------------------
-- 224 bytes per bone
-- TODO
BonesCount = readlong f
WriteLog("--- [ BONES BLOCK ] ---")
WriteLog("Bones Count: " + BonesCount as string)
for bc = 1 to BonesCount do
(
-- Bone Name
bone_name = ReadFixedString f 128
-- Bone Matrix Data
m11 = readfloat f; m12 = readfloat f; m13 = readfloat f; m14 = readfloat f;
m21 = readfloat f; m22 = readfloat f; m23 = readfloat f; m24 = readfloat f;
m31 = readfloat f; m32 = readfloat f; m33 = readfloat f; m34 = readfloat f;
m41 = readfloat f; m42 = readfloat f; m43 = readfloat f; m44 = readfloat f;
-- Position Data
BPosX = readfloat f
BPosY = readfloat f
BPosZ = readfloat f
-- Dimensions Data
dimX = readfloat f
dimY = readfloat f
dimZ = readfloat f
-- Unknown
unkBone0 = readfloat f
-- ParentBone ID
parentBoneID = readlong f
tfm = (matrix3 [m11, m12, m13] [m21, m22, m23] [m31, m32, m33] ([m41, m42, m43] * m44 * modelScale) )
-----------------------------------------
--cBone = dummy showLinks:true showLinksOnly:true
cBone = bonesys.createbone [0,0,0] [0,0,0] [0,0,0]
cBone.showlinks = true
cBone.showlinksonly = true
cBone.wirecolor = yellow
cBone.name = bone_name
cBone.transform = tfm
-- Transform Matrix are related to previous bone
if parentBoneID > -1 then
(
cBone.parent = BonesArr[parentBoneID + 1]
cBone.transform *= cBone.parent.transform
)
--print cBone.transform
-- Add to BonesArray for Later Use
append BonesArr cBone
WriteLog("["+ bc as string + "] Bone Name: " + bone_name)
WriteLog(" - Transform: " + tfm as string)
WriteLog(" - Positions: X: " + BPosX as string + " | Y: " + BPosY as string + " | Z:" + BPosZ as string)
WriteLog(" - Dimensions: X: " + dimX as string + " | Y: " + dimY as string + " | Z: " + dimZ as string)
WriteLog(" - Unknown: " + unkBone0 as string);
WriteLog(" - Parent ID: " + parentBoneID as string)
-----------------------------------------
)
--for i in 1 to BonesCount do BonesArr[i].resetbonestretch()
-- [ MATERIALS BLOCK ] --------------------------------------
-- 64 bytes per material
-- It only includes the name, it's the same name for the texture
MaterialsCount = readlong f
WriteLog("--- [ MATERIALS BLOCK ] ---")
WriteLog("Materials Count: " + MaterialsCount as string)
for mc = 1 to MaterialsCount do
(
material_name = ReadFixedString f 64
WriteLog(" ["+ mc as string + "] Material Name: " + material_name)
-- Texture
tm = Bitmaptexture filename:(CurrentDir + material_name + ".dds")
-- Create Material as Standard
mat = standardMaterial()
mat.name = material_name
mat.showinviewport = true
mat.twosided = false
mat.diffuseMap = tm
-- Support Alpha Textures
mat.opacityMap = tm
mat.opacityMap.monoOutput = 1
-- Save Current Material on Array
append MaterialsArr mat
)
-- [ MODEL FLAGS BLOCK ] --------------------------------------
WriteLog("--- [ MODEL FLAGS BLOCK ] ---")
MeshFramesCount = readbyte f #unsigned -- sometimes 5, some 1
MeshFramesFlag = readbyte f #unsigned -- sometimes 1, some 0
Always0_1 = readbyte f #unsigned -- 0
Always0_2 = readbyte f #unsigned -- 0
WriteLog(" - Mesh Frames Count: " + MeshFramesCount as string)
WriteLog(" - Mesh Frames Flag: " + MeshFramesFlag as string)
WriteLog(" - Always 0: " + Always0_1 as string)
WriteLog(" - Always 0: " + Always0_2 as string)
-- MESH FRAMES BLOCK ] --------------------------------------
WriteLog("--- [ MESH FRAMES BLOCK ] ---")
currentMesh = 1
do
(
print "----------------- MESH FRAME START -----------------"
-- MESH FRAME SETTINGS
MFS_U0 = readbyte f #unsigned -- 255
MFS_U1 = readbyte f #unsigned -- 255
MFS_U2 = readbyte f #unsigned -- 255
MFS_U3 = readbyte f #unsigned -- 255
WriteLog(" - MFS_U0: " + MFS_U0 as string)
WriteLog(" - MFS_U1: " + MFS_U1 as string)
WriteLog(" - MFS_U2: " + MFS_U2 as string)
WriteLog(" - MFS_U3: " + MFS_U3 as string)
MeshesCount = readlong f
WriteLog(" - Meshes Count on Current Frame: " + MeshesCount as string)
-- For Each Mesh on Current Mesh Frame
for i = 1 to MeshesCount do
(
-- Start a New Mesh Block
PM = PolyMesh()
-- Current Mesh Data
PM.ID = readlong f
PM.MatID = currentMesh
Mesh_Unk0 = readlong f -- unk (71 | 79)
Mesh_Unk1 = readlong f -- always 1
Mesh_Unk2 = readshort f -- always 0
Mesh_Unk3 = readbyte f #unsigned -- unk
Mesh_Unk33 = readbyte f #unsigned -- unk
Mesh_Unk4 = readbyte f #unsigned -- unk
Mesh_Unk44 = readbyte f #unsigned -- unk
PM.VertsCount = readshort f
PM.FacesCount = readshort f
WriteLog(" [ Current Mesh Frame Settings")
WriteLog(" - Mesh ID: " + (PM.ID) as string)
WriteLog(" - Unk0: " + Mesh_Unk0 as string)
WriteLog(" - Unk1: " + Mesh_Unk1 as string)
WriteLog(" - Unk2: " + Mesh_Unk2 as string)
WriteLog(" - Unk3: " + Mesh_Unk3 as string)
WriteLog(" - Unk33: " + Mesh_Unk33 as string)
WriteLog(" - Unk4: " + Mesh_Unk4 as string)
WriteLog(" - Unk44: " + Mesh_Unk44 as string)
WriteLog(" - Vertices Count: " + PM.VertsCount as string)
WriteLog(" - Faces Count: " + PM.FacesCount as string)
--------- Faces Block ---------
WriteLog(" - ** [Reading Faces]")
local TriStripsArr = #()
for x0 = 1 to PM.FacesCount do
(
-- Read face by face and append to array
append TriStripsArr (readshort f)
)
-- Convert TriStrip to Trilist
for x1 = 1 to TriStripsArr.count - 2 do
(
tfa = TriStripsArr[x1]
tfb = TriStripsArr[x1+1]
tfc = TriStripsArr[x1+2]
if((tfa != tfb) and (tfa != tfc) and (tfc != tfb)) do
(
if mod x1 2 == 0 then append PM.FacesArray [tfc+1, tfb+1, tfa+1] else append PM.FacesArray [tfb+1, tfc+1, tfa+1]
)
)
-- Clear array to next mesh
free TriStripsArr
--------- Vertices Block ---------
WriteLog(" - ** [Reading Vertices]")
for x2 = 1 to PM.VertsCount do
(
vx = readfloat f
vy = readfloat f
vz = readfloat f
append PM.VertsArray (R2L [vx, vy, vz])
)
--------- Normals Block ---------
WriteLog(" - ** [Reading Normals]")
for x3 = 1 to PM.VertsCount do
(
nX = readfloat f
nY = readfloat f
nZ = readfloat f
append PM.NormalsArray [nX, nY, nZ]
)
--------- Vertex Colors Block ---------
if Mesh_Unk0 == 79 then
(
WriteLog(" - ** [Reading Vertex Colors]")
for x4 = 1 to PM.VertsCount do
(
vcR = readbyte f #unsigned
vcG = readbyte f #unsigned
vcB = readbyte f #unsigned
vcA = readbyte f #unsigned
append PM.VertexColors [vcR, vcG, vcB, vcA]
)
)
else
(
WriteLog(" - ** [Ignore Vertex Colors]")
)
--------- UV's Block ---------
WriteLog(" - ** [Reading UV's]")
for x5 = 1 to PM.VertsCount do
(
uvX = readfloat f
uvY = readfloat f
append PM.UVsArray [uvX, 1 - uvY, 0]
)
--------- Nulled Bytes Block ---------
WriteLog(" - ** [Skip Nulled Bytes Block]")
fseek f (PM.VertsCount * 4) #seek_cur
-------- START OF NEXT MESH ----------
-- [ BUILD MESH ] --------------------------------------
-- Support for: Vertices, Faces, UV's, Vertex Colors, Materials (With Alpha Maps)
msh = mesh vertices:PM.VertsArray faces:PM.FacesArray tverts:PM.UVsArray
msh.name = MaterialsArr[PM.MatID].name
msh.material = MaterialsArr[PM.MatID]
msh.numTVerts = PM.UVsArray.count
buildTVFaces msh
if Mesh_Unk0 == 79 then
(
setNumCPVVerts msh PM.UVsArray.count
setCVertMode msh true
setShadeCVerts msh true
defaultVCFaces msh
for j = 1 to PM.VertexColors.count do setVertColor msh j PM.VertexColors[j]
)
for j = 1 to PM.UVsArray.count do setTVert msh j PM.UVsArray[j]
for j = 1 to PM.FacesArray.count do setTVFace msh j PM.FacesArray[j]
-- Add Current Mesh to Meshes Array
--append MeshArr PM
currentMesh += 1
)
print "----------------- MESH FRAME END -----------------"
) while (currentMesh != (MaterialsCount + 1))
print ("Finish at position: "+((ftell f) as string))
)
else
(
print "Invalid DXG Version, only version 5 is supported"
)
)
else
(
print "Invalid DXG file format..."
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment