Both sides previous revisionPrevious revisionNext revision | Previous revision |
trs:fundamentals [2020/05/19 12:01] – [Rectangular (Quad) Face Definition] zdimension | trs:fundamentals [2020/05/19 12:16] (current) – [Fixed Point Data Types] zdimension |
---|
|''%%float%%'' |specifies a 32-bit IEEE-754 floating-point number | | |''%%float%%'' |specifies a 32-bit IEEE-754 floating-point number | |
|''%%fixed%%'' |specifies a 32-bit non-trivial 16.16 fixed point value — see further| | |''%%fixed%%'' |specifies a 32-bit non-trivial 16.16 fixed point value — see further| |
| |''%%ufixed16%%'' |specifies a 16-bit non-trivial 8.8 fixed point value — see further| |
| |
All multi-byte integers (''%%{u}int16_t%%'', ''%%{u}int32_t%%'') are stored in little-endian (Intel-x86, etc.) format, with the least significant byte stored first and the most significant byte stored last. When using this data in platforms with big-endian (PowerPC, etc.) number format, be sure to reverse the order of bytes. | All multi-byte integers (''%%{u}int16_t%%'', ''%%{u}int32_t%%'') are stored in little-endian (Intel-x86, etc.) format, with the least significant byte stored first and the most significant byte stored last. When using this data in platforms with big-endian (PowerPC, etc.) number format, be sure to reverse the order of bytes. |
| |
==== 32 bit Fixed Point Data Type ==== | ==== Fixed Point Data Types ==== |
| |
This is a 32 bit integer, where a unit (i.e., the 1 in the normal numerical sense) is expressed as $2^{16}$. Under the assumption that $f$ is a real number, and $p$ is a fixed-point number, the conversion is $f = p/2^{16}$, or $p = [f \cdot 2^{16}]$. | These very specific data types mimic floating-point behaviour, //while remaining integer//. It is done by splitting floating-point value into whole and fractional parts, and keeping each part as ''int16_t'' and ''uint16_t'' correspondingly for `fixed` type and as ''uint8_t'' and ''uint8_t'' for ''ufixed16'' type. Whole part is kept as it is, while fractional part is multiplied by 65536 (for ''fixed'') or by 255 (for ''ufixed16''), and then kept as unsigned integer. So, the formula to calculate floating-point from ''fixed'' is: |
| |
There are certain cases where special caution must be paid. A multiplication $f = f_1 \cdot f_2$ must be calculated as | $F_{real} = P_{whole} + ( P_{frac} \div 65536 )$ |
| |
$f = f_1 \cdot f_2 \Leftrightarrow f = (p_1/2^{16}) \cdot (p_1/2^{16}) \Leftrightarrow f = p/2^{16} = \frac{p_1 \cdot p_2}{2^{32}} \Leftrightarrow p = \frac{p_1 \cdot p_2}{2^{16}}$ | Formula to calculate floating-point from ''ufixed16'' is: |
| |
| $F_{real} = P_{whole} + ( P_{frac} \div 255 )$ |
| |
| ...where $P_{whole}$ is whole part of mixed float (signed for ''fixed'', unsigned for ''ufixed16''), and $P_{frac}$ is fractional part (unsigned). |
| |
| <note> |
| The reason why such complicated setup was invented is to avoid using floating-point numbers. In 90% of all cases, Tomb Raider engines use integer numbers, even |
| for geometry calculations and animation interpolations. The root of this setup lies in multi-platform nature of the code, which was simultaneously written for PC and PlayStation. While PCs had enough computational power to deal with floats at that time, PlayStation relied only on integers. |
| |
| However, some internal variables and constants (like drawing distance, fog distance constants and some light properties) are PC-specific and stored in floating |
| point numbers. Also, last game in series, TR5, extensively used floating-point numbers for certain data types – like colours, vertices and coordinates. |
| </note> |
| |
==== Data Alignment ==== | ==== Data Alignment ==== |
|//Bit 0 set, blending enabled// |//Bit 0 not set, blending disabled// | | |//Bit 0 set, blending enabled// |//Bit 0 not set, blending disabled// | |
| |
* //Bit 1:// if set, face has _environment mapping_ effect (so-called "shiny effect" in TRLE community). Environment map is derived from special pre-rendered texture. | * //Bit 1:// if set, face has //environment mapping// effect (so-called "shiny effect" in TRLE community). Environment map is derived from special pre-rendered texture. |
* //Bits 2..7:// strength of //environment mapping// effect (so-called “shiny effect” in TRLE community). Environment map is derived from special pre-rendered texture. The bigger the value is, the more visible the effect is. | * //Bits 2..7:// strength of //environment mapping// effect. The bigger the value is, the more visible the effect is. |
| |
|{{:illustrations:shine-on.jpg?nolink|illustrations/shine-on.jpg}}|{{:illustrations:shine-off.jpg?nolink|illustrations/shine-off.jpg}}| | |{{:illustrations:shine-on.jpg?nolink|illustrations/shine-on.jpg}}|{{:illustrations:shine-off.jpg?nolink|illustrations/shine-off.jpg}}| |