Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Crash Bandicoot Nitro Kart 2 - Track 3D model

Featured Replies

Hello guys, I've wanted to extract a mesh from the files I found in the game. It's an old iphone game. So far I've only managed to notice that the file is divided into chunks: VERT, TCOR, TXTR, MATL, INDS etc and also after some trial and error I noticed that if I divide the data into short signed floats it spits out something comprehensible. However it only generates a small part of the map. If someone could help me extract a full mesh from the file I'd really appreciate it
 

obraz.png

Track Mesh.zip

  • Supporter

Is mesh.bin a file from game folder or was it extracted? (If so, how?)

There's some assumed face index blocks (starting with 000001000200) but no suiting vertex blocks so far. Wild guess: sub mehes are assumed to be small, vertex count around 266.

 

mesh_viewer_sRpzdKLG40.png

  • Author
20 minutes ago, shak-otay said:

Is mesh.bin a file from game folder or was it extracted? (If so, how?)

There's some assumed face index blocks (starting with 000001000200) but no suiting vertex blocks so far. Wild guess: sub mehes are assumed to be small, vertex count around 266.

 

mesh_viewer_sRpzdKLG40.png

Here are all the files I extracted from the game, the tracks are presumably the 12 biggest .vram files

CNK2.zip

  • Supporter

Thanks. There's some obvious structures but no way to get proper meshes, seems:

mesh_viewer_yBKye6eWOp.png

mesh_viewer_98uJtEtb1c.png

Edited by shak-otay

  • Supporter

Thanks. I found the face index block at 0x333B which results in a vertex count of 403. But the vertices are still a riddle to me. Using FVFsize of 12 and shorts.

  • Localization
35 minutes ago, shak-otay said:

Thanks. I found the face index block at 0x333B which results in a vertex count of 403. But the vertices are still a riddle to me. Using FVFsize of 12 and shorts.

They are 3 x (4 bytes unsigned longs).

  • Author

obraz.thumb.png.ef58eb0b2ac9fd2d0f9f4b82927b7e02.png

Thanks a lot guys, I'm starting to crack how this thing works. I noticed in the INDS section that the map is divided into multiple meshes, the indice data helped me establish how many vertices each mesh has. I'm quite sure that each vertex has 6 bytes and the indices are 3 byte each. 

  • Localization
7 hours ago, Gargantus said:

I noticed in the INDS section that the map is divided into multiple meshes, the indice data helped me establish how many vertices each mesh has. I'm quite sure that each vertex has 6 bytes and the indices are 3 byte each. 

The VERT chunk has

chunk size (4 bytes longint)

vertex counter (4 bytes longint)

vertex counter * 6 bytes vertices

 

chunk size / vertex counter = 6

 

I did try to read the vertices as 3 x 2 bytes integers or 3 x 2 bytes words or 3 x 2 bytes half-floats, but none of them worked for me.

 

How did you get the correct vertex datas?

  • Author
29 minutes ago, Karpati said:

How did you get the correct vertex datas?

Here's a simple C++ script I made and the output
 

obraz.png

obraz.png

  • Localization
39 minutes ago, Gargantus said:

Here's a simple C++ script I made and the output

I don't use the C language, but as I see the values are 2 bytes integers.

I don't undestrand that if I read the first 1000 vertices I have got a good view, but if I read all vertices I have got a very bad view.

CBNK_2_VRAM_ea0560ab_first_1000_vertices.png

CBNK_2_VRAM_ea0560ab_all_vertices.png

  • Supporter

I think it's just samples with different FVFsizes. With SCENVERS in the header it's 6 bytes, with 3DOBHEADL it's 12 bytes (just a wild guess).

Gargantus' code searches for 5254 hex, to find (VE)RT in SCENVERS  samples.

Quote

Gargantus

What did you use?

Sorry, have overread this. I used hex2obj.

Edited by shak-otay

  • Localization
1 hour ago, shak-otay said:

I think it's just samples with different FVFsizes. With SCENVERS in the header it's 6 bytes, with 3DOBHEADL it's 12 bytes (just a wild guess).

Gargantus' code searches for 5254 hex, to find (VE)RT in SCENVERS  samples.

It's OK. The uploaded mesh.bin and my (I extracted from the game's archive file) ea0560ab.vram files are the same.

The header is SCENVERS and first time I tried to load all vertices from this file and I was confused about the 6 bytes vertex format.

  • Author

I did some work on my script, it roughly divides the file into different meshes. Though I've yet to find a way to make it 100% consistent. Most meshes are off by a few vertices. It would be cool if you looked up for any patterns here

vram converter.zip

Edited by Gargantus

  • Supporter

Thanks! Can you tell your compiler settings?

