Jump to content

Reverse enigneering 3D models using Model Researcher


Recommended Posts

  • Members
Posted (edited)

Today I am gonna show you, how to reverse eningeer any Binary 3D Models, turns out this is not that hard and actually one of the cooolest things in reverse enigneering! (Uncompressed and un-encrypted models obviously).

 

+====TUTORIAL SECTION=====+

=| INTRODUCTION |=
But how do all those models store their 3D Data?
Well, the answer is simple, there is no magic here, All 3D Models are just made up of *Vertecies*, *Faces*, *Vertex UV Coordinates* and *Vertex Normal Coordinates*
They are definatelly *must* somewhere there in your file (this place is called buffer) and there is absolutelly no extra magic in here.

This is how the Vertecies look like:
v  1.0 4.0 3.0 <= X, Y, Z matrix coordinates (usually from 0.01 to 1000)
v  2.0 3.0 4.0 <= Point values so are usually floats
v  6.0 2.0 3.0 <= Usually stable, values don't varry to much in max and min values

This is how faces looks like:
f  1 2 3 <= Takes all those previous vertecies and makes a triangle out of them

This is how UV Vertex coords look lke:
vt  0.2 0.3 <= 2D coordinate of the first vertex (usually from 0.1 to 1.0)
vt  0.5 0.2 <= Point values so are usually floats
vt  0.3 0.1 <= Usually stable, values don't warry to much in max and min values

This is how Vertex normals look like (not important actually!):
vn  0.745 0.845 0.360 <= X, Y, Z matriz coordinates (usually from 0.01 to 1)
vn  0.320 0.625 0.270 <= Point values so are usually floats, so "v2 x, y, z"
vn  0.430 0.320 0.390 <= Usually stable, values don't warry much in max and min values


This is how the simplest 3D Model format OBJ stores their 3D Model data, hovewer we can say that all of the binary models store their 3D Data in OBJ file format there is just one more thing to it.

Binary fomrats have two ways of storing the 3D Data (Aside faces) in a Separate way and Structured way, here is how it looks like:

Separate way:

vertex_buffer = [

    v1  1.0 4.0 3.0 <= X, Y, Z matrix coordinates (usually from 0.01 to 1000)
    v2  2.0 3.0 4.0 <= Point values so are usually floats, so "v2  x, y, x"
    v3  6.0 2.0 3.0 <= Usually stable, values don't varry to much in max and min values
    ...
]

face_buffer = [

    f1  1 2 3 <= Takes all those previous vertecies and makes triangle out of them, so "f1  v1, v2, v3"
    ...
]

uv_coords_buffer = [

    vt1  0.2 0.3 <= 2D coordinate of the first vertex (usually from 0.1 to 1.0)
    vt2  0.5 0.2 <= Point values so are usually floats, so "vt2  u, v"
    vt3  0.3 0.1 <= Usually stable, values don't warry to nuch in max and min values
    ...
]

vertex_normals = {

    vn1  0.745 0.845 0.360 <= X, Y, X matrix coordinates (usually from 0.01 to 1)
    vn2  0.320 0.625 0.270 <= Point values so are usually floats, so "v2, x, y, z"
    vn3  0.450 0.310 0.390 <= Usually stable, values don't warry much in max and min values
    ...
}

Structured way:

data_array = [

    {v1  1.0 4.0 3.0, vt1  0.2 0.3, vn1  0.745 0.845 0.360}
    {v2  2.0 3.0 4.0, vt2  0.5 0.2, vn2  0.320 0.625 0.270}
    {v3  6.0 2.0 3.0, vt3  0.3 0.1, vn3  0.450 0.310 0.390}
    ...
]

=| BINARY DATA |=
The data in each file can be viewed as binary no matter if it was readable or unreadable or even empty before, viewing it in binary will spoil immediatelly everything.
And while binary files are all the same, the way we read it changes drastically everything! To view your binary file yiou must dump HEX from it or load it into HEX Viewer:

Example file:
Addres:   HEX Bytes:                                        ASCII:
0012BFC0  48 53 68 61 70 65 5F 31 37 00 00 00 00 00 01 00   HShape_17....... <= First line contains ASCII strings
0012BFD0  00 00 0A 00 00 00 22 00 00 10 00 00 00 00 0C 00   ......"......... <= Second line contains ASCII strings
0012BFE0  00 00 61 32 76 2E 6F 62 6A 43 6F 6F 72 64 01 00   ..a2v.objCoord.. <= Third line contains ASCII strings
0012BFF0  00 00 FF FF FF FF 02 00 00 00 47 04 00 00 82 56   ..........G....V <= Fourth line contains interesting "00 FF FF FF FF 00" separation mark
0012C000  F9 40 39 94 59 43 76 26 13 41 BB 61 FB 40 5A A4   [email protected]&.A.a.@Z. <= Fifth line starts containg the actual float Vertex coordinates! But looks random in ASCII strings!
0012C010  5B 43 95 B7 00 41 8F 70 CB 40 C1 4A 5B 43 31 08   [[email protected][C1. <= Sixth line contains actual float Vertex coordinates! But looks random in ASCII strings!
0012C020  12 41 8A 8E C9 40 E7 5B 59 43 E8 82 1D 41 90 A0   .A...@.[YC...A.. <= Seventh line contains actual flaot Vertex coordinates! But looks still random in ASCII strings!
0012C030  62 40 21 90 58 43 05 DD 1C 41 BC B3 78 40 D7 63   b@[email protected] <= Eight line contains actual float Vertex coordinates! But looks again random in ASCII strings!


But what are those floats, shorts and ASCII?
The Bits are the smallest units of computer data they are either 0 or 1 and comma.
The Bytes hgovewer is a combined 8 Bits that can actually start representing some data. Those are Bits ranging from 0 to 255, where 0 is also precieved as an important value (So 256 combinations), (I represented them in HEX, 0-F values, so a 256 combinations)
Here is one Byte for example: 10110111 (32 16 8 4 2 1 = 256 bits as sum), combining Bytes together we can make multiple data types.

This are all of the data types:
Byte/Char => 1 Byte, unsigned/signed (8 Bits)                                                |Example: 48 <= H | ASCII
Word/Short => 2 bytes, unsigned, signed (16 Bits)                                            |Example: 48 53 <= HS | ASCII
Dword/Int => 4 bytes, unsigned, signed (32 Bits)                                             |Example: 48 53 68 61 <= HShap | ASCII
ULONG32/Long => 4 Byte, unsigned, signed (32 Bits)                                           |Example: 48 53 68 61 <= HShap | ASCII
ULONG64/Long Long => 8 Byte, unsigned, signed (64 Bits)                                      |Example: 48 53 68 61 70 65 5F 31 <= HShape_17 | ASCII
float => 4 bytes, for represnting floating point values (32 Bits)                            |Example: 48 53 68 61 <= HShap | ASCII
double => 8 bytes, for representing more precise floating point values (64 Bits)             |Example: 48 53 68 61 70 65 5F 31 <= HShape_17 | ASCII
String/Char => A Sequence/Array of Characters terminated by the nulll character              |Example: 48 53 68 61 70 65 5F 31 <= HShape_17 | ASCII

Big-Endina vs Little-Endian:
Reading in Big-Endian for example a float byte will read it normally, left-to-right 48 53 68 61 "HShap", where's Little-endin reads byte in reverse order, right-to-left 61 68 53 48 "paSH".
Big-Endians were mainly used in PS3, Xbox360 and Wii platform s where Little-Endians are mainly in Windows, PS4, Xbox One, Nintendo Switch.

=| TRYING TO REVERSE THE BINARY 3D FORMAT |=

But how do we actually apply this info into reverse engineering the binary 3D file format structure and even converting it into an OBJ Model.
Assuming that you have the actual decompressed/uncompressed and decrypted/unencrypted binary 3D model file, you can actually visualize the 3D Data geometry while analyzing the HEX from it in realtime!
ModelResearcherUltimate is the program that will enable this opportunities.

First of, Level 1: Start with vertecies count 500, type: float, carefully try different offsets while printing the values and render it too, until you see a countinous very stable output without insanelly big or small values. (from 0.001 to 1000).
If nothing works try with different Endianess, then try a different type (unlikely). If the mesh appears but random vertecies appear too that means that the Data structure is sctructured and you need to try different Padding or even Pad inters sometimes.
Second of, Level 2: Start with vertex UV coordinates count [exactly how many vertecies], type: float, carefully try different offsets while printing the values and rendering it too, until you see a countinous stable output without insanelyy big or small values (from 0.0001 to 1.)
If nothing works try different type, since you already know the Endianes and Structure.
Third of, Level 3: Start with faces, they are actually very carefully linked with vertecies, so the errors will constantly appear, carefully try different offsets while printing the values, don't render it, it will often just throw the errors.
You will need see the full values without floating points that are very stable in output without big and small values, if nothing works try different type or even the format.
Fourth of, Level 4: [To be honest I didn't know what to write here, normals are pretty useless though, you can just flip them and calculate, very easily in programs like Blender in just a few clicks, so it's not worth your brainstorming!]

Edited by user3678
  • Engineers
Posted
9 hours ago, user3678 said:


Fourth of, Level 4: [To be honest I didn't know what to write here, normals are pretty useless though, you can just flip them and calculate, very easily in programs like Blender in just a few clicks, so it's not worth your brainstorming!]

Hi, I usually don't care for normals, too, but some texture expert could tell you, that there's different kind of normals (face normals, vertex normals, tangent normals) and sometimes it's required to have the original ones and not the autogenerated from blender (which are face normals, afaik).

(btw, I'd suggest to place your tutorials in the "Tutorials" forum)

Maybe take into account that pure text tutorials are "out of date", some pictures could help, but that's my personal opinion.

(Meanwhile many people demand video tutorials and that was the point where I stopped my efforts, more or less.)

  • Members
Posted
On 12/7/2025 at 12:42 AM, shak-otay said:

Hi, I usually don't care for normals, too, but some texture expert could tell you, that there's different kind of normals (face normals, vertex normals, tangent normals) and sometimes it's required to have the original ones and not the autogenerated from blender (which are face normals, afaik).

(btw, I'd suggest to place your tutorials in the "Tutorials" forum)

Maybe take into account that pure text tutorials are "out of date", some pictures could help, but that's my personal opinion.

(Meanwhile many people demand video tutorials and that was the point where I stopped my efforts, more or less.)

Hello, sorry for those half-way unfinished tutorials, it's a shame but I was very, very busy recently, I am planning to update them a few times and later with some small visual changes. With normals of course for sure, that was my older tutorial section I am planning for my Model Researcher Ultimate project on GitHub, some models with vertex duplicates and etc. actually look and work way beter with correct normals hovewer it's nothing as demanding as getting Vertecies/Faces/UV Coords first so I just skipped this section for a bit.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...