Tomb Raider Forums  

Go Back   Tomb Raider Forums > Tomb Raider Series > Tomb Raider II

Reply
 
Thread Tools
Old 18-08-17, 22:17   #1
Arsunt
Member
 
Arsunt's Avatar
 
Joined: Jan 2010
Posts: 384
Exclamation Playstation Waving Inventory algorithm + Patch

Hello! Some of you know that I have been working for a long time on a project, related with the decompilation, bugfixing and software improvement of the first games of the Tomb Raider series, mainly TR2 and TR3. Several people even accused me of not sharing the technical details of my work with the community. Well, in my defense, I can say that I spend almost all my free time on the project itself, and most of the knowledge received and still rapidly arriving is in the form of separate drafts that have not been properly drawn up for use by anyone else. It's just pointless to give out incomprehensible material, 50% consisting of wild pseudocode, 25% of the assembler and 25% of the notes that are clear to me alone.

Nevertheless, I plan to write and submit to you articles with the most interesting in my opinion details in the jungle of the program code of the Tomb Raider games. Here is the first such article, and it describes the animated wallpaper of the PlayStation TR2 inventory. It takes time to complete the documentation, but time is not always there. The preparation of this article and the project itself for the release into open source took two weeks. All these two weeks I did not deal with the main programming tasks (except, of course, my fulltime work in the office, for which I get wages). But sooner or later, it was necessary to do this.

Update: Beta test is started. You can inspect the code and try the patch right now.
As bonus you get all pictures properly remastered by me (including all versions of title pictures).
Just unzip the latest version, copy to your game folder and launch.
Don't forget to try some nice options, that can be toggled by reg files from ExtraOptions folder.


Introduction

Before we begin, I want to say that all of the below that I discovered in the PlayStation game code I've implemented for PC too. Version of the game itself with the necessary improvements is in active development. Though it is in closed beta testing now, but will soon be available for everyone. Before this happens, I need to complete my TR2Draw dynamic library, which will allow to port the game to native DirectX 9 code (or any other API later, since the DLL is opensource). At last we could throw away DirectX 5 and the wrapper crutches (Yuk, I fiercely hate these workarounds!). The source code of a small part of this TR2Draw library, related to the animated wallpaper of the inventory, is already presented on GitHub.

There is video on YouTube comparing the original implementation of wallpaper on the PlayStaion, my implentation for the PC with the original textures, as well as one with the HD textures (also remastered by me).


If this article is TLDR for you, you can just click through links, videos, images and animations.
For everyone else, here we go!


Preparation

Behind the scenes, the Playstation TR2 generates an 13x9 array of vertices located in 2D plane. These vertices form 12x8 grid of equal textured squares. The center vertex is anchored to the center of the screen. The resulting grid of squares is scaled so that the height of the screen is equal to 4.5 of the height of a square. You can see bright red frame on the image below - this is game screen limits.


Click to enlarge tne image



Every such vertex has 3 parameters:
  • X screen coordinate
  • Y screen coordinate
  • Color
Coordinates can be both within the boundaries of the screen, and outside. As you see there is no Z coordinate, this mesh is totally flat. Color is always one of the shades of gray. When mixed with the colors of the texture, the color of the vertex determines the brightness of the texture. So next we will call this parameter as brightness, or amount of light. If brightness is 0% the texture becomes black, and if it is 100% the texture has original color.

All vertices receive a base 50% brightness (128/255), except for the farther ones (all of them are outside visible screen by the way). The farthermost vertices receive a 25% brightness (64/255), and the neighboring farther vertices receive 37.5% (96/255). Any square gets a gradient brightness depending on the brightness of each of its vertices. I do not know why the developers implemented a separate lighting scheme for these farther vertices, because this shade effect is actually not noticeable within the game screen at all. In my implementation for the PC, I did not obscure the vertices far beyond the screen.

Then the game initializes three angular variables that will control all subsequent animation. There is one small, but important detail. For most trigonometric calculations, Tomb Raider uses short integer (2 bytes) representations of angles, as well as the results of various functions such as the sine and cosine. This is in some way convenient, and also such calculations work much faster than full-fledged trigonometric floating-point operations. For all angle values we will use hexadecimal integer representation in this article.

Angle examples:
  • 0x0000 -> 0 degrees
  • 0x2000 -> 45 degrees
  • 0x4000 -> 90 degrees
  • 0x6000 -> 135 degrees
  • 0x8000 -> 180 degrees
  • 0xA000 -> 225 degrees
  • 0xC000 -> 270 degrees
  • 0xE000 -> 315 degrees
  • 0x0000 -> 360 degrees
When this hexadecimal value overflows through 0xFFFF it becomes 0x0000 and vice versa (0 degrees = 360 degrees).

Well so, the game initializes three angle variables.
Code:
static unsigned short deformWavePhase = 0x0000; // 0 degrees
static unsigned short shortWavePhase = 0x4000; // 90 degrees
static unsigned short longWavePhase = 0xA000; // 225 degrees
The game updates these variables every frame while you're in the inventory:
  • deformWavePhase and shortWavePhase decreases by 0x0267 (3.92 degrees)
  • longWavePhase decreases by 0x0200 (2.81 degrees)

We will need them in the next stages.


Deformation

