News:

Herr Otto Partz says you're all nothing but pipsqueaks!

Main Menu

Dissecting the Stunts files, trying to. Anyone know more?

Started by Cyberman, July 23, 2004, 08:15:12 PM

Previous topic - Next topic

dstien

Quote from: Duplode on March 27, 2008, 06:37:41 AM
Moreover, the word "numIndices" is 0x0c, but there are only six indices to edit... and if you try to deform a tyre by extending it in one direction the wheel will be suitably adjusted and a second distortion, symmetrical in relation to the origin vertex, will take place as well. Thus, there is *something* else involved in wheel drawing.
Interesting. It sounds like numIndices can also be a code for using other polygon primitives, or an escape code for referencing previous polygons...

Quote from: Duplode on March 27, 2008, 06:37:41 AM
BTW, FYI, counting printable-byte colour strings reveals we have (a few more than) 223 polygons in STCOUN.3SH. Of those 223, 148 are in car0 and 66 in car1...
Remember that each resource is an independent entity. All shapes have their own SHAPE structure with header values, it seems to add up.

Quote from: Duplode on March 27, 2008, 06:37:41 AM
I attached a very sloppy (and sleepy!) spreadsheet chart which may serve as a rough guide for the time being...
Wow! Again, well done. It'll sure prove useful.

Duplode

OK, now we're in a position to understand a good chunk of the structure. First of all, I'll quote dstein's pseudocode again for reference:

Quote from: dstien on March 26, 2008, 10:46:42 PM

struct SHAPE {
    BYTE numVertices;
    BYTE numPolygons;
    BYTE numPalettes;

    [...] // Vertices and other unknown data?

    POLYGON polygons[numPolygons]
};

struct POLYGON {
    WORD numIndices;
    BYTE colors[numPalettes];
    BYTE indices[numIndices];
};

I was able to do a few inferences from comparing car0 resources of Countach, NSX and Indy:

  • The car0 numPalettes byte of the header is located, for all cars, in 0x0040. Then there is an odd "00 ?? ?? 00 00" that appears functionless, and then the vertex block starts at 0x0046.
  • Vertexes are 6-byte (high theoretical resolution!!) 3D cartesian coordinates, in the format "xx XX yy YY zz ZZ" with x, y and z values in little-endian (that is, read the bytes as XXxx, YYyy and ZZzz). Thus, the vertex section extends through 6 * numVertexes bytes. The positions of vertexes in this block is referenced by the polygons section through indices, which range from 0x00 to (numVertices - 1) - arrays start from zero, as could be expected for a C program. Also, it should be mentioned that both in car0 and car1 the first eight vertexes are not referenced by the polygons; thus the first "useful" vertex is index 0x08 - the first of the ones used to draw the wheels.
  • After the last vertex, the byte sequence transitions to a strange section with lots of repetition patterns and apparently no effect on the graphics - both for car0 and car1. The border between those sections is usually characterized by lots of 0xff values on either side of the transition. Another point is the section size appears to be roughly proportional to the number of polygons. Tis strange middle section tends to be terminated by a zero-word.
  • The following and final section are the polygon definitions. First there's the numIndices word, which sets how many vertexes will the polygon have. The "big" byte of this word has no effect (at least they have not made polygons with more than 256 sides available... :)). Then come the (default 7) colour bytes and finally the numIndices single-byte references to the vertexes. A good tip to quickly locate polygon sections in original cars is to check for a lot of 0x26 values packed together - those most likely are wheel colour bytes, corresponding to the very first polygons in the section. The polygon section is terminated by a zero-word, which is directly followed by the next resource. Of course, there's the exception of wheel shapes, that have a lot of quirks we have little clue about.

So, if one can endure the wilderness of cold hex editing, making custom shapes is possible already  :) BTW, I did some research on whether this particular storage format could be linked to a deprecated graphics standard (which in turn might lead, with a lot of luck, to a proper editor), but found no clues.

Now, to the beautification efforts!   ;D



Vodafone McLaren Mercedes (early alpha) vs. pitch-dark Indy... The McLaren still is far from perfection (too much red using the standard colour distribution, in fact it looks almost pure red when looked from the side), but it already looks cool - and so do black cars! BTW Krys, I tried the John Player Special Lotus too, but it looked more strange than the McLaren with excessive golden panels, and thus is not really worth a shot until we identify the panels properly.



