Both sides previous revisionPrevious revisionNext revision | Previous revision |
trs:room_geometry [2020/05/19 13:01] – [Room Light Structure] zdimension | trs:room_geometry [2024/12/13 18:40] (current) – [Room Vertex Structure] stohrendorf |
---|
''<nowiki>BoxIndex</nowiki>'' is a pointer to special [[trs:npc_behaviour#boxes|[Boxes]]] array entry, which is basically a subset of sectors with same height configuration. It is primarily used for AI pathfinding (see the [[trs:npc_behaviour|Non-player character behaviour]] chapter for more details). | ''<nowiki>BoxIndex</nowiki>'' is a pointer to special [[trs:npc_behaviour#boxes|[Boxes]]] array entry, which is basically a subset of sectors with same height configuration. It is primarily used for AI pathfinding (see the [[trs:npc_behaviour|Non-player character behaviour]] chapter for more details). |
| |
{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}In these games, ''<nowiki>BoxIndex</nowiki>'' field is more complicated, and actually contains //two packed values//. Bits 4..14 contain the //actual box index//, and bits 0..3 contain //material index//, which is used to produce specific footstep sound, when Lara is walking or running in this sector. On PlayStation game versions, this index was also used to determine if footprint textures should be applied to this particular place. Both procedures are invoked via ''FOOTPRINT_FX'' flipeffect, which is described in [[trs:miscellany#flipeffects|corresponding section]]. | {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}In these games, ''<nowiki>BoxIndex</nowiki>'' field is more complicated: |
| |
| <code cpp> |
| struct tr3_room_sector // 8 bytes |
| { |
| uint16_t FDindex; // Index into FloorData[] |
| uint16_t Material : 4; // Material index, used |
| uint16_t Box : 11; // Actual box index |
| uint16_t Stopper : 1; |
| uint8_t RoomBelow; // 255 is none |
| int8_t Floor; // Absolute height of floor |
| uint8_t RoomAbove; // 255 if none |
| int8_t Ceiling; // Absolute height of ceiling |
| }; |
| </code> |
| |
| ^ Hex value ^ ''%%0x8000%%'' ^ ''%%0x7FF0%%'' ^^^^^^^^^^^ ''%%0x000F%%'' ^^^^ |
| ^ Bit ^ 15 ^ 14 ^ 13 ^ 12 ^ 11 ^ 10 ^ 9 ^ 8 ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ |
| ^ Field | ''%%Stopper%%'' | ''%%Box%%'' ||||||||||| ''%%Material%%'' |||| |
| |
| ''Material'' is the //material index//, which is used to produce specific footstep sound, when Lara is walking or running in this sector. On PlayStation game versions, this index was also used to determine if footprint textures should be applied to this particular place. Both procedures are invoked via ''FOOTPRINT_FX'' flipeffect, which is described in [[trs:miscellany#flipeffects|corresponding section]]. |
| |
Majority of //material index// values are the same across game versions, but some of them exist only in particular game. Here is the description: | Majority of //material index// values are the same across game versions, but some of them exist only in particular game. Here is the description: |
| |
* **0** — Mud | * **0** — Mud |
* **1** — Snow (TR3 and TR5 only) | * **1** — Snow (TR3 and TR5 only) |
* **2** — Sand | * **2** — Sand |
Mud, snow, sand, grass and maybe some other materials produce footprints in PlayStation version. | Mud, snow, sand, grass and maybe some other materials produce footprints in PlayStation version. |
| |
Furthermore, in TR3-5, //actual box index// may contain special value 2047, which is most likely indicates that this sector is a slope on which Lara can slide (and, therefore, possibly impassable by most NPCs). | Furthermore, in TR3-5, //actual box index// may contain special value 2047 (full 1s), which is most likely indicates that this sector is a slope on which Lara can slide (and, therefore, possibly impassable by most NPCs). |
| |
==== Room Light Structure ==== | ==== Room Light Structure ==== |
| |
<note> TR engines always used static room lights only for processing lighting on entities (such as Lara, enemies, doors, and others). This is called //external lighting//. For room meshes, they used so-called internal, or //pre-baked// lighting, which is done on level building stage: lights are calculated and applied to room faces via vertex colours. There is no way to change room lighting when the level is compiled — meaning, any changes in light positions, intensities and colour won’t affect room faces. </note> | <note> TR engines always used static room lights only for processing lighting on entities (such as Lara, enemies, doors, and others). This is called //external lighting//. For room meshes, they used so-called internal, or //pre-baked// lighting, which is done on level building stage: lights are calculated and applied to room faces via vertex colours. There is no way to change room lighting when the level is compiled — meaning, any changes in light positions, intensities and colour won’t affect room faces. </note> |
| |
There are four different types of room light structures. First one is used in TR1-2, second is used in TR3, third is used in TR4, and fourth is used in TR5. Here is the description of each: | There are four different types of room light structures. First one is used in TR1-2, second is used in TR3, third is used in TR4, and fourth is used in TR5. Here is the description of each: |
uint32_t Fade1; // Falloff value | uint32_t Fade1; // Falloff value |
}; | }; |
</code> | |
| |
''<nowiki>X/Y/Z</nowiki>'' are in world coordinates. ''<nowiki>Intensity1/Intensity2</nowiki>'' are almost always equal. This lighting only affects //externally-lit// objects. Tomb Raider 1 has only the first of the paired ''<nowiki>Intensity</nowiki>'' and ''<nowiki>Fade</nowiki>'' values. | </code> |
| |
''<nowiki>Intensity1</nowiki>'' ranges from ''0'' (dark) to ''0x1FFF'' (bright). However, some rooms occasionally have some lights with intensity greater than ''0x1FFF'' (for example, look at room #9, 2nd light in ''<nowiki>level1.phd</nowiki>''). ''<nowiki>Fade1</nowiki>'' is the maximum distance the light shines on, and ranges from ''0'' to ''0x7FFF''. | ''<nowiki>X/Y/Z</nowiki>'' are in world coordinates. ''<nowiki>Intensity1/Intensity2</nowiki>'' are almost always equal. This lighting only affects //externally-lit// objects. Tomb Raider 1 has only the first of the paired ''<nowiki>Intensity</nowiki>'' and ''<nowiki>Fade</nowiki>'' values. |
| |
| ''<nowiki>Intensity1</nowiki>'' ranges from ''0'' (dark) to ''0x1FFF'' (bright). However, some rooms occasionally have some lights with intensity greater than ''0x1FFF'' (for example, look at room #9, 2nd light in ''<nowiki>level1.phd</nowiki>''). ''<nowiki>Fade1</nowiki>'' is the maximum distance the light shines on, and ranges from ''0'' to ''0x7FFF''. |
=== TR2 Room Lighting === | === TR2 Room Lighting === |
| |
uint32_t Fade2; // Only in TR2 | uint32_t Fade2; // Only in TR2 |
}; | }; |
</code> | |
| |
''<nowiki>Intensity2</nowiki>'' and ''<nowiki>Fade2</nowiki>'' values are seemingly not used. ''<nowiki>Intensity1</nowiki>'' can go very well beyond ''0x1FFF'', right to ''0x7FFF'' (ultra bright light). Above ''0x7FFF'', it is always black, so the number is pseudo-signed (negative values are always treated as zero). | </code> |
| |
| ''<nowiki>Intensity2</nowiki>'' and ''<nowiki>Fade2</nowiki>'' values are seemingly not used. ''<nowiki>Intensity1</nowiki>'' can go very well beyond ''0x1FFF'', right to ''0x7FFF'' (ultra bright light). Above ''0x7FFF'', it is always black, so the number is pseudo-signed (negative values are always treated as zero). |
=== TR3 Room Lighting === | === TR3 Room Lighting === |
| |
} | } |
}; | }; |
</code> | |
| |
''<nowiki>Intensity</nowiki>'' is the power of the light and ranges mainly from ''0'' (low power) to ''0x1FFF'' (high power). | </code> |
''<nowiki>Fade</nowiki>'' is the distance max the light can shine on. Range is mainly from ''0'' to ''0x7FFF''. | |
| |
| ''<nowiki>Intensity</nowiki>'' is the power of the light and ranges mainly from ''0'' (low power) to ''0x1FFF'' (high power). ''<nowiki>Fade</nowiki>'' is the distance max the light can shine on. Range is mainly from ''0'' to ''0x7FFF''. |
=== TR4 Room Lighting === | === TR4 Room Lighting === |
| |
float dx, dy, dz; // Direction - used only by sun and spot lights | float dx, dy, dz; // Direction - used only by sun and spot lights |
}; | }; |
| |
</code> | </code> |
| |
''<nowiki>LightType</nowiki>'' was extended and is now somewhat similar to D3D light type, but there are some differences. | ''<nowiki>LightType</nowiki>'' was extended and is now somewhat similar to D3D light type, but there are some differences. |
| |
* **0** — Sun | * **0** — Sun |
* **1** — Light | * **1** — Light |
* **2** — Spot | * **2** — Spot |
float r, g, b; // Colour of the light | float r, g, b; // Colour of the light |
| |
uint32_t Separator // Dummy value = 0xCDCDCDCD | uint32_t shadow; // Dummy value = 0xCDCDCDCD |
| |
float In; // Cosine of the IN value for light / size of IN value | float In; // Cosine of the IN value for light / size of IN value |
uint8_t Filler[3]; // Dummy values = 3 x 0xCD | uint8_t Filler[3]; // Dummy values = 3 x 0xCD |
}; | }; |
| |
</code> | </code> |
| |
{ | { |
float x, y, z; // Position of light, in world coordinates | float x, y, z; // Position of light, in world coordinates |
float r, g, b; // Colour of the light | float rad, sqrad; |
| float den; |
| float r, g, b; |
| }; |
| |
uint32_t Separator // Dummy value = 0xCDCDCDCD | |
| |
float In; // Cosine of the IN value for light / size of IN value | |
float Out; // Cosine of the OUT value for light / size of OUT value | |
}; | |
</code> | </code> |
| |
**TODO**: investigate exact meaning of ''tr5_fog_bulb'' fields. | |
| |
''<nowiki>x,y,z</nowiki>'' values shouldn’t be used by sun type light, but sun seems to have a large ''<nowiki>x</nowiki>'' value (9 million, give or take), a zero ''<nowiki>y</nowiki>'' value, and a small ''<nowiki>z</nowiki>'' value (4..20) in the original TR5 levels. | ''<nowiki>x,y,z</nowiki>'' values shouldn’t be used by sun type light, but sun seems to have a large ''<nowiki>x</nowiki>'' value (9 million, give or take), a zero ''<nowiki>y</nowiki>'' value, and a small ''<nowiki>z</nowiki>'' value (4..20) in the original TR5 levels. |
| |
''<nowiki>x2</nowiki>'', ''<nowiki>y2</nowiki>'', ''<nowiki>z2</nowiki>'', ''<nowiki>dx2</nowiki>'', ''<nowiki>dy2</nowiki>'' and ''<nowiki>dz2</nowiki>'' values repeat previous corresponding information in long data types instead of floats. | ''<nowiki>x2</nowiki>'', ''<nowiki>y2</nowiki>'', ''<nowiki>z2</nowiki>'', ''<nowiki>dx2</nowiki>'', ''<nowiki>dy2</nowiki>'' and ''<nowiki>dz2</nowiki>'' values repeat previous corresponding information in long data types instead of floats. |
| |
| |
==== Room Vertex Structure ==== | ==== Room Vertex Structure ==== |
int16_t Lighting; | int16_t Lighting; |
uint16_t Attributes; // A set of flags for special rendering effects | uint16_t Attributes; // A set of flags for special rendering effects |
int16_t Lighting2; // Almost always equal to Lighting1 | int16_t RenderedLighting; // Internal field to store the actually rendered lighting |
}; | }; |
</code> | </code> |
uint16_t NumLayerVertices; // Number of vertices in this layer (2 bytes) | uint16_t NumLayerVertices; // Number of vertices in this layer (2 bytes) |
uint16_t NumLayerVerticesWater; // Number of underwater vertices in this layer (2 bytes) | uint16_t NumLayerVerticesWater; // Number of underwater vertices in this layer (2 bytes) |
uint16_t UnknownL1; | uint16_t NumLayerVerticesShore; |
uint16_t NumLayerRectangles; // Number of rectangles in this layer (2 bytes) | uint16_t NumLayerRectangles; // Number of rectangles in this layer (2 bytes) |
uint16_t NumLayerTriangles; // Number of triangles in this layer (2 bytes) | uint16_t NumLayerTriangles; // Number of triangles in this layer (2 bytes) |
uint16_t UnknownL2; | uint16_t NumLayerRectanglesWater; // Number of rectangles containing water vertices |
| uint16_t NumLayerTrianglesWater; // Number of trianglescontaining water vertices |
| |
uint16_t Filler; // Always 0 | uint16_t Filler; // Always 0 |
uint16_t Filler2; // Always 0 | |
| |
// The following 6 floats define the bounding box for the layer | // The following 6 floats define the bounding box for the layer |
float LayerBoundingBoxZ2; | float LayerBoundingBoxZ2; |
| |
uint32_t Filler3; // Always 0 (4 bytes) | uint32_t Filler3; // Always 0 (4 bytes), internal pointer |
uint32_t VerticesOffset; // Those fields are overwritten at level loading | uint32_t VerticesOffset; // Those fields are overwritten at level loading |
uint32_t PolyOffset; // by the ones present in the tr5_room struct + an offset | uint32_t PolyOffset; // by the ones present in the tr5_room struct + an offset |
uint32_t PolyOffset2; // i.e. the values are not read, the fields are there for storage purposes | uint32_t PrelightOffset; // i.e. the values are not read, the fields are there for storage purposes |
} | } |
</code> | </code> |
| |
''<nowiki>UnknownL2</nowiki>'' appears to be the number of double sided textures in this layer, however is sometimes 1 off (2 bytes). | ''<nowiki>NumLayerVerticesShore</nowiki>'' appears to be the number of double sided textures in this layer, however is sometimes 1 off (2 bytes). |
| |
===== The Whole Room Structure ===== | ===== The Whole Room Structure ===== |
uint16_t NumZsectors; // ``Width'' of sector list | uint16_t NumZsectors; // ``Width'' of sector list |
uint16_t NumXsectors; // ``Height'' of sector list | uint16_t NumXsectors; // ``Height'' of sector list |
tr_room_sector SectorList[NumXsectors * NumZsectors]; // List of sectors in this room | tr3_room_sector SectorList[NumXsectors * NumZsectors]; // List of sectors in this room |
| |
int16_t AmbientIntensity; // Affects externally-lit objects | int16_t AmbientIntensity; // Affects externally-lit objects |
uint16_t NumZsectors; // ``Width'' of sector list | uint16_t NumZsectors; // ``Width'' of sector list |
uint16_t NumXsectors; // ``Height'' of sector list | uint16_t NumXsectors; // ``Height'' of sector list |
tr_room_sector SectorList[NumXsectors * NumZsectors]; // List of sectors in this room | tr3_room_sector SectorList[NumXsectors * NumZsectors]; // List of sectors in this room |
| |
uint32_t RoomColour; // In ARGB format! | uint32_t RoomColour; // In ARGB format! |
==== TR5 Room Structure ==== | ==== TR5 Room Structure ==== |
| |
As it was mentioned before, TR5 room structure was almost completely changed, when compared to previous versions. For example, TR5 completely throws out a concept of [[trs:room_geometry#tr_room_data|[tr_room_data]]] structure, shuffles numerous values and structures in almost chaotic manner, and introduces a bunch of completely new parameters (mostly to deal with //layers//). Also, there is vast amount of //fillers// and //separators//, which contain no specific data. | As it was mentioned before, TR5 room structure was almost completely changed, when compared to previous versions. For example, TR5 shuffles numerous values and structures in almost chaotic manner, and introduces a bunch of completely new parameters (mostly to deal with //layers//). Also, there is vast amount of //fillers// and //separators//, which contain no specific data. |
| |
| <note> The one possible reason for such ridiculous structure change is an attempt to //crypt file format//, so it won’t be accessed by unofficial level editing tools, which received major development by that time. Another possible reason is whole TR5 development process was rushed, as the team developed //Tomb Raider: Angel of Darkness// at the very same time. </note> |
| |
<note> The one possible reason for such ridiculous structure change is an attempt to //crypt file format//, so it won’t be accessed by unofficial level editing tools, which received major development by that time. Another possible reason is whole TR5 development process was rushed, as the team developed //Tomb Raider: Angel of Darkness// at the very same time. </note> | <note> There are multiple pointer fields in the structure, they are relative to the **end** of the ''tr5_room'' structure, i.e. to the beginning of the ''tr5_room_data'' structure.</note> |
| |
{{anchor:tr5_room}} | {{anchor:tr5_room}} |
| |
<code cpp> | <code cpp> |
virtual struct tr5_room // (variable length) | struct tr5_room // 216 bytes |
{ | { |
char XELA[4]; // So-called "XELA landmark" | char XELA[4]; // So-called "XELA landmark" |
| |
uint32_t RoomDataSize; | uint32_t RoomDataSize; // size of following fields (208 bytes) + tr5_room_data (dynamic) |
| |
uint32_t Separator; // 0xCDCDCDCD (4 bytes) | char* RoomData; // is filled by the game at run time. Always 0xCDCDCDCD in level files (4 bytes), |
| |
uint32_t EndSDOffset; | uint16_t* NumPortals; // points to tr5_room_data.NumPortals |
uint32_t StartSDOffset; | tr3_room_sector* SectorList; // points to tr5_room_data.SectorList |
| |
uint32_t Separator; // Either 0 or 0xCDCDCDCD | tr5_room_light* Lights; // points to tr5_room_data.Lights |
| |
uint32_t EndPortalOffset; | tr3_room_staticmesh* StaticMeshes; // points to tr5_room_data.StaticMeshes |
| |
tr5_room_info info; | tr5_room_info info; |
uint8_t ReverbInfo; | uint8_t ReverbInfo; |
uint8_t AlternateGroup; | uint8_t AlternateGroup; |
uint16_t WaterScheme; | |
| |
uint32_t Filler[2]; // Both always 0x00007FFF | int8_t MeshEffect; |
uint32_t Separator[2]; // Both always 0xCDCDCDCD | int8_t bound_active; |
uint32_t Filler; // Always 0xFFFFFFFF | |
| int16_t left; // always 0x7FFF |
| int16_t right; // always 0 |
| int16_t top; // always 0x7FFF |
| int16_t bottom; // always 0 |
| |
| int16_t test_left; // always 0xCDCD |
| int16_t test_right; // always 0xCDCD |
| int16_t test_top; // always 0xCDCD |
| int16_t test_bottom; // always 0xCDCD |
| |
| int16_t item_number; // always 0xFFFF (-1) |
| int16_t fx_number; // always 0xFFFF (-1) |
| |
uint16_t AlternateRoom; | uint16_t AlternateRoom; |
uint16_t Flags; | uint16_t Flags; |
| |
uint32_t Unknown1; | uint32_t nVerts; |
uint32_t Unknown2; // Always 0 | uint32_t nWaterVerts; // Always 0 |
uint32_t Unknown3; // Always 0 | uint32_t nShoreVerts; // Always 0 |
| |
uint32_t Separator; // 0xCDCDCDCD | uint32_t Separator; // 0xCDCDCDCD, internally a pointer |
| |
uint16_t Unknown4; | uint32_t Separator; // internally a pointer to the face data |
uint16_t Unknown5; | |
| |
float RoomX; | float RoomX; |
float RoomZ; | float RoomZ; |
| |
uint32_t Separator[4]; // Always 0xCDCDCDCD | uint32_t vnormals; // internal pointer |
uint32_t Separator; // 0 for normal rooms and 0xCDCDCDCD for null rooms | uint32_t fnormals; // internal pointer |
uint32_t Separator; // Always 0xCDCDCDCD | uint32_t prelight; // internal pointer |
| uint32_t prelightwater; // internal pointer |
| uint32_t watercalc; // internal pointer, 0 for normal rooms and 0xCDCDCDCD for null rooms |
| uint32_t verts; // internal pointer |
| |
uint32_t NumRoomTriangles; | uint32_t NumRoomTriangles; |
uint32_t NumRoomRectangles; | uint32_t NumRoomRectangles; |
| |
uint32_t Separator; // Always 0 | tr5_room_light* RoomLights; // points to tr5_room_data.RoomLights |
| tr5_fog_bulb* FogBulbs; // points to tr5_room_data.FogBulbs |
| |
uint32_t LightDataSize; | |
uint32_t NumLights2; // Always same as NumLights | uint32_t NumLights2; // Always same as NumLights |
| |
uint32_t NumFogBulbs; // Almost always 0. | uint32_t NumFogBulbs; |
| |
int32_t RoomYTop; | int32_t RoomYTop; |
uint32_t NumLayers; | uint32_t NumLayers; |
| |
uint32_t LayerOffset; | tr5_room_layer* Layers; // points to tr5_room_data.Layers |
uint32_t VerticesOffset; | tr5_room_vertex* Vertices; // points to tr5_room_data.Vertices |
uint32_t PolyOffset; | void* PolyOffset; // points to tr5_room_data.Faces |
uint32_t PolyOffset2; // Same as PolyOffset | void* PrelightOffset; // points to tr5_room_data.Faces, internal? |
| |
uint32_t NumVertices; | uint32_t NumVertices; |
| |
uint32_t Separator[4]; // Always 0xCDCDCDCD | // Always 0xCDCDCDCD |
| float fLeft; |
| float fRight; |
| float fTop; |
| float fBottom; |
| } |
| // immediately after |
| virtual struct tr5_room_data |
| { |
tr5_room_light Lights[NumLights]; // Data for the lights (88 bytes * NumRoomLights) | tr5_room_light Lights[NumLights]; // Data for the lights (88 bytes * NumRoomLights) |
tr5_fog_bulb FogBulbs[NumFogBulbs* 36]; // Data for the fog bulbs (36 bytes * NumFogBulbs) | tr5_fog_bulb FogBulbs[NumFogBulbs]; // Data for the fog bulbs (36 bytes * NumFogBulbs) |
tr_room_sector SectorList[NumXSectors * NumZSectors]; // List of sectors in this room | tr3_room_sector SectorList[NumXSectors * NumZSectors]; // List of sectors in this room |
| |
uint16_t NumPortals; // Number of visibility portals to other rooms | uint16_t NumPortals; // Number of visibility portals to other rooms |
tr5_room_vertex Vertices[NumVertices]; | tr5_room_vertex Vertices[NumVertices]; |
} | } |
| |
</code> | </code> |
| |
''<nowiki>XELA</nowiki>'' landmark seemingly serves as a header for room structure. It is clear that //XELA// is a reversed //ALEX//, which is most likely the name of TR5 programmer, //Alex Davis//. It probably indicates that Alex Davis is responsible for changes in room structures. | ''<nowiki>XELA</nowiki>'' landmark seemingly serves as a header for room structure. It is clear that //XELA// is a reversed //ALEX//, which is most likely the name of TR5 programmer, //Alex Davis//. It probably indicates that Alex Davis is responsible for changes in room structures. |
| |
''<nowiki>RoomDataSize</nowiki>'' is a handy value determining the size of the following data. You can use this value to quickly //parse thru// to the next room. | ''<nowiki>RoomDataSize</nowiki>'' is a handy value determining the size of the following data. You can use this value to quickly //parse thru// to the next room. |
| |
''<nowiki>EndSDOffset</nowiki>'': usually this number ''<nowiki>+216</nowiki>'' will give you the offset from the start of the room data to the end of the ''<nowiki>SectorData</nowiki>'' section. However, it is known that this uint32_t could be equal to ''<nowiki>0xFFFFFFFF</nowiki>'', so to calculate the end of ''<nowiki>SectorData</nowiki>'', it is better to use the following value $StartSDOffset + 216 + ((NumXSectors \cdot NumZSectors) \cdot 8)$, if you need to obtain this information. | ''<nowiki>RoomX</nowiki>'', ''<nowiki>RoomY</nowiki>'' and ''<nowiki>RoomZ</nowiki>'' values are positions of room in world coordinates. **NOTE:** If room is //null room//, then each of these values will be ''<nowiki>0xCDCDCDCD</nowiki>''. |
| |
''<nowiki>StartSDOffset</nowiki>'': This number ''<nowiki>+216</nowiki>'' will give you the offset from the start of the room to the start of the ''<nowiki>SectorData</nowiki>'' section. | ''<nowiki>NumRoomTriangles</nowiki>'' and ''<nowiki>NumRoomRectangles</nowiki>'' are respectively the numbers of triangular and rectangular faces in a given room. **NOTE:** If room is //null room//, each of these values will be ''<nowiki>0xCDCDCDCD</nowiki>''. |
| |
''<nowiki>EndPortalOffset</nowiki>'': this number ''<nowiki>+216</nowiki>'' will give you the offset from the start of the room to the end of the portal data. | ''<nowiki>LightDataSize</nowiki>'' is the size of the light data in bytes (//not// in [[:trs:room_geometry#tr5_room_light|[tr5_room_light]]] units). |
| |
''<nowiki>RoomX</nowiki>'', ''<nowiki>RoomY</nowiki>'' and ''<nowiki>RoomZ</nowiki>'' values are positions of room in world coordinates. **NOTE:** If room is //null room//, then each of these values will be ''<nowiki>0xCDCDCDCD</nowiki>''. | ''<nowiki>RoomYTop</nowiki>'' and ''<nowiki>RoomYBottom</nowiki>'' are equal to ''<nowiki>yTop</nowiki>'' and ''<nowiki>yBottom</nowiki>'' values in [[:trs:room_geometry#tr_room_info|[tr_room_info]]] structure. If room is a //null room//, both of these values are ''<nowiki>0xCDCDCDCD</nowiki>''. |
| |
''<nowiki>NumRoomTriangles</nowiki>'' and ''<nowiki>NumRoomRectangles</nowiki>'' are respectively the numbers of triangular and rectangular faces in a given room. **NOTE:** If room is //null room//, each of these values will be ''<nowiki>0xCDCDCDCD</nowiki>''. | ''<nowiki>NumLayers</nowiki>'' is a number of layers (volumes) in this room. |
| |
''<nowiki>LightDataSize</nowiki>'' is the size of the light data in bytes (//not// in [[trs:room_geometry#tr5_room_light|[tr5_room_light]]] units). | ''<nowiki>VerticesSize</nowiki>'' is the size of vertex data block in bytes. Therefore, it //must// be a multiple of [[:trs:room_geometry#tr5_room_vertex|[tr5_room_vertex]]] size, else it means the block size is wrong. |
| |
''<nowiki>RoomYTop</nowiki>'' and ''<nowiki>RoomYBottom</nowiki>'' are equal to ''<nowiki>yTop</nowiki>'' and ''<nowiki>yBottom</nowiki>'' values in [[trs:room_geometry#tr_room_info|[tr_room_info]]] structure. If room is a //null room//, both of these values are ''<nowiki>0xCDCDCDCD</nowiki>''. | ''<nowiki>Faces</nowiki>'' is a sequential data array for the room polygons (both [[:trs:fundamentals#tr_face4|[tr_face4]]] and [[:trs:fundamentals#tr_face3|[tr_face3]]]), |
| |
''<nowiki>NumLayers</nowiki>'' is a number of layers (volumes) in this room. | <note> ''<nowiki>Faces</nowiki>'' array is strictly linked with ''<nowiki>NumLayers</nowiki>'' value. The data is sequentially structured for each layer — at first it lists first layer’s rectangles then triangles, followed by the second layer’s rectangles and triangles, and so on, until all layers are done. </note> |
| |
''<nowiki>LayerOffset</nowiki>'': this number ''<nowiki>+216</nowiki>'' will give you an offset from the start of the room data to the start of the layer data. | |
| |
''<nowiki>VerticesOffset</nowiki>'': this number ''<nowiki>+216</nowiki>'' will give you an offset from the start of the room data to the start of the verex data. | |
| |
''<nowiki>PolyOffset</nowiki>'': this number ''<nowiki>+216</nowiki>'' will give you an offset from the start of the room data to the start of the rectangle/triangle data. | |
| |
''<nowiki>VerticesSize</nowiki>'' is the size of vertex data block in bytes. Therefore, it //must// be a multiple of [[trs:room_geometry#tr5_room_vertex|[tr5_room_vertex]]] size, else it means the block size is wrong. | |
| |
''<nowiki>Faces</nowiki>'' is a sequential data array for the room polygons (both [[trs:fundamentals#tr_face4|[tr_face4]]] and [[trs:fundamentals#tr_face3|[tr_face3]]]), | |
| |
<note> ''<nowiki>Faces</nowiki>'' array is strictly linked with ''<nowiki>NumLayers</nowiki>'' value. The data is sequentially structured for each layer — at first it lists first layer’s rectangles then triangles, followed by the second layer’s rectangles and triangles, and so on, until all layers are done. </note> | |
| |
==== Common Fields of a Room Structure ==== | ==== Common Fields of a Room Structure ==== |
| |
''<nowiki>Flags</nowiki>'' is an array of various flag bits, which meaning is as follows: | ''<nowiki>Flags</nowiki>'' is an array of various flag bits, which meaning is as follows: |
| |
* **Bit 0** — Room is filled with water. Sound effects played without internal flag ''SFX_WATER'' (''0x01'') will not play. | * **Bit 0** — Room is filled with water. Sound effects played without internal flag ''SFX_WATER'' (''0x01'') will not play. |
* **Bit 3** — {{:icons:tr2.png?nolink&}}{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Set if the //skybox// can be seen from this room. Used to speed things up: if no rendered room has this bit set, then the sky can never been seen, so it is not rendered. Else, if at least one visible room has this bit set, then the sky must be drawn because it is (could be) visible. | * **Bit 3** — {{:icons:tr2.png?nolink&}}{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Set if the //skybox// can be seen from this room. Used to speed things up: if no rendered room has this bit set, then the sky can never been seen, so it is not rendered. Else, if at least one visible room has this bit set, then the sky must be drawn because it is (could be) visible. |
* **Bit 5** — {{:icons:tr2.png?nolink&}}{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Lara’s ponytail gets blown by the wind. Beginning with TR3, some particle types are also be blown, if they end up in such room (particle type is specified by certain particle flag). | * **Bit 5** — {{:icons:tr2.png?nolink&}}{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Lara’s ponytail gets blown by the wind. Beginning with TR3, some particle types are also be blown, if they end up in such room (particle type is specified by certain particle flag). |
* **Bit 6** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Room is inside. Used in official levels. No apparent effects. | * **Bit 6** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Room is inside. Used in official levels. No apparent effects. |
* **Bit 7** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Different meaning in TR3 and TR4/5. In TR3, it means that room is filled with quicksand, while in TR4/5 it presumably blocks //global lens flare// from appearing in that room (in TRLE, checkbox which sets this flag is named //NL//). | * **Bit 7** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Different meaning in TR3 and TR4/5. In TR3, it means that room is filled with quicksand, while in TR4/5 it presumably blocks //global lens flare// from appearing in that room (in TRLE, checkbox which sets this flag is named //NL//). |
* **Bit 8** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Creates //caustics effect// similar to that used in water rooms. TRLE sets this bit when the M option is used (in the same time, the degree of fading intensity typed by the user is put in the ''<nowiki>water_scheme</nowiki>'' byte). | * **Bit 8** — {{:icons:tr1.png?nolink&16x16}}Skybox-like room. These must be rendered before other rooms with depth testing disabled, as these skybox rooms generally overlap each other and depth testing generall leads to z-fightig flickering. |
* **Bit 9** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} The room has some //water reflectivity//. TRLE sets this bit when the R (//reflectivity//) option is used (in the same time, the amount of reflectivity typed by the user + 5 is put in the ''<nowiki>water_scheme</nowiki>'' byte). When the flag is set for normal room and there is water room below it, game engine creates “reflection effect” above the water surface — effectively it means that all the vertices at the bottom of the room receive caustics effect described well above. | * **Bit 8** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Creates //caustics effect// similar to that used in water rooms. TRLE sets this bit when the M option is used (in the same time, the degree of fading intensity typed by the user is put in the ''<nowiki>water_scheme</nowiki>'' byte). |
| * **Bit 9** — {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}The room has some //water reflectivity//. TRLE sets this bit when the R (//reflectivity//) option is used (in the same time, the amount of reflectivity typed by the user + 5 is put in the ''<nowiki>water_scheme</nowiki>'' byte). When the flag is set for normal room and there is water room below it, game engine creates “reflection effect” above the water surface — effectively it means that all the vertices at the bottom of the room receive caustics effect described well above. |
* **Bit 10** — unused. Was re-used in NGLE as a flag specifying //room with snow//. | * **Bit 10** — unused. Was re-used in NGLE as a flag specifying //room with snow//. |
* **Bit 11** — {{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Not found in any original TR levels, but when the //D// flag is set in the TRLE, this bit is set. Was re-used in NGLE as a flag specifying //room with rain//. | * **Bit 11** — {{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Not found in any original TR levels, but when the //D// flag is set in the TRLE, this bit is set. Was re-used in NGLE as a flag specifying //room with rain//. |
* **Bit 12** — {{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} Not found in any original TR levels, but when the //P// flag is set in the TRLE, this bit is set. Was also re-used in NGLE as a flag specifying //cold room// (a room which produce damage on Lara). | * **Bit 12** — {{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}Not found in any original TR levels, but when the //P// flag is set in the TRLE, this bit is set. Was also re-used in NGLE as a flag specifying //cold room// (a room which produce damage on Lara). |
{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} ''<nowiki>WaterScheme</nowiki>'' is used for different purposes. If room is a water room, then it specifies underwater caustics patterns. If it is set for normal room //placed above the water room//, then it controls //wave strength// effect applied to the faces adjoining water room. Maximum value in both cases is 15. | {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}''<nowiki>WaterScheme</nowiki>'' is used for different purposes. If room is a water room, then it specifies underwater caustics patterns. If it is set for normal room //placed above the water room//, then it controls //wave strength// effect applied to the faces adjoining water room. Maximum value in both cases is 15. |
| |
{{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}} ''<nowiki>ReverbInfo</nowiki>'' defines //room reverberation type//. It affects sound postprocessing, if listener position belongs to that room. This feature was present //only in PlayStation versions// of the game, but not on PC. Nevertheless, the info is preserved in PC level files. Here are the types of reverberation: | {{:icons:tr3.png?nolink&}}{{:icons:tr4.png?nolink&}}{{:icons:tr5.png?nolink&}}''<nowiki>ReverbInfo</nowiki>'' defines //room reverberation type//. It affects sound postprocessing, if listener position belongs to that room. This feature was present //only in PlayStation versions// of the game, but not on PC. Nevertheless, the info is preserved in PC level files. Here are the types of reverberation: |
| |
* **0** — Outside. No (or barely heard) reverberation. | * **0** — Outside. No (or barely heard) reverberation. |
* **3** — Large room. | * **3** — Large room. |
* **4** — Pipe. Highest reverberation level. Almost never used. | * **4** — Pipe. Highest reverberation level. Almost never used. |
| |
\\ | |
| |
| |