Reverse Engineering Compressed UV Maps
In order for Disney Interactive to optimize the performance in their MMORPGs, much of the games hidden art assets were obfuscated to barely comprehensible asset files.
Preface: Some Background History
Back in the early days of video game optimization, it was vital to compress textures for lower-end graphics/video cards, while preserving just enough detail in order to illustrate the model. The common hardware used in game consoles (including PC gaming) wasn’t quite powerful enough to render a lot of high quality textures while preserving a stable, playable framerate.
Technically speaking, typical graphics cards back then only provided ~128 MB of vRAM for display memory. The vRAM [video RAM] is used to store visual information of the scene such as textures, 3D models, shaders, etc. Well, with so little amount of storage space to hold textures, this could become quite an issue when displaying dozens of different textures at once! If a single, uncompressed 1024x1024 RGBA texture uses 8 MB of vRAM, or even worse, an uncompressed 2048x2048 RGBA texture using 16 MB of vRAM, we’d run out of display memory pretty quickly!
Thus, the most efficient optimization method a game developer can use is getting rid of any unnecessary graphical differentiations; compressing graphics. The faster it takes to render objects onto the screen, the quicker more frames can be drawn in shorter time– referred to as frame rate or frames per second (fps). Ultimately, dropping a lot of the quality in displayed graphics resulted in better performance and compatibility with less powerful machines.
Link to the original image and some more interesting 2D graphical compression talk can be found here
As 3D graphics processing made way in the early 2000’s, many game developers were still limited with how much detail a model could have. While large, distributed server farms have been invented by companies to handle non-realtime complex 3D rendering, single consumer video acceleration cards were known to struggle even in less complex situations, due to the requirement of realtime rendering. As such, two approaches to modeling were born: high poly and low poly modeling. High poly models were traditionally chosen by 3D filmmakers, as their scenes only had to be pre-rendered once by powerful server farms. An example for such a high poly 3D movie is the famous 1995 comedy film Toy Story. Despite this, video game creators have been constantly forced to make do with less convoluted low poly models and lower resolution textures.
Researching Compression Techniques Used in a Disney Game
My focus in this post is going to be a single game that stands out the most to me. However, many points made here can be similar to situations encountered in other older video games.
Disney’s Toontown Online
Disney’s now-defunct MMORPG, “Disney’s Toontown Online” began development in the late ‘90s - early 2000’s when graphic/display hardware were still limited to only a few megabytes of vRAM at most. The game engine utilized for Toontown was Panda3D.
In order to provide the most compatibility for users to experience the game, detail had to be sacrificed in favor of stability. Thus, all of the 2D assets and 3D models in the game were to be compressed to use the fewest computer resources as possible.
All of Toontown’s 2D assets, including artwork done for the game, were downscaled to miniscule resolutions: 64x64, 128x128, 256x256, and at most, 512x512 for texture atlasing. 3D models were devised to use the fewest amount of polygons as possible, yet keeping important characteristics that were still distinguishable and identifiable to the player.
To increase framerate and performance, individual 2D textures were often palletized into images that contained multiple textures within themselves. Texture Atlasing, also referred to as texture tiling or texture paging, is the process of concatenating singular textures into one larger texture, reducing the time it takes to complete the model loading process. After all, loading less files is better for the hard drive, as well as GPU memory bus performance, contrary to loading every texture as individual files one at a time…
As stated by James Schauf, a 3D artist who had worked on Sellbot Field Offices for Toontown previously, “The requirements [to] keep everything really low poly, I mean REALLY low” with the entire scene, including props and modules. Since the early development of the Panda3D game engine and Toontown during the early 2000’s, resources were pretty limited on a game intended to be a 3D-based MMORPG for anyone to play. As a solution for dealing with a short allowance of resources, 3D artists created low-poly models for props that the player wouldn’t interact much with (contrary to their player model) and creating different level of detail (LOD) based models for objects that players saw and interacted with more commonly.
Compression a la Panda3D
In addition, Panda3D applies its own compression procedures such as FFTW / Fastest Fourier Transform in the West compression, utilized to compress animation channelsbefore sending data to the GPU, and zlib DEFLATE compression for internal 3D model vertex bookkeeping, to allow for relatively more complex models than normally possible with the aforementioned limitations. Panda3D applies a variety of different compression techniques to further optimize performance, however Panda’s compression magic is a whole different ball game to cover in itself!
Throughout my journey with investigating Toontown assets, I continuously encountered assets that were considerably compressed for game optimization. Many of the textures as seen in the game’s resource files (referred to as phase files) were outstandingly wonky-looking. When attempting to re-texture some of the Toontown models for practice, I only had one thought in mind: “how could ANYONE work with this extreme amount of distortion when texturing this model?!” Before I get into the distortion part, let me break down exactly what’s going on, step-by-step.
Accessing the Assets
Encryption / Decryption
Panda3D has a functionality to compress multiple files at once into a single file, decreasing the total file size that the assets require for distribution. This tool is known as the Multifile, and from the official Panda3D manual: Multifile archives are archive files that store game resources. Think of it as a giant zip file that stores, optionally compresses and encrypts your data files, but does not need to be extracted. source Since Panda3D is an open-source game engine, we can use the multifile tool to essentially “unzip” these multifiles, unpacking the contents inside.
Accessing / Viewing
Models accessed with Panda3D use two unique file types called
.egg files contain plaintext information about parts of the model, while
.bam is a compressed version of so. To view these models, we can use the Panda3D
Note: There’s much more to discuss about how Panda3D works with models, but that requires a whole different article to go on about.
Panda3D also comes with several tools to convert
.egg files into
.mtl, and even
.mb (Autodesk Maya) files! When converting from
.mb, the nodes (parts of the model), UV data, and material data (texture info) are preserved and kept the same way. Because of this, we now have the same UV maps for the converted model that’s seen in-game.
Dealing with Distortion
…Shoot, here comes the main focus of this post.… As I mentioned before, these models bare wonky, heavily distorted UV maps that are extremely difficult, if not impossible to work with. So, how do we mitigate this problem? TLDR for below: texture baking.
Texture Baking into Editable Textures
The first thing we need to do is re-UV map the model. Many Toontown models are notorious for having disconnected vertices, so it’s very important that we merge them together. When a loop of vertices are disconnected, Maya will treat that area as a different mesh – we don’t want that when we need to UV map.
Now that we’ve re-UV mapped the body portion of the bear, it’s time to start the texture baking process! What is texture baking? Texture baking is simply the process of transferring the details (such as textures) from one model to another. Baking textures from one model to another is a phenomenal idea, because that means we can transfer these distorted textures on to a UV map that’s comprehensible! For clarification, we can say that Model A is the original model containing the original UV map (Original being the texture found in the game assets after decompiling them!) and Model B is the newer model with the newer UV map, the model where Model A’s texture will be baked into. With the help of texture baking, we can convert these older textures on to newer UVs while preserving [most of] the original quality!
With the help of Autodesk Maya, Blender, and Panda3D tools, I was able to essentially “reverse-engineer” what was originally incomprehensible. Ultimately, with this technique, any artist could easily expand any compressed texture into a single texture that is way easier to work with.
This post was created to present my research for a personal independent research project. Please note that I’m really just making educated guesses on possible schemes that Toontown Online artists would’ve followed when texturing these 3D models. There is no public documentation on the procedures they adhered to. However, by researching techniques that were applied in similar video games during that time, we can presume these are techniques utilized in their process.
Credits, Sources used, etc.
High Poly vs. Low Poly Comparison
https://gamedevelopment.tutsplus.com/articles/using-texture-atlas-in-order-to-optimize-your-game--cms-26783 https://en.wikipedia.org/wiki/Texture_atlas https://www.gamasutra.com/view/feature/130940/practical_texture_atlases.php https://pages.jh.edu/~dighamm/research/2004_01_sta.pdf https://developer.amd.com/wordpress/media/2013/01/Chapter02-Mittring-Advanced_Virtual_Texture_Topics.pdf
UV mapping workflows
https://www.theseus.fi/bitstream/handle/10024/131241/Terava_Tapio.pdf?sequence=1&isAllowed=y https://web.archive.org/web/20170426214223/http://mesh.brown.edu/taubin/pdfs/Balmelli-etal-eg02.pdf https://www.cs.unc.edu/~isenburg/papers/is-ctcslp-03.pdf http://www.freepatentsonline.com/20190114821.pdf https://perso.liris.cnrs.fr/guillaume.lavoue/travaux/revue/CGF16.pdf