British Racing Green vs. Danish girls' special edition... :) Notice the pink car is actually bi-colour: even very slight tonality differences make a large improvement in visuals.

A very positive fact is that Indy has far fewer polygons than most other cars, and so creating all crazy team schemes we can might not be that hard. 8)[/list]

BonzaiJoe

The black car has finally arrived after 17.3 years!!

And nice of you to make a car for Lene :)
But we can't be quite sure.


Krys TOFF

Hail to the "D" guys : Dstien and Duplode !
Raaaaaah, I love to be here to see this historical moment, keep up this awesome job guys. ;)

zaqrack


Mark L. Rivers


Really a fantastic job...  :) :) :)  Infinite thanks to Dstien and Duplode...
Now I have only a favour to ask you, Duplode: would you like to paint "my" Speedgate XSD as I dreamt to see it since its creation...? You know... :)

dstien

It seems like we have the basic structure now:
struct SHAPE {
    BYTE numVertices;
    BYTE numPolygons;
    BYTE numPalettes;
    BYTE reserved; // Always == 0. Ignored.

    VERTEX vertices[numVertices];
    UNKNOWN unknowns[numPolygons];
    POLYGON polygons[numPolygons];

    BYTE padding[]; // -> EOF. Ignored.
};

struct VERTEX {
    WORD x;
    WORD y;
    WORD z;
};

struct UNKNOWN {
    BYTE data[8];
};

struct POLYGON {
    BYTE numIndices;
    BYTE depthIndex;
    BYTE colors[numPalettes];
    BYTE indices[numIndices == 0xC ? 6 : numIndices];
};


The value depthIndex in the POLYGON struct is used to override the game's depth clipping. The barn shape, for example, has details drawn on a plane at the exact same depth. Without setting custom depth-indices the details will flicker:


I don't think shapes stores animation data (windmill rotations, "Joe's" flashing sign). They may be hardcoded... :-\

Duplode

Quote from: Krys TOFF on March 29, 2008, 08:21:38 AM
Hail to the "D" guys : Dstien and Duplode !
Raaaaaah, I love to be here to see this historical moment, keep up this awesome job guys. ;)

Haha, the "D" guys!! :D "The Daniels" could be even cooler, such a nice coincidence...

Quote from: Mark L. Rivers on March 29, 2008, 01:37:35 PM

Really a fantastic job...  :) :) :)  Infinite thanks to Dstien and Duplode...
Now I have only a favour to ask you, Duplode: would you like to paint "my" Speedgate XSD as I dreamt to see it since its creation...? You know... :)

Sure! Check your PMs ;)

On a practical level, there are two useful ideas we should consider about colours:
1. Creating different colour sets for Melange and other customs, so as to distinguish them from the base shapes.
2. Releasing alternative colour sets for the original cars - perhaps in a package installable by a batch/shell script. Maybe we should start for the four default colours missing for each car plus some particularly good looking colours. Or, alternatively, implement Zak's idea of special colour sets as prizes  :) - and BTW again, I agree with BJ that black cars are a must and with Zak that those dark green look great - even more because it is not exactly the same colour of the grass...
So, keep thinking on suggestions guys  ;)

----

Back to hacking: I found several pieces of useful data during the weekend, and matching it with the additions dstien made to the basic structure I'd say we know 100% of the organization and ~70% of the functionality of .3SH shapes. I can't post details right now (I'm away from home, so editing data is unavailable), but anyway they say a picture is worth a thousand words, so...



The picture you're seeing above was generated from the very STANSX.3SH file. I coded a (very crude) parser for the structure which saves in separated, human-readable ASCII tables coordinates, polygon indexes and colours for each structure (for a car, that's 21 different tables per run). Then I used the statistics/graphing programming language R to make a plot of vertex cooordinates, overlay the polygons according to the index table and write adequate labels. With the program compiled and the R script handy, the whole thing is fully automated. I attached a very-high resolution pdf of the same picture, so you can explore it better. Black numbers are vertex labels (ranging from 0 to numVertexes-1 in hex) and blue numbers are polygons (ranging from 1 to numPolygons, in hex as well). The labels were printed at a slight offset from the vertex position/polygon center, so that labels for stuff at the right side of the car is at the right of the vertex/polygon, and vice-versa. 

