The game works similar to Mario 64 - all "models" are in fact just programs executed by the GPU (the proper term being display lists). Fortunately it uses a very simple, high-level bytecode, which has no variables, branches, loops, or conditionals - anything that isn't static would be generated on the fly by the CPU, which would just evaluate these things during generation. So it's not too difficult to parse those instructions into a very generic format, closer to traditional 3D models.
The "distance models" are just different display lists. The game saves a load of rendering time by only rendering the areas you can actually see. Tracks have a path with several points, and the game basically uses the nearest point and the direction faced to determine which part to render. The parts overlap to make the transition seamless.
(This is why, if you use levitation cheats or a certain Wario Stadium shortcut, the track ahead of you may be a black void until you actually land on it. The path tracking is tied into the hit detection, so it doesn't realize the visible region has changed until you land.)
What this program does is just parse the already fairly simple commands into even simpler, highly generic ones. When several polygons are drawn one after another, without any change to rendering mode or texture and within one list, they're put into a group. Groups and lists can be named, and there is support for defining their names in a file, but right now they're just named after their memory address.
These lists operate at a much higher level than the N64 GPU, and so don't have to worry about such things as the vertex cache, memory segments, or synchronization. For a textureless rendering like the above, the game has to use many different binary instructions (load vertices into cache, draw triangle, draw another triangle, synchronize, end list, etc), but in this simpler form, there are only two instructions: call another list and draw a polygon group. Also, each instruction has only a single string or integer as parameter. (Hopefully, there will be no need to try to pack multiple parameters into a string. For example, I split "Set Texture S Coordinate" and "Set Texture T Coordinate" into two commands, rather than try to stuff two coordinates into the string. The interface should handle such complexities, so there will be little need to work with list commands directly, once other methods are written.)
The major benefits of converting to this simpler format are: first off, obviously, it's simpler. Compare:
| 06 00 00 00 07 00 14 08 | CallList 07001408 |
04 00 18 60 04 00 01 00
BF 00 02 04 00 02 04 06
BF 08 0A 0C 00 0A 0C 0E
[...] | RenderGroup 04000100 |
and of course you can rename them to something more meaningful than "07001408".
Secondly, it's microcode-independent, and for that matter, platform-independent. The limitations of the N64 GPU and the F3DEX microcode do not apply. It is up to the Rena*-to-N64 parser routine (or will be, once it's written) to translate these instructions into something the N64 can handle - breaking polygon groups up into vertex cache chunks, inserting sync instructions where necessary, potentially splitting large textured billboards into several small polygons to work around the texture size limit, and warning if the input is simply too complex. That means it would be entirely possible to import a F3DEX display list, and export a Fast3D or F3DEX2 display list, despite them being binary-incompatible and having different limitations. For example you can't
directly port F3DEX to Fast3D because of the smaller vertex cache - instructions need to be added and changed. With this system you could even export to, say, Gamecube or PS2 games.
Aside from the obvious possibility that creates of easily moving models between games, I hope to also add support for importing other things. For example, import an SVG image as a flat track, give it some hills and bumps, and then add detail around it. Or import a 3D model directly.
The biggest stumbling block with importing is that any imported model will have to be split into regions the way the tracks are now. That means the editor will have to render at the game's native resolution, and advance slowly along the path, at each point rotating 360°, and determine if enough pixels have entered/left the view to warrant splitting at this point. I know how this will work, but it will almost certainly be slow - something like O(n
4). This is why I didn't opt to try to convert to an ordinary 3D model format in the first place, as you'd have to do this on every save, rather than just once on import.
I haven't thought much about exporting to 3D models - best to get it doing what it's intended to do before thinking about such exotic features - but I don't think that will be difficult to do either.
Simply put, although I'm designing it for Mario Kart initially, it promises to have a pretty big impact on other N64 game hacking as well, and perhaps even other consoles.
*Rena stands for Racetrack Editor, Navigator & Assembler and is totally not a backronym.____________________