Restore previous room mesh generation method; fix trapdoor bridge collision mesh enable-disable; layout for door mesh management

This commit is contained in:
Sezz 2025-04-22 19:19:20 +10:00
parent 9980c0e900
commit ed741ab5be
9 changed files with 165 additions and 109 deletions

View file

@ -883,7 +883,7 @@ INVENTORY_PASSPORT
INVENTORY_SUNGLASSES INVENTORY_SUNGLASSES
INVENTORY_KEYS INVENTORY_KEYS
INVENTORY_HEADPHONES INVENTORY_HEADPHONES
INVENTORY_POLAROID INVENTORY_PHOTO
SMOKE_EMITTER_WHITE SMOKE_EMITTER_WHITE
SMOKE_EMITTER_BLACK SMOKE_EMITTER_BLACK
SMOKE_EMITTER SMOKE_EMITTER

View file

@ -294,7 +294,7 @@
</li> </li>
<li><span class="parameter">pos</span> <li><span class="parameter">pos</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
X,Y position of the bar's background in screen percent (0-100). X,Y position of the diary background sprite in screen percent (0-100).
</li> </li>
<li><span class="parameter">rot</span> <li><span class="parameter">rot</span>
<span class="types"><span class="type">float</span></span> <span class="types"><span class="type">float</span></span>
@ -302,7 +302,7 @@
</li> </li>
<li><span class="parameter">scale</span> <li><span class="parameter">scale</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
X,Y Scaling factor for the bar's background sprite. X,Y Scaling factor for the diary background sprite.
</li> </li>
<li><span class="parameter">alignMode</span> <li><span class="parameter">alignMode</span>
<span class="types"><a class="type" href="../4 enums/View.AlignMode.html#">AlignMode</a></span> <span class="types"><a class="type" href="../4 enums/View.AlignMode.html#">AlignMode</a></span>

View file

