Platoon 3D Model

Skeletons, animations, shaders, texturing, converting, fixing and anything else related to read game models
wattostudios
Posts: 20
Joined: Fri Jun 02, 2017 2:15 pm

Platoon 3D Model

Post by wattostudios »

Hi Experts,

I'm new to 3D model examining, but have managed to work out some of the models from the game Platoon. A single model seems to be comprised of a number of separate meshes (with separate faces, verts, etc) - all this looks OK, but I'm struggling to get the separate meshes to fit together into the complete model.

See attached for example - it's a tank that's made up of 4 meshes (body, turret, cannon, gun), but I can't seem to get the pieces to fit on top of each other. The OBOX appears to be (at my guess) a set of co-ordinates which I assumed was to position each mesh, but I'm not sure.

Is anyone able to help me with the final bit of understanding here, please?

The specs I have worked out are...

Code: Select all

  // for each block
    4 - Block Name
    4 - Block Length (including these 2 header fields)
   
    if (BlockName = DUMY){
      // Dummy, can contain objects in it
      4 - Object Number (incremental from 0)
      4 - Name Length
      X - Name
      68 - Unknown
      }
    else if (BlockName == OBST){
      // Object
      4 - Object Number (incremental from 0)
      4 - Name Length
      X - Name
      68 - Unknown
      }
    else if (BlockName == MESH){
      // Mesh
      4 - Unknown
      4 - Unknown
      4 - Number of Vertex Points
      }
    else if (BlockName == VERT){
      // Vertex block, contained within a MESH
      4 - Number of Vertex Points
      4 - Unknown
      4 - null
     
      // for each vertex (32 bytes per entry)
        4 - Vertex X
        4 - Vertex Y
        4 - Vertex Z
        4 - Normal X
        4 - Normal Y
        4 - Normal Z
        4 - UV X
        4 - UV Y
       
      4 - Number of Entries? (1)
     
      // for each entry
        4 - Unknown
      }
    else if (BlockName == ISTR){
      // Face Indexs block, contained within a MESH
      4 - Number of Face Indexes
     
      // for each Face Index
        2 - Face Index
      }
    else if (BlockName == FACE){
      // Faces block, contained within a MESH
      4 - Number of Faces
     
      // for each Face
        // LODP entry
      }
    else if (BlockName == LODP){
      // Unknown block, contained within a FACE
      4 - Unknown
      4 - Number of FSEC Entries? (1)
     
      // for each FSEC entry
        // FSEC entry
      }
    else if (BlockName == FSEC){
      // Face Sequence? block, contained within a LODP
      2 - null
      4 - Unknown (0)
      4 - Unknown
      4 - Number of Face Indexes
      4 - Unknown (101)
      4 - First Face Index Number
      4 - Last Face Index Number
      }
    else if (BlockName == OBOX){
      // Object Center Point
        4 - Center Vertex X
        4 - Center Vertex Y
        4 - Center Vertex Z
        4 - Center Normal X
        4 - Center Normal Y
        4 - Center Normal Z
      }
    else if (BlockName == MBOX){
      // Unknown block
      24 - Unknown
      }
    else if (BlockName == TEXT){
      // Unknown block
      4 - null
      4 - String Length
      X - String
      }
    else if (BlockName == MATE){
      // Material block
      4 - Material Number? (0/1)
      4 - Texture Filename Length
      X - Texture Filename
     
      4 - Number of Entries
      96 - Unknown
     
      // for each entry
        20 - Unknown
      }
    else if (BlockName == BLST){
      // Unknown block
      4 - null
      }
    else if (BlockName == ASEL){
      // Unknown block
      4 - Number of Strings
     
      // for each string
        4 - String ID
        4 - Unknown
        4 - String Length
        X - String
      }
    else if (BlockName == ASEC){
      // Unknown block
      4 - null
      }
    else if (BlockName == TIME){
      // Timestamp Block
      24 - Timestamp String
      }


Appreciate your help!
mariokart64n
Posts: 12
Joined: Fri Aug 08, 2014 12:59 am

Re: Platoon 3D Model

Post by mariokart64n »

Image

Code: Select all

/*
maxscript for Platoon 3D
by mariokart64n
feb 26 2021
*/
clearlistener()

