Both sides previous revisionPrevious revisionNext revision | Previous revision |
trs:meshes_models [2017/02/04 16:33] – ↷ Links adapted because of a move operation stohrendorf | trs:meshes_models [2021/02/09 16:08] (current) – [Meshes] stohrendorf |
---|
| {{indexmenu_n>4}} |
| |
====== Meshes and Models ====== | ====== Meshes and Models ====== |
| |
===== Overview ===== | ===== Overview ===== |
| |
Nearly all of the non-geographic visual elements in TR (as well as a few parts of the landscape) consist of as meshes. A //mesh// is simply a list of vertices and how they’re arranged. The mesh structure includes a list of vertices as relative coordinates (which allows meshes to easily be placed anywhere in the world geometry), a list of normals (to indicate which side of each face is visible), and lists of Rectangles and Triangles, both textured and coloured. The elements of each [[trs:savegame:trs:fundamentals#tr_face4|[tr_face4]]] or [[trs:savegame:trs:fundamentals#tr_face3|[tr_face3]]] (or same version-specific) structure (Rectangles and Triangles) contain an offset into the ''%%Vertices[]%%'' array for the mesh. Other arrays (''%%Entities[]%%'', ''%%StaticMeshes[]%%'') do not reference the array ''%%Meshes[]%%'' directly, but instead reference the array ''%%MeshPointers[]%%'', which points to locations inside of ''%%Meshes[]%%'', inside of which the meshes are stored in packed fashion. | Nearly all of the non-geographic visual elements in TR (as well as a few parts of the landscape) consist of as meshes. A //mesh// is simply a list of vertices and how they’re arranged. The mesh structure includes a list of vertices as relative coordinates (which allows meshes to easily be placed anywhere in the world geometry), a list of normals (to indicate which side of each face is visible), and lists of Rectangles and Triangles, both textured and coloured. The elements of each [[trs:fundamentals#tr_face4|[tr_face4]]] or [[trs:fundamentals#tr_face3|[tr_face3]]] (or same version-specific) structure (Rectangles and Triangles) contain an offset into the ''%%Vertices[]%%'' array for the mesh. Other arrays (''%%Entities[]%%'', ''%%StaticMeshes[]%%'') do not reference the array ''%%Meshes[]%%'' directly, but instead reference the array ''%%MeshPointers[]%%'', which points to locations inside of ''%%Meshes[]%%'', inside of which the meshes are stored in packed fashion. |
| |
<note tip> | <note tip> |
{ | { |
tr_vertex Centre; | tr_vertex Centre; |
int32_t CollRadius; | int16_t CollRadius; |
| uint16_t Flags; // 0x01 for Flat Shaded, i.e. Normals should not affect lighting |
| |
int16_t NumVertices; // Number of vertices in this mesh | int16_t NumVertices; // Number of vertices in this mesh |
}; | }; |
</code> | </code> |
''%%Centre%%'' is usually close to the mesh’s centroid, and appears to be the center of a sphere used for certain kinds of collision testing. | ''%%Centre%%'' is usually close to the mesh’s centroid, and is the center of a sphere used for certain kinds of collision testing. |
| |
''%%CollRadius%%'' appears to be the radius of that aforementioned collisional sphere. | ''%%CollRadius%%'' is the radius of that aforementioned collisional sphere. |
| |
''%%NumNormals%%'': If positive, it is a number of normals in this mesh. If negative, it is a number of vertex lighting elements (''%%abs%%'' value). | ''%%NumNormals%%'': If positive, it is a number of normals in this mesh. If negative, it is a number of vertex lighting elements (''%%abs%%'' value). |
| |
Depending on a value of ''%%NumNormals%%'', next data block is interpreted either as ''%%Normals[]%%'' array (in [[trs:savegame:trs:fundamentals#tr_vertex|[tr_vertex]]] format) or ''%%Lights%%'' array (just standard ''%%int16_t%%'' values). | Depending on a value of ''%%NumNormals%%'', next data block is interpreted either as ''%%Normals[]%%'' array (in [[trs:fundamentals#tr_vertex|[tr_vertex]]] format) or ''%%Lights%%'' array (just standard ''%%int16_t%%'' values). |
| |
''%%NumTexturedTriangles%%'' and ''%%NumTexturedRectangles%%'' are respectively the number of triangular and rectangular faces in this mesh. Corresponding ''%%TexturedTriangles%%'' and ''%%TexturedRectangles%%'' array contain textured triangles and rectangles themselves. | ''%%NumTexturedTriangles%%'' and ''%%NumTexturedRectangles%%'' are respectively the number of triangular and rectangular faces in this mesh. Corresponding ''%%TexturedTriangles%%'' and ''%%TexturedRectangles%%'' array contain textured triangles and rectangles themselves. |
''%%VisibilityBox%%'' and ''%%CollisionBox%%'' boundaries is always stay axis aligned even after applying tr_room_staticmesh::Rotation (always have 90 degrees step). Additionally, the test whether to rotate the box or not relies on the mesh’s rotation being an exact multiple of 0x4000 (aka 90 degrees). If this is not the case, the box is not rotated, which results in wrong collision checks. | ''%%VisibilityBox%%'' and ''%%CollisionBox%%'' boundaries is always stay axis aligned even after applying tr_room_staticmesh::Rotation (always have 90 degrees step). Additionally, the test whether to rotate the box or not relies on the mesh’s rotation being an exact multiple of 0x4000 (aka 90 degrees). If this is not the case, the box is not rotated, which results in wrong collision checks. |
| |
{{:icons:tr1.png?nolink|TR1 only}}{{:icons:tr2.png?nolink|TR2 only}} ''%%Flags%%'' value is usually 2, and is 3 for static meshes //without collision//, like plants and lying skeletons. Since TR3, value is ignored, and no-collision mode is obtained using degenerate collision box (with all-zero or all-one coordinates). | {{:icons:tr1.png?nolink|TR1 only}}{{:icons:tr2.png?nolink|TR2 only}}{{:icons:tr3.png?nolink|TR3 only}} ''%%Flags%%'': |
| * **Bit 0** (''0x0001''): no collision |
| * **Bit 1** (''0x0002''): is visible |
| |
===== Models ===== | ===== Models ===== |
''%%Angle%%'' is an //Euler Yaw angle// (i.e. “horizontal” rotation) stored in a special manner. To convert it to ordinary degrees, use this formula: | ''%%Angle%%'' is an //Euler Yaw angle// (i.e. “horizontal” rotation) stored in a special manner. To convert it to ordinary degrees, use this formula: |
| |
$\angle^\circ = (Angle \div 16384) \times -90$ | $\angle^\circ = \frac{Angle}{16384} \cdot -90$ |
| |
{{:icons:tr1.png?nolink|TR1 only}} ''%%Intensity2%%'' field is missing in this game version, so the structure size is 2 bytes less. | {{:icons:tr1.png?nolink|TR1 only}} ''%%Intensity2%%'' field is missing in this game version, so the structure size is 2 bytes less. |
struct tr_sprite_texture // 16 bytes | struct tr_sprite_texture // 16 bytes |
{ | { |
uint16_t Tile; | uint16_t Atlas; |
uint8_t x; | uint8_t x; |
uint8_t y; | uint8_t y; |
}; | }; |
</code> | </code> |
{{:icons:tr4.png?nolink|TR4 only}}{{:icons:tr5.png?nolink|TR5 only}} ''%%x%%'' and ''%%y%%'' values //are not used// in this version. Additionally, formula for ''%%Width%%'' and ''%%Height%%'' is changed: now it’s $(\text{ActualWidth} - 1) * 256$ and $(\text{ActualHeight} - 1) * 256$ respectively. | {{:icons:tr4.png?nolink|TR4 only}}{{:icons:tr5.png?nolink|TR5 only}} ''%%x%%'' and ''%%y%%'' values //are not used// in this version. Additionally, formula for ''%%Width%%'' and ''%%Height%%'' is changed: now it’s $(\text{ActualWidth} - 1) \cdot 256$ and $(\text{ActualHeight} - 1) \cdot 256$ respectively. |
| |
===== Sprite Sequences ===== | ===== Sprite Sequences ===== |