@ -8,6 +8,7 @@
#include "Game/room.h" #include "Game/room.h"
#include "Game/Setup.h" #include "Game/Setup.h"
#include "Objects/game_object_ids.h" #include "Objects/game_object_ids.h"
#include "Objects/Generic/Doors/generic_doors.h"
#include "Math/Math.h" #include "Math/Math.h"
#include "Renderer/Renderer.h" #include "Renderer/Renderer.h"
#include "Specific/level.h" #include "Specific/level.h"
@ -15,6 +16,7 @@
using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Floordata;
using namespace TEN::Collision::Point; using namespace TEN::Collision::Point;
using namespace TEN::Entities::Doors;
using namespace TEN::Math; using namespace TEN::Math;
using namespace TEN::Utils; using namespace TEN::Utils;
using TEN::Renderer::g_Renderer; using TEN::Renderer::g_Renderer;
@ -121,7 +123,7 @@ namespace TEN::Collision::Los
// 1) Collect room LOS collision. // 1) Collect room LOS collision.
los.Room = GetRoomLosCollision(origin, roomNumber, dir, dist); los.Room = GetRoomLosCollision(origin, roomNumber, dir, dist);
// 2) Collect item and sphere LOS collisions. // 2) Collect item and sphere LOS collisions (if applicable).
if (collideItems || collideSpheres) if (collideItems || collideSpheres)
{ {
// Run through nearby items. // Run through nearby items.
@ -267,6 +269,21 @@ namespace TEN::Collision::Los
{ {
closestTri = meshColl->Triangle; closestTri = meshColl->Triangle;
closestDist = meshColl->Distance; closestDist = meshColl->Distance;
// Run through bounded doors.
auto doorItemIds = room.DoorCollisionMeshes.GetBoundedIds(ray, closestDist);
for (int doorItemNumber : doorItemIds)
{
const auto& doorItem = g_Level.Items[doorItemNumber];
const auto& door = GetDoorObject(doorItem);
auto doorMeshColl = door.CollisionMesh.GetCollision(ray, closestDist);
if (doorMeshColl.has_value())
{
closestTri = doorMeshColl->Triangle;
closestDist = doorMeshColl->Distance;
}
}
} }
// 2.2) Clip bridge (if applicable). // 2.2) Clip bridge (if applicable).

View file

@ -1,7 +1,9 @@
#pragma once #pragma once
#include "Game/collision/floordata.h" #include "Game/collision/floordata.h"
struct ItemInfo; struct ItemInfo;
namespace TEN::Physics { class CollisionMesh; }
struct DOORPOS_DATA struct DOORPOS_DATA
{ {
@ -26,4 +28,6 @@ struct DOOR_DATA
unsigned char dn3; unsigned char dn3;
unsigned char dn4; unsigned char dn4;
ItemInfo* item; ItemInfo* item;
CollisionMesh CollisionMesh = {};
}; };

View file

@ -98,24 +98,44 @@ void RoomData::GenerateCollisionMesh()
// Get north sector (Z+). // Get north sector (Z+).
const auto* sectorNorth = &Sectors[(x * ZSize) + (z + 1)]; const auto* sectorNorth = &Sectors[(x * ZSize) + (z + 1)];
if (sectorNorth->SidePortalRoomNumber != NO_VALUE) if (sectorNorth->SidePortalRoomNumber != NO_VALUE)
sectorNorth = nullptr; {
const auto& room = g_Level.Rooms[sectorNorth->SidePortalRoomNumber];
auto gridCoord = GetRoomGridCoord(sectorNorth->SidePortalRoomNumber, sectorNorth->Position.x, sectorNorth->Position.y);
sectorNorth = &room.Sectors[(gridCoord.x * room.ZSize) + gridCoord.y];
}
// Get south sector (Z-). // Get south sector (Z-).
const auto* sectorSouth = &Sectors[(x * ZSize) + (z - 1)]; const auto* sectorSouth = &Sectors[(x * ZSize) + (z - 1)];
if (sectorSouth->SidePortalRoomNumber != NO_VALUE) if (sectorSouth->SidePortalRoomNumber != NO_VALUE)
sectorSouth = nullptr; {
const auto& prevRoomZ = g_Level.Rooms[sectorSouth->SidePortalRoomNumber];
auto prevRoomGridCoordZ = GetRoomGridCoord(sectorSouth->SidePortalRoomNumber, sectorSouth->Position.x, sectorSouth->Position.y);
sectorSouth = &prevRoomZ.Sectors[(prevRoomGridCoordZ.x * prevRoomZ.ZSize) + prevRoomGridCoordZ.y];
}
// Get east sector (X+). // Get east sector (X+).
const auto* sectorEast = &Sectors[((x + 1) * ZSize) + z]; const auto* sectorEast = &Sectors[((x + 1) * ZSize) + z];
if (sectorEast->SidePortalRoomNumber != NO_VALUE) if (sectorEast->SidePortalRoomNumber != NO_VALUE)
sectorEast = nullptr; {
const auto& room = g_Level.Rooms[sectorEast->SidePortalRoomNumber];
auto gridCoord = GetRoomGridCoord(sectorEast->SidePortalRoomNumber, sectorEast->Position.x, sectorEast->Position.y);
sectorEast = &room.Sectors[(gridCoord.x * room.ZSize) + gridCoord.y];
}
// Get west sector (X-). // Get west sector (X-).
const auto* sectorWest = &Sectors[((x - 1) * ZSize) + z]; const auto* sectorWest = &Sectors[((x - 1) * ZSize) + z];
if (sectorWest->SidePortalRoomNumber != NO_VALUE) if (sectorWest->SidePortalRoomNumber != NO_VALUE)
sectorWest = nullptr; {
const auto& room = g_Level.Rooms[sectorWest->SidePortalRoomNumber];
auto gridCoord = GetRoomGridCoord(sectorWest->SidePortalRoomNumber, sectorWest->Position.x, sectorWest->Position.y);
CollectSectorCollisionMeshTriangles(desc, sector, sectorNorth, sectorSouth, sectorEast, sectorWest); sectorWest = &room.Sectors[(gridCoord.x * room.ZSize) + gridCoord.y];
}
CollectSectorCollisionMeshTriangles(desc, sector, *sectorNorth, *sectorSouth, *sectorEast, *sectorWest);
} }
} }
desc.Optimize(); desc.Optimize();
@ -126,8 +146,8 @@ void RoomData::GenerateCollisionMesh()
void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc, void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
const FloorInfo& sector, const FloorInfo& sector,
const FloorInfo* sectorNorth, const FloorInfo* sectorSouth, const FloorInfo& sectorNorth, const FloorInfo& sectorSouth,
const FloorInfo* sectorEast, const FloorInfo* sectorWest) const FloorInfo& sectorEast, const FloorInfo& sectorWest)
{ {
constexpr auto SECTOR_SURFACE_COUNT = 2; constexpr auto SECTOR_SURFACE_COUNT = 2;
@ -207,7 +227,6 @@ void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
{ {
const auto& surface = isFloor ? sector.FloorSurface : sector.CeilingSurface; const auto& surface = isFloor ? sector.FloorSurface : sector.CeilingSurface;
auto& surfVertices = isFloor ? sectorVerts.Floor : sectorVerts.Ceil; auto& surfVertices = isFloor ? sectorVerts.Floor : sectorVerts.Ceil;
int sign = isFloor ? 1 : -1;
// 2.1) Set surface status data. // 2.1) Set surface status data.
surfVertices.IsSplit = sector.IsSurfaceSplit(isFloor); surfVertices.IsSplit = sector.IsSurfaceSplit(isFloor);
@ -252,18 +271,10 @@ void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
// +---+ // +---+
// | | Current // | | Current
// +---+ // +---+
if (sectorNorth != nullptr) const auto& surfNorth = isFloor ? sectorNorth.FloorSurface : sectorNorth.CeilingSurface;
{ surfVertices.NorthNeighbor.IsWall = sectorNorth.IsWall(1);
surfVertices.NorthNeighbor.IsWall = sectorNorth->IsWall(1); surfVertices.NorthNeighbor.Vertex0 = Vector3(corner1.x, getSurfaceTriangleVertexY(sectorNorth, REL_CORNER_0.x, REL_CORNER_0.y, 1, isFloor), corner1.y);
surfVertices.NorthNeighbor.Vertex0 = Vector3(corner1.x, getSurfaceTriangleVertexY(*sectorNorth, REL_CORNER_0.x, REL_CORNER_0.y, 1, isFloor), corner1.y); surfVertices.NorthNeighbor.Vertex1 = Vector3(corner2.x, getSurfaceTriangleVertexY(sectorNorth, REL_CORNER_3.x, REL_CORNER_3.y, 1, isFloor), corner2.y);
surfVertices.NorthNeighbor.Vertex1 = Vector3(corner2.x, getSurfaceTriangleVertexY(*sectorNorth, REL_CORNER_3.x, REL_CORNER_3.y, 1, isFloor), corner2.y);
}
else
{
int height = Aabb.Center.y + (Aabb.Extents.y * sign);
surfVertices.NorthNeighbor.Vertex0 = Vector3(corner1.x, height, corner1.y);
surfVertices.NorthNeighbor.Vertex1 = Vector3(corner2.x, height, corner2.y);
}
// 2.4) Set south neighbor data. // 2.4) Set south neighbor data.
// +---+ // +---+
@ -272,56 +283,30 @@ void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
// 0---1 // 0---1
// | X | South // | X | South
// +---+ // +---+
if (sectorSouth != nullptr) const auto& surfSouth = isFloor ? sectorSouth.FloorSurface : sectorSouth.CeilingSurface;
{ surfVertices.SouthNeighbor.IsWall = sectorSouth.IsWall(0);
surfVertices.SouthNeighbor.IsWall = sectorSouth->IsWall(0); surfVertices.SouthNeighbor.Vertex0 = Vector3(corner0.x, getSurfaceTriangleVertexY(sectorSouth, REL_CORNER_1.x, REL_CORNER_1.y, 0, isFloor), corner0.y);
surfVertices.SouthNeighbor.Vertex0 = Vector3(corner0.x, getSurfaceTriangleVertexY(*sectorSouth, REL_CORNER_1.x, REL_CORNER_1.y, 0, isFloor), corner0.y); surfVertices.SouthNeighbor.Vertex1 = Vector3(corner3.x, getSurfaceTriangleVertexY(sectorSouth, REL_CORNER_2.x, REL_CORNER_2.y, 0, isFloor), corner3.y);
surfVertices.SouthNeighbor.Vertex1 = Vector3(corner3.x, getSurfaceTriangleVertexY(*sectorSouth, REL_CORNER_2.x, REL_CORNER_2.y, 0, isFloor), corner3.y);
}
else
{
int height = Aabb.Center.y + (Aabb.Extents.y * sign);
surfVertices.NorthNeighbor.Vertex0 = Vector3(corner0.x, height, corner0.y);
surfVertices.NorthNeighbor.Vertex1 = Vector3(corner3.x, height, corner3.y);
}
// 2.5) Set east neighbor data. // 2.5) Set east neighbor data.
// +---+ 1---+ // +---+ 1---+
// Current | | | X | East // Current | | | X | East
// +---+ 0---+ // +---+ 0---+
if (sectorEast != nullptr) const auto& surfEast = isFloor ? sectorEast.FloorSurface : sectorEast.CeilingSurface;
{ bool useEastSurfTri0 = (!sectorEast.IsSurfaceSplit(isFloor) || surfEast.SplitAngle == SectorSurfaceData::SPLIT_ANGLE_0);
const auto& surfEast = isFloor ? sectorEast->FloorSurface : sectorEast->CeilingSurface; surfVertices.EastNeighbor.IsWall = sectorEast.IsWall(useEastSurfTri0 ? 0 : 1);
bool useEastSurfTri0 = (!sectorEast->IsSurfaceSplit(isFloor) || surfEast.SplitAngle == SectorSurfaceData::SPLIT_ANGLE_0); surfVertices.EastNeighbor.Vertex0 = Vector3(corner2.x, getSurfaceTriangleVertexY(sectorEast, REL_CORNER_1.x, REL_CORNER_1.y, useEastSurfTri0 ? 0 : 1, isFloor), corner2.y);
surfVertices.EastNeighbor.IsWall = sectorEast->IsWall(useEastSurfTri0 ? 0 : 1); surfVertices.EastNeighbor.Vertex1 = Vector3(corner3.x, getSurfaceTriangleVertexY(sectorEast, REL_CORNER_0.x, REL_CORNER_0.y, useEastSurfTri0 ? 0 : 1, isFloor), corner3.y);
surfVertices.EastNeighbor.Vertex0 = Vector3(corner2.x, getSurfaceTriangleVertexY(*sectorEast, REL_CORNER_1.x, REL_CORNER_1.y, useEastSurfTri0 ? 0 : 1, isFloor), corner2.y);
surfVertices.EastNeighbor.Vertex1 = Vector3(corner3.x, getSurfaceTriangleVertexY(*sectorEast, REL_CORNER_0.x, REL_CORNER_0.y, useEastSurfTri0 ? 0 : 1, isFloor), corner3.y);
}
else
{
int height = Aabb.Center.y + (Aabb.Extents.y * sign);
surfVertices.NorthNeighbor.Vertex0 = Vector3(corner2.x, height, corner2.y);
surfVertices.NorthNeighbor.Vertex1 = Vector3(corner3.x, height, corner3.y);
}
// 2.6) Set west neighbor data. // 2.6) Set west neighbor data.
// +---1 +---+ // +---1 +---+
// West | X | | | Current // West | X | | | Current
// +---0 +---+ // +---0 +---+
if (sectorWest != nullptr) const auto& surfWest = isFloor ? sectorWest.FloorSurface : sectorWest.CeilingSurface;
{ bool useWestSurfTri0 = !(!sectorWest.IsSurfaceSplit(isFloor) || surfWest.SplitAngle == SectorSurfaceData::SPLIT_ANGLE_0);
const auto& surfWest = isFloor ? sectorWest->FloorSurface : sectorWest->CeilingSurface; surfVertices.WestNeighbor.IsWall = sectorWest.IsWall(useWestSurfTri0 ? 0 : 1);
bool useWestSurfTri0 = !(!sectorWest->IsSurfaceSplit(isFloor) || surfWest.SplitAngle == SectorSurfaceData::SPLIT_ANGLE_0); surfVertices.WestNeighbor.Vertex0 = Vector3(corner0.x, getSurfaceTriangleVertexY(sectorWest, REL_CORNER_3.x, REL_CORNER_3.y, useWestSurfTri0 ? 0 : 1, isFloor), corner0.y);
surfVertices.WestNeighbor.IsWall = sectorWest->IsWall(useWestSurfTri0 ? 0 : 1); surfVertices.WestNeighbor.Vertex1 = Vector3(corner1.x, getSurfaceTriangleVertexY(sectorWest, REL_CORNER_2.x, REL_CORNER_2.y, useWestSurfTri0 ? 0 : 1, isFloor), corner1.y);
surfVertices.WestNeighbor.Vertex0 = Vector3(corner0.x, getSurfaceTriangleVertexY(*sectorWest, REL_CORNER_3.x, REL_CORNER_3.y, useWestSurfTri0 ? 0 : 1, isFloor), corner0.y);
surfVertices.WestNeighbor.Vertex1 = Vector3(corner1.x, getSurfaceTriangleVertexY(*sectorWest, REL_CORNER_2.x, REL_CORNER_2.y, useWestSurfTri0 ? 0 : 1, isFloor), corner1.y);
}
else
{
int height = Aabb.Center.y + (Aabb.Extents.y * sign);
surfVertices.NorthNeighbor.Vertex0 = Vector3(corner0.x, height, corner0.y);
surfVertices.NorthNeighbor.Vertex1 = Vector3(corner1.x, height, corner1.y);
}
isFloor = !isFloor; isFloor = !isFloor;
} }
@ -505,34 +490,7 @@ void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
} }
} }
// 2.5) Collect west cardinal wall triangles. // 2.5) Collect east cardinal wall triangles.
bool isTriWallWest = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.IsWall : surfVerts.Tri1.IsWall;
if (!isTriWallWest || !surfVerts.WestNeighbor.IsWall)
{
// Full wall.
if (isFloor && (!isTriWallWest && surfVerts.WestNeighbor.IsWall))
{
const auto& vertex0 = sectorVerts.Floor.IsSplitAngle0 ? sectorVerts.Floor.Tri0.Vertex0 : sectorVerts.Floor.Tri1.Vertex0;
const auto& vertex1 = sectorVerts.Floor.IsSplitAngle0 ? sectorVerts.Floor.Tri0.Vertex1 : sectorVerts.Floor.Tri1.Vertex1;
const auto& vertex2 = sectorVerts.Ceil.IsSplitAngle0 ? sectorVerts.Ceil.Tri0.Vertex1 : sectorVerts.Ceil.Tri1.Vertex1;
const auto& vertex3 = sectorVerts.Ceil.IsSplitAngle0 ? sectorVerts.Ceil.Tri0.Vertex0 : sectorVerts.Ceil.Tri1.Vertex0;
insertWallTriangles(isFloor, vertex0, vertex1, vertex2, vertex3);
}
// Step wall.
else if (!isTriWallWest && !surfVerts.WestNeighbor.IsWall)
{
const auto& vertex0 = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.Vertex0 : surfVerts.Tri1.Vertex0;
const auto& vertex1 = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.Vertex1 : surfVerts.Tri1.Vertex1;
const auto& vertex2 = surfVerts.WestNeighbor.Vertex1;
const auto& vertex3 = surfVerts.WestNeighbor.Vertex0;
if (isFloor ? !(vertex0.y <= vertex3.y && vertex1.y <= vertex2.y) : !(vertex0.y >= vertex3.y && vertex1.y >= vertex2.y))
insertWallTriangles(isFloor, vertex0, vertex1, vertex2, vertex3);
}
}
// 2.6) Collect east cardinal wall triangles.
bool isTriWallEast = surfVerts.IsSplitAngle0 ? surfVerts.Tri1.IsWall : surfVerts.Tri0.IsWall; bool isTriWallEast = surfVerts.IsSplitAngle0 ? surfVerts.Tri1.IsWall : surfVerts.Tri0.IsWall;
if (!isTriWallEast || !surfVerts.EastNeighbor.IsWall) if (!isTriWallEast || !surfVerts.EastNeighbor.IsWall)
{ {
@ -559,6 +517,33 @@ void RoomData::CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
} }
} }
// 2.6) Collect west cardinal wall triangles.
bool isTriWallWest = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.IsWall : surfVerts.Tri1.IsWall;
if (!isTriWallWest || !surfVerts.WestNeighbor.IsWall)
{
// Full wall.
if (isFloor && (!isTriWallWest && surfVerts.WestNeighbor.IsWall))
{
const auto& vertex0 = sectorVerts.Floor.IsSplitAngle0 ? sectorVerts.Floor.Tri0.Vertex0 : sectorVerts.Floor.Tri1.Vertex0;
const auto& vertex1 = sectorVerts.Floor.IsSplitAngle0 ? sectorVerts.Floor.Tri0.Vertex1 : sectorVerts.Floor.Tri1.Vertex1;
const auto& vertex2 = sectorVerts.Ceil.IsSplitAngle0 ? sectorVerts.Ceil.Tri0.Vertex1 : sectorVerts.Ceil.Tri1.Vertex1;
const auto& vertex3 = sectorVerts.Ceil.IsSplitAngle0 ? sectorVerts.Ceil.Tri0.Vertex0 : sectorVerts.Ceil.Tri1.Vertex0;
insertWallTriangles(isFloor, vertex0, vertex1, vertex2, vertex3);
}
// Step wall.
else if (!isTriWallWest && !surfVerts.WestNeighbor.IsWall)
{
const auto& vertex0 = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.Vertex0 : surfVerts.Tri1.Vertex0;
const auto& vertex1 = surfVerts.IsSplitAngle0 ? surfVerts.Tri0.Vertex1 : surfVerts.Tri1.Vertex1;
const auto& vertex2 = surfVerts.WestNeighbor.Vertex1;
const auto& vertex3 = surfVerts.WestNeighbor.Vertex0;
if (isFloor ? !(vertex0.y <= vertex3.y && vertex1.y <= vertex2.y) : !(vertex0.y >= vertex3.y && vertex1.y >= vertex2.y))
insertWallTriangles(isFloor, vertex0, vertex1, vertex2, vertex3);
}
}
isFloor = !isFloor; isFloor = !isFloor;
} }
} }