Now there's a way around the first big obstacle to editing the files - identifying vertexes and polygons... 8) I will return later and post the program, scripts and further details. See you!

Krys TOFF

Quote from: DuplodeSure! Check your PMs ;)
Hey, I want to try a black speedgate too. ;D

Quote from: Duplodea picture is worth a thousand words, so...

OMG ! :o Awesome !

dstien

Yup, visualization did the trick. Now we can see how the wheels are built.


Krys TOFF

We really need a tool to create new 3D shapes now. ;D
this way, we will be able to create 1 shape for each tuned car, including those already created, and identify clearly which cars are original and which are tuned ones. Whaooooh !

dstien

Another special case of numIndices is the value 11 (0x0B), it takes two vertex indices to make a sphere (origin + radius). It's used to render the helmet on the Indy shape in the car selection screen:


Duplode

The follow-up to my last post...
First of all, a zip of stuxplic (for Stunts explicit...) with source code and binaries attached. The code was done hastily and is pretty inelegant and rough at this version (dstien will find specially amusing the fact it is written in Fortran...), but it works AFAIK. Also attached is the .R script used to plot that polygon map, if anyone has R ans is willing to try it (in that case, tell me if you get confused).

The first observation I would have to mention were some errors in my previous accounting of bytes, most important of which is vertex list starting at the 5th byte of resource block (and not at 9th as previously implied). Dstien has already corrected my accounting in his latest version of the structure. Such offsets caused me quite some trouble while writing the parser, since the effect of a mistake of +-2 or +-4 byte is surprisingly subtle (e.g. the assymetric distortions on the meshes posted three posts above by dstien).  Also, the shift in byte frame means the vertex coordinates are ordered [y,z,x] if we take the usual convention of x = length, y = width and z = height. Anyway, the new info means both our posts and my program are correct now...

(And before I forget, nice find about the helmet, when we find what escape code produces the circular taillights it will be a neat addition.)

Those corrections mean that now we only have the mysterious "UNKNOWN" middle section to understand. Actually, I did some brute force tests while writing the parser (e.g. blanking the whole thing), and it seems that the "UNKNOWN" section has actually two parts, one with five-byte blocks and the other with three-byte blocks. The first part might have some relation with angles of visualization - for instance, wheels have "ff ff ff ff ff" sequences, and blanking some (don't remember which) values will make them disappear, while arbitrary changes might make them go on and off as the car0 structure rotates in the selection screen. As for the second part, still no clue on what it stores.

Now, on where we go from now... first thing I wish to do is to print better polygon maps, so it is feasible freely colorize a car. Also, I wonder about editors. One of the motivations behind the creation of the ASCII parser was to use it as an intermediate tool for feasible edition. I can think of two routes:


  • Decompose the .3SH in tables of vertexes, colours, polygons and whatever else is needed, modify the intermediate as wished and re-package everything on a new .3SH with another program. That could be useful, for instance, in providing a comfortable way to tune colours without having to worry all the time about offsets - but more important would be the role of such process in the other treatment...
  • ...namely, use a new parser to convert the essentials (vertex and polygons at least) data in a format that can be read by an actual 3D editor, then use another program to rebuild the .3SH. While that may sound unfeasible at first, there's a damn simple and common 3D shape format that uses tables very similar to what we already have to code polygonal shapes: the .OBJ format.

For the moment, though, I'm merely speculating. Surely dstein knows a lot more about 3D shape edition than me (for I would have found nothing without his guidance), and is a more experienced programmer as well (he doesn't have to write his parsers in Fortran  :)), so he can have a more proper opinion in that respect.

And to close in a lighthearted note I leave you with an actual on-track Black Indy pic... but this time the actual loaded texture was car0. Now only if we could play at such resolutions... ;D



Edit: Windows zip attached as well.

CTG

I wish I could ever see a P962 IMSA with my NFS:PU Porsche 911 GT1 colors (black with red-yellow lines)... :D

Those 3D shapes look very nice.

BonzaiJoe

But we can't be quite sure.