(I use

-std=C++11
-Wsign-compare

and output.txt is different/wrong. edit: changed the compiler, now output.txt is the same.)

---------------------

Your output.txt contains invalid triangles, for mesh 11 for example:

f 1 2 1 <
f 3 1 4
f 1 2 1 <
f 5 1 6
f 1 7 1 <
f 8 1 9
f 1 10 1 <
f 11 1 11 <
f 1 10 1 <
f 12 1 13
f 1 2 1 <
f 14 1 6
f 1 8 1 <
f 15 1 11
f 1 12 1 <

This can be avoided by checking for v0<>v1<>v2 before creating faces.

 

Edited by shak-otay

  • Author

I'm using C++14 with wsign enabled. Also I realise that some meshes are incorrect, the script is still WIP, I just wanted wanted to show what patterns I've noticed. There are still some things that prevent it from being 100% accurate. I think that some of the later indices are actually 16 bit and not 8 bit like the first ones

Edited by Gargantus

  • Supporter
1 hour ago, Gargantus said:

I think that some of the later indices are actually 16 bit and not 8 bit like the first ones

edit: yep, I see. (Didn't see that you're reading bytes.)

when comparing mesh 11 fis (read as bytes) from output.txt

f 1 2 1
f 3 1 4
f 1 2 1
f 5 1 6
f 1 7 1
f 8 1 9
f 1 10 1
f 11 1 11
f 1 10 1
f 12 1 13
f 1 2 1
f 14 1 6
f 1 8 1
f 15 1 11
f 1 12 1

to hex2obj output from assumed offset 0x61FB7 (reading 16 bit fis):

Faces are different then>

f 1 2 3
f 4 2 5
f 6 7 8
f 9 10 11
f 11 10 12

f 13 2 14
f 6 8 15
f 11 12 16

 

Hex2obj0.25b-FIS.png

Edited by shak-otay

  • Author

What I'm curious about is why are the mesh vertices offset backwards or forwards, seemingly in a random way. There's clearly some extra data between those vertices. Or maybe I'm calculating the indices wrongly, the meshes make sense when you offset them a bit though

  • Supporter

There's two ways at least to tackle the problems: doing a deep analysis (see bt templates, 010 editor, which is not free, btw) or using tools like hex2obj, meshreaper (AMR) or ModelResearcher (MR) to get some meshes (maybe these two methods are similar to bottom up versa top down.).

For now I'd suggest to create two lists of counts, for vertex blocks and FI blocks, where for the FIs the "max FI count" is required (must match the vertex count, as you have calculated, maxVertexNumber).

These lists would grant an overview about matching blocks, hopefully.

The naming,

meshList[i].size() confused me, btw, isn't it FaceIndexList[i].size()? 

 

Edited by shak-otay

  • Author

the meshlist is a list of meshes, which are lists containing indice data, meshList.size() refers to the number of indices in a referred mesh. I use them to get the number of vertices per mesh

  • Supporter
3 hours ago, Gargantus said:

meshList.size() refers to the number of indices in a referred mesh.

Seems the browser swalloed the square brackets?

meshList[i].size()
Quote

There's clearly some extra data between those vertices.

How about uv data?

btw, mesh 1 starts at 0x162? (0x24 +53x6 dec.)

edit 2: mesh 2 is where it breaks:

blender_M2break.png

Edited by shak-otay

  • 1 month later...
  • Localization

I finished my Crash Bandicoot Nitro Kart 2 (Except scenes) *.VRAM loader module and I released the following programs:

- 3D Object Converter v11.50 (Windows)
- 3D Object Converter v1.50 (AmigaOS)

- i3DConverter v6.50 (macOS)
- i3DConverter v4.50 (Linux)


How to get the 3D Object Converter (Windows) v11.50:
Download the 3D Object Converter from http://3dconverter.synology.me/3doc or http://3doc.i3dconverter.com and install it or download and use the portable version (if you don’t have it yet).
(Or just use the Help/Check for updates... function to get the v11.50.)

How to get the 3D Object Converter (AmigaOS) v1.50:
Download the 3D Object Converter from http://3dconverter.synology.me/3doc or http://3doc.i3dconverter.com and install it or download and use the portable version (if you don’t have it yet).
(Or just use the Help/Check for updates... function to get the v1.50.)

How to get the i3DConverter macOS v6.50:
Download the i3DConverter from http://3dconverter.synology.me or http://www.i3dconverter.com and install it (if you don’t have it yet).
(Or just use the Help/Check for updates... function to get the v6.50.)

How to get the i3DConverter Linux v4.50:
Download the i3DConverter from http://3dconverter.synology.me or http://www.i3dconverter.com and install it (if you don’t have it yet).
(Or just use the Help/Check for updates... function to get the v4.50.)

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.