View file

@ -158,8 +158,9 @@ struct RoomData
//RoomObjectHandler Moveables = RoomObjectHandler(); // TODO: Refactor linked list of items in room to use a BVH instead. //RoomObjectHandler Moveables = RoomObjectHandler(); // TODO: Refactor linked list of items in room to use a BVH instead.
//RoomObjectHandler Statics = RoomObjectHandler(); // TODO: Refactor to use BVH. //RoomObjectHandler Statics = RoomObjectHandler(); // TODO: Refactor to use BVH.
std::vector<MESH_INFO> mesh = {}; // Statics std::vector<MESH_INFO> mesh = {}; // Statics
RoomObjectHandler DoorCollisionMeshes = {};
CollisionMesh CollisionMesh = TEN::Physics::CollisionMesh(); CollisionMesh CollisionMesh = {};
RoomObjectHandler Bridges = RoomObjectHandler(); RoomObjectHandler Bridges = RoomObjectHandler();
std::vector<PortalData> Portals = {}; std::vector<PortalData> Portals = {};
std::vector<TriggerVolume> TriggerVolumes = {}; std::vector<TriggerVolume> TriggerVolumes = {};
@ -178,8 +179,8 @@ struct RoomData
private: private:
void CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc, void CollectSectorCollisionMeshTriangles(CollisionMeshDesc& desc,
const FloorInfo& sector, const FloorInfo& sector,
const FloorInfo* sectorNorth, const FloorInfo* sectorSouth, const FloorInfo& sectorNorth, const FloorInfo& sectorSouth,
const FloorInfo* sectorEast, const FloorInfo* sectorWest); const FloorInfo& sectorEast, const FloorInfo& sectorWest);
}; };
void DoFlipMap(int group); void DoFlipMap(int group);

