Last active
December 28, 2023 08:19
-
-
Save The-Meth0d/6d350f0654ed042bb11afb75a07dd0a9 to your computer and use it in GitHub Desktop.
MX Vs ATV Unleashed DXG Importer - Maxscript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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