diff --git a/TR5Main/Game/collide.cpp b/TR5Main/Game/collide.cpp index 3c4c2aea8..03b951665 100644 --- a/TR5Main/Game/collide.cpp +++ b/TR5Main/Game/collide.cpp @@ -11,6 +11,7 @@ #include "sound.h" #include "trmath.h" #include "prng.h" +#include "room.h" using std::vector; using namespace TEN::Math::Random; @@ -44,7 +45,7 @@ int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, IT MESH_INFO* mesh = &room->mesh[j]; STATIC_INFO* staticMesh = &StaticObjects[mesh->staticNumber]; - if (mesh->flags & 1) + if (mesh->flags & StaticMeshFlags::VISIBLE) { if (collidingItem->pos.yPos + radius + STEP_SIZE/2 >= mesh->y + staticMesh->collisionBox.Y1) { @@ -194,24 +195,25 @@ void CollideSolidStatics(ITEM_INFO* item, COLL_INFO* coll) y < COLLISION_CHECK_DISTANCE && z < COLLISION_CHECK_DISTANCE) { - if ((mesh->flags & 1) && (mesh->flags & 2)) - CollideSolidStatic(item, mesh, coll); + if ((mesh->flags & StaticMeshFlags::VISIBLE) && (mesh->flags & StaticMeshFlags::SOLID)) + { + auto stInfo = StaticObjects[mesh->staticNumber]; + auto stPos = PHD_3DPOS(mesh->x, mesh->y, mesh->z, 0, mesh->yRot, 0); + + if (CollideSolidBounds(item, stInfo.collisionBox, stPos, coll)) + coll->hitStatic = true; + } } } } } -bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll) +bool CollideSolidBounds(ITEM_INFO* item, BOUNDING_BOX box, PHD_3DPOS pos, COLL_INFO* coll) { - auto stInfo = StaticObjects[mesh->staticNumber]; - - // Ignore collision if flag is not set - if (stInfo.flags & 1) - return false; + bool result = false; // Get DX static bounds in global coords - auto staticPos = PHD_3DPOS(mesh->x, mesh->y, mesh->z, 0, mesh->yRot, 0); - auto staticBounds = TO_DX_BBOX(&staticPos, &stInfo.collisionBox); + auto staticBounds = TO_DX_BBOX(&pos, &box); // Get local TR bounds and DX item bounds in global coords auto itemBBox = GetBoundsAccurate(item); @@ -323,30 +325,30 @@ bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll) } coll->hitCeiling = bottom; - coll->hitStatic = true; + result = true; } // Check if bounds still collide after top/bottom position correction if (!staticBounds.Intersects(TO_DX_BBOX(&PHD_3DPOS(item->pos.xPos, item->pos.yPos, item->pos.zPos), &collBox))) - return false; + return result; // Determine identity rotation/distance - auto distance = Vector3(item->pos.xPos, item->pos.yPos, item->pos.zPos) - Vector3(mesh->x, mesh->y, mesh->z); - auto c = phd_cos(mesh->yRot); - auto s = phd_sin(mesh->yRot); + auto distance = Vector3(item->pos.xPos, item->pos.yPos, item->pos.zPos) - Vector3(pos.xPos, pos.yPos, pos.zPos); + auto c = phd_cos(pos.yRot); + auto s = phd_sin(pos.yRot); // Rotate item to collision bounds identity - auto x = round(distance.x * c - distance.z * s) + mesh->x; + auto x = round(distance.x * c - distance.z * s) + pos.xPos; auto y = item->pos.yPos; - auto z = round(distance.x * s + distance.z * c) + mesh->z; + auto z = round(distance.x * s + distance.z * c) + pos.zPos; // Determine identity static collision bounds - auto XMin = mesh->x + stInfo.collisionBox.X1; - auto XMax = mesh->x + stInfo.collisionBox.X2; - auto YMin = mesh->y + stInfo.collisionBox.Y1; - auto YMax = mesh->y + stInfo.collisionBox.Y2; - auto ZMin = mesh->z + stInfo.collisionBox.Z1; - auto ZMax = mesh->z + stInfo.collisionBox.Z2; + auto XMin = pos.xPos + box.X1; + auto XMax = pos.xPos + box.X2; + auto YMin = pos.yPos + box.Y1; + auto YMax = pos.yPos + box.Y2; + auto ZMin = pos.zPos + box.Z1; + auto ZMax = pos.zPos + box.Z2; // Determine item collision bounds auto inXMin = x - coll->radius; @@ -360,7 +362,7 @@ bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll) if (inXMax <= XMin || inXMin >= XMax || inYMax <= YMin || inYMin >= YMax || inZMax <= ZMin || inZMin >= ZMax) - return false; + return result; // Calculate shifts @@ -383,12 +385,12 @@ bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll) rawShift.z = shiftRight; // Rotate previous collision position to identity - distance = Vector3(coll->old.x, coll->old.y, coll->old.z) - Vector3(mesh->x, mesh->y, mesh->z); - auto ox = round(distance.x * c - distance.z * s) + mesh->x; - auto oz = round(distance.x * s + distance.z * c) + mesh->z; + distance = Vector3(coll->old.x, coll->old.y, coll->old.z) - Vector3(pos.xPos, pos.yPos, pos.zPos); + auto ox = round(distance.x * c - distance.z * s) + pos.xPos; + auto oz = round(distance.x * s + distance.z * c) + pos.zPos; // Calculate collisison type based on identity rotation - switch (GetQuadrant(coll->facing - mesh->yRot)) + switch (GetQuadrant(coll->facing - pos.yRot)) { case NORTH: if (rawShift.x > coll->radius || rawShift.x < -coll->radius) @@ -476,18 +478,17 @@ bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll) } // Determine final shifts rotation/distance - distance = Vector3(x + coll->shift.x, y, z + coll->shift.z) - Vector3(mesh->x, mesh->y, mesh->z); - c = phd_cos(0 - mesh->yRot); - s = phd_sin(0 - mesh->yRot); + distance = Vector3(x + coll->shift.x, y, z + coll->shift.z) - Vector3(pos.xPos, pos.yPos, pos.zPos); + c = phd_cos(-pos.yRot); + s = phd_sin(-pos.yRot); // Calculate final shifts rotation/distance - coll->shift.x = (round(distance.x * c - distance.z * s) + mesh->x) - item->pos.xPos; - coll->shift.z = (round(distance.x * s + distance.z * c) + mesh->z) - item->pos.zPos; + coll->shift.x = (round(distance.x * c - distance.z * s) + pos.xPos) - item->pos.xPos; + coll->shift.z = (round(distance.x * s + distance.z * c) + pos.zPos) - item->pos.zPos; if (coll->shift.x == 0 && coll->shift.z == 0) coll->collType = CT_NONE; // Paranoid - coll->hitStatic = true; return true; } @@ -2756,10 +2757,8 @@ void DoObjectCollision(ITEM_INFO* l, COLL_INFO* coll) // previously LaraBaddieCo { MESH_INFO* mesh = &g_Level.Rooms[roomsToCheck[i]].mesh[j]; - // Flag 0x01: collision - // Flag 0x02: solid collision (processed in CollideSolidStatic) - - if ((mesh->flags & 1) && !(mesh->flags & 2)) + // Only process meshes which are visible and non-solid + if ((mesh->flags & StaticMeshFlags::VISIBLE) && !(mesh->flags & StaticMeshFlags::SOLID)) { int x = abs(l->pos.xPos - mesh->x); diff --git a/TR5Main/Game/collide.h b/TR5Main/Game/collide.h index e5a1432a2..2bdfe10a5 100644 --- a/TR5Main/Game/collide.h +++ b/TR5Main/Game/collide.h @@ -121,5 +121,5 @@ bool SnapToDiagonal(short& angle, int interval); void CalcItemToFloorRotation(ITEM_INFO* item, int radiusDivide = 1); Vector2 GetDiagonalIntersect(int xPos, int zPos, int splitType, int radius, short yRot); // find xPos, zPos that intersects with diagonal on sector Vector2 GetOrthogonalIntersect(int xPos, int zPos, int radius, short yRot); // find xPos, zPos near sector bound, offset by radius; -bool CollideSolidStatic(ITEM_INFO* item, MESH_INFO* mesh, COLL_INFO* coll); +bool CollideSolidBounds(ITEM_INFO* item, BOUNDING_BOX box, PHD_3DPOS pos, COLL_INFO* coll); void CollideSolidStatics(ITEM_INFO* item, COLL_INFO* coll); \ No newline at end of file diff --git a/TR5Main/Game/room.h b/TR5Main/Game/room.h index 38a11706e..d66283df2 100644 --- a/TR5Main/Game/room.h +++ b/TR5Main/Game/room.h @@ -83,6 +83,13 @@ enum RoomEnumFlag ENV_FLAG_UNKNOWN3 = 0x0400 }; +enum StaticMeshFlags : short +{ + NONE = 0, + VISIBLE = 1, + SOLID = 2 +}; + enum TriggerStatus { TS_OUTSIDE = 0, diff --git a/TR5Main/Renderer/Renderer11Frame.cpp b/TR5Main/Renderer/Renderer11Frame.cpp index 10a124a65..961064d2f 100644 --- a/TR5Main/Renderer/Renderer11Frame.cpp +++ b/TR5Main/Renderer/Renderer11Frame.cpp @@ -83,7 +83,7 @@ namespace TEN::Renderer for (int i = 0; i < numStatics; i++) { MESH_INFO *mesh = &r->mesh[i]; - if (mesh->flags & 1) + if (mesh->flags & StaticMeshFlags::VISIBLE) { RendererStatic* newStatic = &room.Statics[i]; STATIC_INFO* sinfo = &StaticObjects[mesh->staticNumber];