3D models are in .gbx files instead, can something be done for them?

Code: Select all
fGBX = getOpenFileName caption:"Choose Model File:" \
types:"TrackMania Gamebox Container (*.gbx)|*.gbx|"
fn readByteAsChar binstr = -- not necessary, but looks nicer in my opinion
(
return bit.intAsChar(readbyte binstr)
)
fn readTextLine binstr = -- reads a string until a newline character is found
(
str = ""
while c != 13 do
(
c = readbyte binstr #unsigned
if c != 13 do str += bit.intAsChar(c)
)
readbyte binstr
return str
)
fn readTextBool binstr = -- as above but returns boolean
(
return readTextLine binstr as booleanClass
)
fn readTextInt binstr = -- as above but returns integer
(
return readTextLine binstr as integer
)
fn readTextFloat binstr = -- as above but returns float
(
return readTextLine binstr as float
)
fn readStr binstr strLen = --reads a fixed-size string
(
str = ""
for w=1 to strLen do(str += (bit.intasChar(readByte binstr #unsigned)))
return str
)
if fGBX != undefined then (
f = fopen fGBX "rb"
clearlistener()
fArr=#()
vArr=#()
nArr=#()
tArr=#()
propertyCount = 7
firstMesh = true
modelPath = getFilenamePath fGBX
diffusePath = modelPath+"diffuse.dds"
detailsPath = modelPath+"details.dds"
diffMaterial = standard showInViewport:true Name:"diffuse"
detMaterial = standard showInViewport:true Name:"details"
diffMaterial.diffuseMap = Bitmaptexture fileName:diffusePath name:"diffuse"
detMaterial.diffuseMap = Bitmaptexture fileName:detailsPath name:"details"
header = readStr f 3
if header != "GBX" do return messageBox "This is not a TrackMania GBX Container."
version = readshort f
if version != 6 do messageBox "GBX file isn't version 6. There might be problems."
fileFormat = readByteAsChar f -- Binary or Text
refTable = readByteAsChar f -- Compressed or Uncompressed
fileBody = readByteAsChar f -- Compressed or Uncompressed
unknown = readByteAsChar f -- R or E (unknown purpose)
classID = readTextLine f -- in car models this should be 09005000
userData = readTextInt f -- length of user data
numRefs = readTextInt f -- number of chunks ? (unverified)
numExtRefs = readTextInt f -- number of external chunks ? (usually 0 - not used)
numMeshes = 0
for i=1 to 4 do -- totally the wrong way to do it
(
chunkID = readTextLine f
case chunkID of
(
default:
(
return messageBox "Unknown ID " + mainID + "."
)
"9005000":
(
readTextInt f
)
"9005007":
(
readTextBool f
)
"900500d":
(
readTextBool f
readTextBool f
readTextInt f
)
"904f000":
(
-- do nothing
)
"904f006":
(
readTextInt f
numMeshes = readTextInt f
readTextInt f
)
"904f006":
(
readTextInt f
numMeshes = readTextInt f
readTextInt f
)
"904f00d":
(
if firstMesh do
(
readTextInt f
firstMesh = false
)
)
"40000000":
(
objectName = readTextLine f
)
)
)
-- estimated beginning of submeshes
for i = 1 to numMeshes do
(
for x=1 to propertyCount do readTextLine f
objectName = readTextLine f
for x=1 to 23 do readTextLine f
count = readTextInt f
for x=1 to 2 do readTextLine f
free tArr
for x = 1 to count do
(
tu=readfloat f
tv=readfloat f
append tArr[tu,tv,0]
)
for x=1 to 10 do readTextLine f
free vArr
free nArr
for x = 1 to count do
(
vx=readfloat f
vy=readfloat f
vz=readfloat f
nx=readfloat f
ny=readfloat f
nz=readfloat f
unk1=readfloat f
unk2=readfloat f
unk3=readfloat f
unk4=readfloat f
append vArr[vx,-vz,vy]
append nArr[nx,-nz,ny]
)
for x=1 to 5 do readTextLine f
unk=readlong f
count=readTextInt f
free fArr
for x = 1 to count/3 do
(
fa=1+readshort f #unsigned
fb=1+readshort f #unsigned
fc=1+readshort f #unsigned
append fArr[fa,fb,fc]
)
for x=1 to 10 do readTextLine f
fseek f 8 #seek_cur
for x=1 to 4 do readTextLine f
fseek f 88 #seek_cur
for x=1 to 4 do readTextLine f
readlong f
for x=1 to 6 do readTextLine f
readlong f
tmatrix = matrix3 1
tmatrix.row1 = [readTextFloat f, readTextFloat f, readTextFloat f]
tmatrix.row2 = [readTextFloat f, readTextFloat f, readTextFloat f]
tmatrix.row3 = [readTextFloat f, readTextFloat f, readTextFloat f]
tmatrix.row4 = [readTextFloat f, readTextFloat f, readTextFloat f]
for x=1 to 2 do readTextLine f
max modify mode
cui.expertModeOn()
with redraw off
(
amesh = mesh vertices:vArr faces:fArr name:objectName
meshop.setMapSupport amesh 1 true
setMesh amesh tverts:tarr
for face = 1 to amesh.numfaces do setFaceSmoothGroup amesh face 1
select amesh
addmodifier amesh (Edit_Normals ()) ui:off
amesh.Edit_Normals.MakeExplicit selection:#{1..nArr.count}
EN_convertVS = amesh.Edit_Normals.ConvertVertexSelection
EN_setNormal = amesh.Edit_Normals.SetNormal
normID = #{}
--apply normals
for v = 1 to nArr.count do
(
free normID
EN_convertVS #{v} &normID
for id in normID do EN_setNormal id nArr[v]
)
collapseStack amesh
max select none
amesh.transform = tMatrix
--rotate amesh (eulerangles 90 0 0)
matType = objectName[1]
case matType of
(
default:
(
--return messageBox "Uknown material type."
)
"S":
(
amesh.material = diffMaterial
)
"s":
(
amesh.material = diffMaterial
)
"d":
(
amesh.material = detMaterial
)
"D":
(
amesh.material = detMaterial
)
"g":
(
amesh.material = detMaterial
)
)
)
propertyCount = 6
)
gc()
fclose f
cui.expertModeOff()
)
else
(
clearlistener()
)
barti wrote:I tried to make a MAXScript for this format a while ago. There's two most common model types for cars (you can see which one it is by opening the model in a hex editor and looking at the first few bytes - BUCR (Binary - Compressed) and TUUE (Text - Uncompressed). BUCR models use LZO compression. My script works on a few TUUE files, and since it was complete enough to extract the model I wanted I didn't bother with it anymore. Maybe it'll be useful for some models:Code: Select all
-code snipped for short reply-
Automotive Gaming wrote:If I'm not wrong, the latest Trackmania games use the same format for these models, because in the readme I can't see any specification for this mod, if it is related to Nations, Sunrise, etc.
Of course, please correct me if my guess is wrong!