Each vertex of the grid mesh, which we prepared in the last stage, must be shifted from the base position to a distance of 10% of the grid square width before the rendering. The direction of the shift is given by the individual angular phase of each vertex, which depends on the common phase (common phase is stored in deformWavePhase variable). In fact, each vertex spins in a circle around its base position with a radius equal to 10% of the grid square width. Cosines of its phase is X offset, sines is Y offset.




The extreme upper left vertex gets the common angular phase. The right vertex next to it gets a phase increased by 0x3000 (67.5 degrees), the lower vertex next to it gets a phase increased by 0x33E7 (73 degrees). And so each of the points gets its individual phase, calculated from points to the left and above. With every new frame, the phase changes, and all points synchronously rotate counter-clockwise by the amount of the common phase value change.

Schematically the simplified deformation is shown in the figure below. To shift the phase down and to the left, a value of 60 degrees is taken. Thus, in this simplified scheme, vertices are arranged at the corners of synchronously rotating hexagons (as you know the angle between the corners of the hexagon is 60 degrees).


Click to enlarge tne image



Lighting

This animated wallpaper is completely flat but it looks three-dimensional. This illusion is created by a special lighting formula that, like a deformation, spreads from the vertex to the vertex beginning from the top left corner.

The lighting of the vertices depends on two waves. One is short but slower, the second is long but faster. Each uses its common angular phase: shortWavePhase and longWavePhase. We need to get sines of these phases to get brightness values. As you remember, the base brightness of each vertex was 50% (128/255). In the highest position, each wave increases the base vertex brightness by 12.5% of the maximum (+32/255). At the lowest position, the wave reduces the brightness by 12.5% (-32/255). Two waves are summed up and, in some cases, the brightness value is changed to 25% (64/255) in the higher or lower side. So the resultant vertex brightness varies from 25% (64/255) to 75% (192/255).

Like for deformation, there are phase shifts from top left corner of the grid.
Short wave horizontal and vertical shifts are exactly the same as deformation shifts: 0x3000 (67.5 degrees) and 0x33E7 (73 degrees)
Long wave horizontal and vertical shifts have individual values: 0x1822 (33.94 degrees) and 0x1422 (28.31 degrees)


Click to enlarge tne image



These different shifts give us interesting two dimensional wave interference effects, because we have different wave lengths, different wave velocities, and even little different wave 2D directions. By the way you can read on the wikipedia about wave interference.

You can see the animated lighting scheme on the link below. For clarity, a pure red, undeformed, untextured sheet is used. For this demonstration, I wrote several chart functions, executed right in the game.


Click to play the animation



There is even more to come!

This is only one feature, which I tried to describe as clearly and briefly as possible. Maybe I missed something. In any case, I still have a whole warehouse for such improvements and even more bugfixes, and they are waiting for their time to be published. I propose to discuss these in the thread.

Last edited by Arsunt; 05-06-23 at 16:11.
Arsunt is offline   Reply With Quote
Old 18-08-17, 22:32   #2
Wooxman
Member
 
Joined: Jul 2012
Posts: 6,507
Default

That's so cool! Will you try to bring the other PS1 features to the PC versions?
Wooxman is offline   Reply With Quote
Old 18-08-17, 22:37   #3
Arsunt
Member
 
Arsunt's Avatar
 
Joined: Jan 2010
Posts: 384
Default

Quote:
Originally Posted by Wooxman View Post
That's so cool! Will you try to bring the other PS1 features to the PC versions?
Yep, they're halfway there.
Arsunt is offline   Reply With Quote
Old 18-08-17, 22:46   #4
Moosey
Member
 
Moosey's Avatar
 
Joined: Nov 2011
Posts: 1,709
Default

woah this is cool! Nice work!
Moosey is offline   Reply With Quote
Old 18-08-17, 23:15   #5
disapearing-boy
Member
 
disapearing-boy's Avatar
 
Joined: Oct 2006
Posts: 2,372
Default

Great work! Thanks for taking the time to share this.
disapearing-boy is offline   Reply With Quote
Old 19-08-17, 00:28   #6
Zebra
Member
 
Zebra's Avatar
 
Joined: Jun 2007
Posts: 26,910
Default

Great job ! Not just implementing the feature but also explaining it to us in so much detail. This is really interesting, thank you !
Zebra is offline   Reply With Quote
Old 19-08-17, 05:14   #7
ANoDE
Golden
 
ANoDE's Avatar
 
Joined: May 2005
Posts: 7,085
Default

That was a very interesting read, thanks!
ANoDE is online now   Reply With Quote
Old 19-08-17, 10:16   #8
michaeldt
Member
 
michaeldt's Avatar
 
Joined: May 2006
Posts: 16,750
Default

omg, would love to see a HD video
michaeldt is online now   Reply With Quote
Old 19-08-17, 12:13   #9
Teeth
Member
 
Teeth's Avatar
 
Joined: Dec 2006
Posts: 2,117
Default

This is amazing! Do you plan to release this to the public?

What else do you hope to bring to PC players? I'm thinking of the reflective save crystals and gold Lara from TR1.
Teeth is offline   Reply With Quote
Old 19-08-17, 18:42   #10
Alex Fly
Inactive
 
Alex Fly's Avatar
 
Joined: Dec 2006
Posts: 31,967
Default

Wow this is awesome and fascinating! Great job!
Alex Fly is offline   Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



All times are GMT. The time now is 06:01.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Tomb Raider Forums is not owned or operated by CDE Entertainment Ltd.
Lara Croft and Tomb Raider are trademarks of CDE Entertainment Ltd.