View file

@ -42,6 +42,16 @@ namespace TEN::Entities::Doors
EulerAngles(ANGLE(80.0f), ANGLE(80.0f), ANGLE(80.0f))) EulerAngles(ANGLE(80.0f), ANGLE(80.0f), ANGLE(80.0f)))
}; };
const DOOR_DATA& GetDoorObject(const ItemInfo& item)
{
return *(DOOR_DATA*)item.Data;
}
DOOR_DATA& GetDoorObject(ItemInfo& item)
{
return *(DOOR_DATA*)item.Data;
}
void InitializeDoor(short itemNumber) void InitializeDoor(short itemNumber)
{ {
auto* doorItem = &g_Level.Items[itemNumber]; auto* doorItem = &g_Level.Items[itemNumber];
@ -67,20 +77,32 @@ namespace TEN::Entities::Doors
int zOffset = 0; int zOffset = 0;
if (doorItem->Pose.Orientation.y == 0) if (doorItem->Pose.Orientation.y == 0)
{
zOffset = -BLOCK(1); zOffset = -BLOCK(1);
}
else if (doorItem->Pose.Orientation.y == ANGLE(180.0f)) else if (doorItem->Pose.Orientation.y == ANGLE(180.0f))
{
zOffset = BLOCK(1); zOffset = BLOCK(1);
}
else if (doorItem->Pose.Orientation.y == ANGLE(90.0f)) else if (doorItem->Pose.Orientation.y == ANGLE(90.0f))
{
xOffset = -BLOCK(1); xOffset = -BLOCK(1);
}
else else
{
xOffset = BLOCK(1); xOffset = BLOCK(1);
}
auto* r = &g_Level.Rooms[doorItem->RoomNumber]; // TODO: Initialize collision mesh.
doorData->d1.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x + xOffset, doorItem->Pose.Position.z - r->Position.z + zOffset);
auto* room = &g_Level.Rooms[doorItem->RoomNumber];
doorData->d1.floor = GetSector(room, doorItem->Pose.Position.x - room->Position.x + xOffset, doorItem->Pose.Position.z - room->Position.z + zOffset);
auto roomNumber = doorData->d1.floor->SidePortalRoomNumber; auto roomNumber = doorData->d1.floor->SidePortalRoomNumber;
if (roomNumber == NO_VALUE) if (roomNumber == NO_VALUE)
{
boxNumber = doorData->d1.floor->PathfindingBoxID; boxNumber = doorData->d1.floor->PathfindingBoxID;
}
else else
{ {
auto* b = &g_Level.Rooms[roomNumber]; auto* b = &g_Level.Rooms[roomNumber];
@ -90,14 +112,16 @@ namespace TEN::Entities::Doors
doorData->d1.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d1.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE;
doorData->d1.data = *doorData->d1.floor; doorData->d1.data = *doorData->d1.floor;
if (r->flippedRoom != NO_VALUE) if (room->flippedRoom != NO_VALUE)
{ {
r = &g_Level.Rooms[r->flippedRoom]; room = &g_Level.Rooms[room->flippedRoom];
doorData->d1flip.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x + xOffset, doorItem->Pose.Position.z - r->Position.z + zOffset); doorData->d1flip.floor = GetSector(room, doorItem->Pose.Position.x - room->Position.x + xOffset, doorItem->Pose.Position.z - room->Position.z + zOffset);
roomNumber = doorData->d1flip.floor->SidePortalRoomNumber; roomNumber = doorData->d1flip.floor->SidePortalRoomNumber;
if (roomNumber == NO_VALUE) if (roomNumber == NO_VALUE)
{
boxNumber = doorData->d1flip.floor->PathfindingBoxID; boxNumber = doorData->d1flip.floor->PathfindingBoxID;
}
else else
{ {
auto* b = &g_Level.Rooms[roomNumber]; auto* b = &g_Level.Rooms[roomNumber];
@ -108,7 +132,9 @@ namespace TEN::Entities::Doors
doorData->d1flip.data = *doorData->d1flip.floor; doorData->d1flip.data = *doorData->d1flip.floor;
} }
else else
{
doorData->d1flip.floor = NULL; doorData->d1flip.floor = NULL;
}
twoRoom = doorData->d1.floor->SidePortalRoomNumber; twoRoom = doorData->d1.floor->SidePortalRoomNumber;
@ -122,12 +148,14 @@ namespace TEN::Entities::Doors
} }
else else
{ {
r = &g_Level.Rooms[twoRoom]; room = &g_Level.Rooms[twoRoom];
doorData->d2.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x, doorItem->Pose.Position.z - r->Position.z); doorData->d2.floor = GetSector(room, doorItem->Pose.Position.x - room->Position.x, doorItem->Pose.Position.z - room->Position.z);
roomNumber = doorData->d2.floor->SidePortalRoomNumber; roomNumber = doorData->d2.floor->SidePortalRoomNumber;
if (roomNumber == NO_VALUE) if (roomNumber == NO_VALUE)
{
boxNumber = doorData->d2.floor->PathfindingBoxID; boxNumber = doorData->d2.floor->PathfindingBoxID;
}
else else
{ {
auto* b = &g_Level.Rooms[roomNumber]; auto* b = &g_Level.Rooms[roomNumber];
@ -137,14 +165,16 @@ namespace TEN::Entities::Doors
doorData->d2.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d2.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE;
doorData->d2.data = *doorData->d2.floor; doorData->d2.data = *doorData->d2.floor;
if (r->flippedRoom != -1) if (room->flippedRoom != -1)
{ {
r = &g_Level.Rooms[r->flippedRoom]; room = &g_Level.Rooms[room->flippedRoom];
doorData->d2flip.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x, doorItem->Pose.Position.z - r->Position.z); doorData->d2flip.floor = GetSector(room, doorItem->Pose.Position.x - room->Position.x, doorItem->Pose.Position.z - room->Position.z);
roomNumber = doorData->d2flip.floor->SidePortalRoomNumber; roomNumber = doorData->d2flip.floor->SidePortalRoomNumber;
if (roomNumber == NO_VALUE) if (roomNumber == NO_VALUE)
{
boxNumber = doorData->d2flip.floor->PathfindingBoxID; boxNumber = doorData->d2flip.floor->PathfindingBoxID;
}
else else
{ {
auto* b = &g_Level.Rooms[roomNumber]; auto* b = &g_Level.Rooms[roomNumber];
@ -155,7 +185,9 @@ namespace TEN::Entities::Doors
doorData->d2flip.data = *doorData->d2flip.floor; doorData->d2flip.data = *doorData->d2flip.floor;
} }
else else
{
doorData->d2flip.floor = NULL; doorData->d2flip.floor = NULL;
}
ShutThatDoor(&doorData->d2, doorData); ShutThatDoor(&doorData->d2, doorData);
ShutThatDoor(&doorData->d2flip, doorData); ShutThatDoor(&doorData->d2flip, doorData);
@ -395,6 +427,10 @@ namespace TEN::Entities::Doors
if (sector == nullptr) if (sector == nullptr)
return; return;
// TODO: No.
auto& room = g_Level.Rooms[sector->RoomNumber];
room.DoorCollisionMeshes.Insert(dd->item->Index, sector->Aabb);
*doorPos->floor = doorPos->data; *doorPos->floor = doorPos->data;
int pathfindingBoxID = doorPos->block; int pathfindingBoxID = doorPos->block;
@ -414,6 +450,10 @@ namespace TEN::Entities::Doors
if (sector == nullptr) if (sector == nullptr)
return; return;
// TODO: No.
auto& room = g_Level.Rooms[sector->RoomNumber];
room.DoorCollisionMeshes.Remove(dd->item->Index);
sector->PathfindingBoxID = NO_VALUE; sector->PathfindingBoxID = NO_VALUE;
sector->TriggerIndex = 0; sector->TriggerIndex = 0;

View file

@ -8,6 +8,9 @@ struct RoomData;
namespace TEN::Entities::Doors namespace TEN::Entities::Doors
{ {
const DOOR_DATA& GetDoorObject(const ItemInfo& item);
DOOR_DATA& GetDoorObject(ItemInfo& item);
void InitializeDoor(short itemNumber); void InitializeDoor(short itemNumber);
void DoorCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void DoorCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
void DoorControl(short itemNumber); void DoorControl(short itemNumber);

View file

@ -265,13 +265,19 @@ namespace TEN::Entities::Generic
void CloseTrapDoor(short itemNumber) void CloseTrapDoor(short itemNumber)
{ {
auto* trapDoorItem = &g_Level.Items[itemNumber]; auto& trapDoorItem = g_Level.Items[itemNumber];
trapDoorItem->ItemFlags[2] = 1; auto& bridge = GetBridgeObject(trapDoorItem);
trapDoorItem.ItemFlags[2] = 1;
bridge.Enable(trapDoorItem);
} }
void OpenTrapDoor(short itemNumber) void OpenTrapDoor(short itemNumber)
{ {
auto* trapDoorItem = &g_Level.Items[itemNumber]; auto& trapDoorItem = g_Level.Items[itemNumber];
trapDoorItem->ItemFlags[2] = 0; auto& bridge = GetBridgeObject(trapDoorItem);
trapDoorItem.ItemFlags[2] = 0;
bridge.Disable(trapDoorItem);
} }
} }