fn read file = (
   
   local f = try(fopen file "rb")catch(undefined)
   local blockArray = #()
   local OBSTArray = #()
   if f != undefined then (
      
      delete $*
      
      local fsize = getFileSize file
      local b = datablock()
      local vertArray = #()
      local tvertArray = #()
      local colrArray = #()
      local normArray = #()
      local i = 1
      local vertex_count = 0
      local vertex_buffer_size = 0
      local vertex_stride = 0
      local face_count = 0
      local faceArray = #()
      local msh = undefined
      local faceArray2 = #()
      local matidArray = #()
      local v = 1
      local material_count = 0
      local msh_name = ""
      local msh_pos = [0.0, 0.0, 0.0]
      unk009 = 0
      unk010 = 0
      unk011 = 0
      unk012 = 0
      unk013 = 0
      unk014 = 0
      
      local stype = ""
      while ftell f < fsize do (
         stype = bit.IntAsChar (readByte f #unsigned)
         stype += bit.IntAsChar (readByte f #unsigned)
         stype += bit.IntAsChar (readByte f #unsigned)
         stype += bit.IntAsChar (readByte f #unsigned)
         format "BlockRead:\t%\n" stype
         case stype of (
            "OBST": (
               readLong f #unsigned
               readLong f #unsigned
               
               for i = 1 to (readLong f #unsigned) do (
                  msh_name += bit.IntAsChar (readByte f #unsigned)
                  )
               print (readLong f #unsigned)
               
               print (readFloat f)
               
               
               msh_pos += [readFloat f, readFloat f, readFloat f]
               
               
               
               print [readFloat f, readFloat f, readFloat f] -- rotation
               print (readFloat f)
                  
               print [readFloat f, readFloat f, readFloat f] -- scale
               
               print [readFloat f, readFloat f, readFloat f] -- 000
               print (readFloat f)
               readLong f
               
               )
            "DUMY": (
               fseek f ((readLong f #unsigned) - 8) #seek_cur
               )
            "MESH": (
               readLong f
               readLong f
               readLong f
               readLong f
               readLong f
               vertex_buffer_size = readLong f
               vertex_count = readLong f
               readLong f
               readLong f
               i = 1
               vertArray = #()
               tvertArray = #()
               colrArray = #()
               normArray = #()
               
               vertex_stride = ((vertex_buffer_size - 28) / vertex_count) as integer
               
               format "vertex_count:\t%\n" vertex_count
               format "vertex_stride:\t%\n" vertex_stride
               case vertex_stride of (
                  32: (
                     for i = 1 to vertex_count do (
                        append vertArray [readFloat f, readFloat f, readFloat f]
                        append normArray [readFloat f, readFloat f, readFloat f]
                        append tvertArray [readFloat f, readFloat f, 0.0]
                        )
                     )
                  36: (
                     for i = 1 to vertex_count do (
                        append vertArray [readFloat f, readFloat f, readFloat f]
                        append normArray [readFloat f, readFloat f, readFloat f]
                        append colrArray #(readByte f #unsigned, readByte f #unsigned, readByte f #unsigned, readByte f #unsigned)
                        append tvertArray [readFloat f, readFloat f, 0.0]
                        )
                     )
                  default: (
                     format "invalid vertex stride [%]\n" vertex_stride
                     exit
                     )
                  )
               fseek f ((readLong f) * 4) #seek_cur
               
               format "LastRead:\t%\n" (bit.IntAsHex((ftell f) as integer))
               )
            "ISTR": (
               readLong f
               face_count = readLong f / 3
               faceArray = #()
               --format "face_count:\t%\n" face_count
               for i = 1 to face_count do (
                  append faceArray ([readShort f #unsigned, readShort f #unsigned, readShort f #unsigned] + 1)
                  )
               )
            "FACE": (
               
               msh = undefined
               faceArray2 = #()
               matidArray = #()
               v = 1
               
               readLong f
               material_count = readLong f #unsigned
               for i = 1 to material_count do (
                  readLong f
                  readLong f
                  readFloat f
                  readLong f
                  readFloat f
                  readLong f
                  readShort f
                  unk009 = readLong f -- mesh type?
                  
                  unk010 = readLong f
                  unk011 = readLong f -- read
                  unk012 = readLong f -- 101
                  unk013 = readLong f -- pos
                  unk014 = readLong f -- end pos (pos + read)
                  --format "%\t%\t%\t%\t%\t%\n" unk009 unk010 unk011 unk012 unk013 unk014
                  --print (((unk013 / 3)) + ((unk011 / 3)))
                  if i == 1 do ( -- just read first LOD
                     for v = 1 to (((unk011 / 3) as integer)) do (
                        append faceArray2 (faceArray[v + ((unk013 / 3) as integer)])
                        append matidArray i
                        )
                     )
                  )
               
               msh = mesh vertices:vertArray faces:faceArray2-- materialIDs:matidArray
               --msh.material = MultiMaterial numSubs:material_count
               msh.name = msh_name
               msh.position = msh_pos
               msh.wirecolor = random white black
               --for i = 1 to material_count do (msh.material[i].Diffuse = random white black)
               select msh
               )
            "OBOX": (
               readLong f #unsigned
               [readFloat f, readFloat f, readFloat f]
               [readFloat f, readFloat f, readFloat f]
               )
            "ASEC": (
               fseek f ((readLong f #unsigned) - 8) #seek_cur
               )
            default:(
               format "Unknown Type [%], Reading Halted @\t0x%\n" \
                  stype (bit.IntAsHex((ftell f - 4) as integer))
               exit
               )
            )
         )
      
      ) else (format "failed to open file\n")
   )
read (
   "C:\\Users\\Corey\\Downloads\\SingleTankObject\\SingleTankObject.OBST"
   )