diff --git a/TR5Main/Game/Lara/lara.cpp b/TR5Main/Game/Lara/lara.cpp index 9b85c6062..137e2a302 100644 --- a/TR5Main/Game/Lara/lara.cpp +++ b/TR5Main/Game/Lara/lara.cpp @@ -47,6 +47,9 @@ #include "inventory.h" #endif +#include "Game/rope.h" + +using namespace TEN::Game::Rope; using std::function; using TEN::Renderer::g_Renderer; using namespace TEN::Control::Volumes; diff --git a/TR5Main/Game/Lara/lara_objects.cpp b/TR5Main/Game/Lara/lara_objects.cpp index 240a51544..e7d68a022 100644 --- a/TR5Main/Game/Lara/lara_objects.cpp +++ b/TR5Main/Game/Lara/lara_objects.cpp @@ -9,6 +9,9 @@ #include "collide.h" #include "items.h" #include "control/control.h" +#include "Game/rope.h" + +using namespace TEN::Game::Rope; /*This file has "all" lara_as/lara_col functions where Lara is interacting with an object.*/ diff --git a/TR5Main/Game/rope.cpp b/TR5Main/Game/rope.cpp index 6c2c50c8b..e6c724103 100644 --- a/TR5Main/Game/rope.cpp +++ b/TR5Main/Game/rope.cpp @@ -9,750 +9,794 @@ #include "camera.h" #include "items.h" -PENDULUM CurrentPendulum; -PENDULUM AlternatePendulum; -ROPE_STRUCT Ropes[12]; -int NumRopes, RopeSwing = 0; - -void InitialiseRope(short itemNumber) +namespace TEN::Game::Rope { - PHD_VECTOR itemPos; + PENDULUM CurrentPendulum; + PENDULUM AlternatePendulum; + std::vector Ropes; + int RopeSwing = 0; - ITEM_INFO* item = &g_Level.Items[itemNumber]; - short roomNumber = item->roomNumber; - - itemPos.x = item->pos.xPos; - itemPos.y = item->pos.yPos; - itemPos.z = item->pos.zPos; - - FLOOR_INFO* floor = GetFloor(itemPos.x, itemPos.y, itemPos.z, &roomNumber); - itemPos.y = GetCeiling(floor, itemPos.x, itemPos.y, itemPos.z); - - PHD_VECTOR pos; - pos.x = 0; - pos.y = 16384; - pos.z = 0; - - ROPE_STRUCT* rope = &Ropes[NumRopes]; - - PrepareRope(rope, &itemPos, &pos, 128, item); - - item->triggerFlags = NumRopes; - NumRopes++; -} - -void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item) -{ - rope->position = *pos1; - rope->segmentLength = length << 16; - - pos2->x <<= 16; - pos2->y <<= 16; - pos2->z <<= 16; - - NormaliseRopeVector(pos2); - - if (item->triggerFlags == -1) - rope->coiled = 30; - else - rope->coiled = 0; - - int l = 0; - int sum = 0; - int il = 3145728; - - for (int i = 0; i < 24; ++i) + void InitialiseRope(short itemNumber) { - rope->segment[i].x = (int64_t)sum * pos2->x >> 16; - rope->segment[i].y = (int64_t)sum * pos2->x >> 16; - rope->segment[i].z = (int64_t)sum * pos2->z >> 16; + PHD_VECTOR itemPos; - rope->velocity[i].x = 0; - rope->velocity[i].y = 0; - rope->velocity[i].z = 0; + ITEM_INFO* item = &g_Level.Items[itemNumber]; + short roomNumber = item->roomNumber; + + itemPos.x = item->pos.xPos; + itemPos.y = item->pos.yPos; + itemPos.z = item->pos.zPos; + + FLOOR_INFO* floor = GetFloor(itemPos.x, itemPos.y, itemPos.z, &roomNumber); + itemPos.y = GetCeiling(floor, itemPos.x, itemPos.y, itemPos.z); + + PHD_VECTOR pos; + pos.x = 0; + pos.y = 16384; + pos.z = 0; + + ROPE_STRUCT rope; + PrepareRope(&rope, &itemPos, &pos, 128, item); + + item->triggerFlags = Ropes.size(); + + Ropes.push_back(rope); + } + + void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item) + { + rope->position = *pos1; + rope->segmentLength = length << 16; + + pos2->x <<= 16; + pos2->y <<= 16; + pos2->z <<= 16; + + NormaliseRopeVector(pos2); if (item->triggerFlags == -1) + rope->coiled = 30; + else + rope->coiled = 0; + + int l = 0; + int sum = 0; + int il = 3145728; + + for (int i = 0; i < ROPE_SEGMENTS; ++i) { - rope->segment[i].x = l; - rope->segment[i].y >>= 4; + rope->segment[i].x = (int64_t)sum * pos2->x >> FP_SHIFT; + rope->segment[i].y = (int64_t)sum * pos2->x >> FP_SHIFT; + rope->segment[i].z = (int64_t)sum * pos2->z >> FP_SHIFT; - rope->velocity[i].x = 16384; - rope->velocity[i].y = il; - rope->velocity[i].z = 16384; - } - - l += 1024; - sum += rope->segmentLength; - il -= 131072; - } - - rope->active = 0; -} - -PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec) -{ - int x = vec->x >> 16; - int y = vec->y >> 16; - int z = vec->z >> 16; - - if (!x && !y && !z) - return vec; - - int length = SQUARE(x) + SQUARE(y) + SQUARE(z); - if (length < 0) - length = -length; - - length = 65536 / sqrt(length); - - vec->x = ((int64_t) length * vec->x) / 65536; - vec->y = ((int64_t) length * vec->y) / 65536; - vec->z = ((int64_t) length * vec->z) / 65536; - return vec; -} - -void _0x0046D130(ROPE_STRUCT* rope, int segmentFrame, int* x, int* y, int* z) -{ - int segment; - short frame; - - segment = segmentFrame / 128; - frame = segmentFrame & 0x7F; - *x = (rope->normalisedSegment[segment].x * frame >> 16) + (rope->meshSegment[segment].x >> 16) + rope->position.x; - *y = (rope->normalisedSegment[segment].y * frame >> 16) + (rope->meshSegment[segment].y >> 16) + rope->position.y; - *z = (rope->normalisedSegment[segment].z * frame >> 16) + (rope->meshSegment[segment].z >> 16) + rope->position.z; -} - -int DotProduct(PHD_VECTOR* u, PHD_VECTOR* v) -{ - return (u->x * v->x + u->y * v->y + u->z * v->z) / 16384; -} - -void ScaleVector(PHD_VECTOR* u, int c, PHD_VECTOR* destination) -{ - destination->x = c * u->x / 16384; - destination->y = c * u->y / 16384; - destination->z = c * u->z / 16384; -} - -void CrossProduct(PHD_VECTOR* u, PHD_VECTOR* v, PHD_VECTOR* destination) -{ - destination->x = (u->y * v->z - u->z * v->y) / 16384; - destination->y = (u->z * v->x - u->x * v->z) / 16384; - destination->z = (u->x * v->y - u->y * v->x) / 16384; -} - -void _0x0046D420(int* matrix, short* angle) -{ - angle[0] = phd_atan(sqrt(SQUARE(matrix[M22]) + SQUARE(matrix[M02])), matrix[M12]); - if (matrix[M12] >= 0 && angle[0] > 0 || matrix[M12] < 0 && angle[0] < 0) - angle[0] = -angle[0]; - angle[1] = phd_atan(matrix[M22], matrix[M02]); - angle[2] = phd_atan(matrix[M00] * phd_cos(angle[1]) - matrix[M20] * phd_sin(angle[1]), matrix[M21] * phd_sin(angle[1]) - matrix[M01] * phd_cos(angle[1])); -} - -void RopeControl(short itemNumber) -{ - ITEM_INFO* item; - ROPE_STRUCT* rope; - - item = &g_Level.Items[itemNumber]; - rope = &Ropes[item->triggerFlags]; - if (TriggerActive(item)) - { - rope->active = 1; - RopeDynamics(rope); - } - else - { - rope->active = 0; - } -} - -void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) -{ - ITEM_INFO* item; - ROPE_STRUCT* rope; - BOUNDING_BOX* frame; - int segment; - - item = &g_Level.Items[itemNumber]; - rope = &Ropes[item->triggerFlags]; - if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && (l->currentAnimState == LS_REACH || l->currentAnimState == LS_JUMP_UP) && l->gravityStatus && l->fallspeed > 0 && rope->active) - { - frame = GetBoundsAccurate(l); - segment = _0x0046D200(rope, l->pos.xPos, l->pos.yPos + frame->Y1 + 512, l->pos.zPos + frame->Z2 * phd_cos(l->pos.yRot), l->currentAnimState == LS_REACH ? 128 : 320); - if (segment >= 0) - { - if (l->currentAnimState == LS_REACH) - { - l->animNumber = LA_REACH_TO_ROPE_SWING; - l->currentAnimState = LS_ROPE_SWING; - Lara.ropeFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 32 << 8; - Lara.ropeDFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 60 << 8; - } - else - { - l->animNumber = LA_JUMP_UP_TO_ROPE_START; - l->currentAnimState = LS_ROPE_IDLE; - } - l->frameNumber = g_Level.Anims[l->animNumber].frameBase; - l->gravityStatus = false; - l->fallspeed = 0; - Lara.gunStatus = LG_HANDS_BUSY; - Lara.ropePtr = item->triggerFlags; - Lara.ropeSegment = segment; - Lara.ropeY = l->pos.yRot; - DelAlignLaraToRope(l); - CurrentPendulum.Velocity.x = 0; - CurrentPendulum.Velocity.y = 0; - CurrentPendulum.Velocity.z = 0; - ApplyVelocityToRope(segment, l->pos.yRot, 16 * LaraItem->speed); - } - } -} - -void RopeDynamics(ROPE_STRUCT* rope) -{ - int flag, i; - PENDULUM* pendulumPointer; - PHD_VECTOR vec, vec2; - - flag = 0; - if (rope->coiled) - { - --rope->coiled; - if (!rope->coiled) - { - for (i = 0; i < 24; ++i) - rope->velocity[i].y = 0; - } - } - if (rope == &Ropes[Lara.ropePtr]) - { - pendulumPointer = &CurrentPendulum; - if (CurrentPendulum.node != Lara.ropeSegment + 1) - { - _0x0046E1C0(rope, Lara.ropeSegment + 1); - flag = 1; - } - } - else - { - pendulumPointer = &AlternatePendulum; - if (Lara.ropePtr == -1 && CurrentPendulum.Rope) - { - for (i = 0; i < CurrentPendulum.node; ++i) - { - CurrentPendulum.Rope->velocity[i].x = CurrentPendulum.Rope->velocity[CurrentPendulum.node].x; - CurrentPendulum.Rope->velocity[i].y = CurrentPendulum.Rope->velocity[CurrentPendulum.node].y; - CurrentPendulum.Rope->velocity[i].z = CurrentPendulum.Rope->velocity[CurrentPendulum.node].z; - } - CurrentPendulum.Position.x = 0; - CurrentPendulum.Position.y = 0; - CurrentPendulum.Position.z = 0; - CurrentPendulum.Velocity.x = 0; - CurrentPendulum.Velocity.y = 0; - CurrentPendulum.Velocity.z = 0; - CurrentPendulum.node = -1; - CurrentPendulum.Rope = NULL; - } - } - if (Lara.ropePtr != -1) - { - vec.x = pendulumPointer->Position.x - rope->segment[0].x; - vec.y = pendulumPointer->Position.y - rope->segment[0].y; - vec.z = pendulumPointer->Position.z - rope->segment[0].z; - NormaliseRopeVector(&vec); - for (i = pendulumPointer->node; i >= 0; --i) - { - rope->segment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * vec.x >> 16); - rope->segment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * vec.y >> 16); - rope->segment[i].z = rope->meshSegment[i - 1].z + ((int64_t)rope->segmentLength * vec.z >> 16); rope->velocity[i].x = 0; rope->velocity[i].y = 0; rope->velocity[i].z = 0; - } - if (flag) - { - vec2.x = pendulumPointer->Position.x - rope->segment[pendulumPointer->node].x; - vec2.y = pendulumPointer->Position.y - rope->segment[pendulumPointer->node].y; - vec2.z = pendulumPointer->Position.z - rope->segment[pendulumPointer->node].z; - rope->segment[pendulumPointer->node].x = pendulumPointer->Position.x; - rope->segment[pendulumPointer->node].y = pendulumPointer->Position.y; - rope->segment[pendulumPointer->node].z = pendulumPointer->Position.z; - for (i = pendulumPointer->node; i < 24; ++i) + + if (item->triggerFlags == -1) { - rope->segment[i].x -= vec2.x; - rope->segment[i].y -= vec2.y; - rope->segment[i].z -= vec2.z; + rope->segment[i].x = l; + rope->segment[i].y >>= 4; + + rope->velocity[i].x = 16384; + rope->velocity[i].y = il; + rope->velocity[i].z = 16384; + } + + l += 1024; + sum += rope->segmentLength; + il -= 131072; + } + + rope->active = 0; + } + + PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec) + { + int x = vec->x >> FP_SHIFT; + int y = vec->y >> FP_SHIFT; + int z = vec->z >> FP_SHIFT; + + if (!x && !y && !z) + return vec; + + int length = SQUARE(x) + SQUARE(y) + SQUARE(z); + if (length < 0) + length = -length; + + length = 65536 / sqrt(length); + + vec->x = ((int64_t)length * vec->x) >> FP_SHIFT; + vec->y = ((int64_t)length * vec->y) >> FP_SHIFT; + vec->z = ((int64_t)length * vec->z) >> FP_SHIFT; + return vec; + } + + void GetRopePos(ROPE_STRUCT* rope, int segmentFrame, int* x, int* y, int* z) + { + int segment; + short frame; + + segment = segmentFrame / 128; + frame = segmentFrame & 0x7F; + + *x = (rope->normalisedSegment[segment].x * frame >> FP_SHIFT) + (rope->meshSegment[segment].x >> FP_SHIFT) + rope->position.x; + *y = (rope->normalisedSegment[segment].y * frame >> FP_SHIFT) + (rope->meshSegment[segment].y >> FP_SHIFT) + rope->position.y; + *z = (rope->normalisedSegment[segment].z * frame >> FP_SHIFT) + (rope->meshSegment[segment].z >> FP_SHIFT) + rope->position.z; + } + + int DotProduct(PHD_VECTOR* u, PHD_VECTOR* v) + { + return (u->x * v->x + u->y * v->y + u->z * v->z) >> W2V_SHIFT; + } + + void ScaleVector(PHD_VECTOR* u, int c, PHD_VECTOR* destination) + { + destination->x = c * u->x >> W2V_SHIFT; + destination->y = c * u->y >> W2V_SHIFT; + destination->z = c * u->z >> W2V_SHIFT; + } + + void CrossProduct(PHD_VECTOR* u, PHD_VECTOR* v, PHD_VECTOR* destination) + { + destination->x = (u->y * v->z - u->z * v->y) >> W2V_SHIFT; + destination->y = (u->z * v->x - u->x * v->z) >> W2V_SHIFT; + destination->z = (u->x * v->y - u->y * v->x) >> W2V_SHIFT; + } + + void phd_GetMatrixAngles(int* matrix, short* angle) + { + angle[0] = phd_atan(sqrt(SQUARE(matrix[M22]) + SQUARE(matrix[M02])), matrix[M12]); + if (matrix[M12] >= 0 && angle[0] > 0 || matrix[M12] < 0 && angle[0] < 0) + angle[0] = -angle[0]; + angle[1] = phd_atan(matrix[M22], matrix[M02]); + angle[2] = phd_atan(matrix[M00] * phd_cos(angle[1]) - matrix[M20] * phd_sin(angle[1]), matrix[M21] * phd_sin(angle[1]) - matrix[M01] * phd_cos(angle[1])); + } + + void RopeControl(short itemNumber) + { + ITEM_INFO* item; + ROPE_STRUCT* rope; + + item = &g_Level.Items[itemNumber]; + rope = &Ropes[item->triggerFlags]; + if (TriggerActive(item)) + { + rope->active = 1; + RopeDynamics(rope); + } + else + { + rope->active = 0; + } + } + + void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) + { + ITEM_INFO* item; + ROPE_STRUCT* rope; + BOUNDING_BOX* frame; + int segment; + + item = &g_Level.Items[itemNumber]; + rope = &Ropes[item->triggerFlags]; + if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && (l->currentAnimState == LS_REACH || l->currentAnimState == LS_JUMP_UP) && l->gravityStatus && l->fallspeed > 0 && rope->active) + { + frame = GetBoundsAccurate(l); + segment = _0x0046D200(rope, l->pos.xPos, l->pos.yPos + frame->Y1 + 512, l->pos.zPos + frame->Z2 * phd_cos(l->pos.yRot), l->currentAnimState == LS_REACH ? 128 : 320); + if (segment >= 0) + { + if (l->currentAnimState == LS_REACH) + { + l->animNumber = LA_REACH_TO_ROPE_SWING; + l->currentAnimState = LS_ROPE_SWING; + Lara.ropeFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 32 << 8; + Lara.ropeDFrame = g_Level.Anims[LA_ROPE_SWING].frameBase + 60 << 8; + } + else + { + l->animNumber = LA_JUMP_UP_TO_ROPE_START; + l->currentAnimState = LS_ROPE_IDLE; + } + l->frameNumber = g_Level.Anims[l->animNumber].frameBase; + l->gravityStatus = false; + l->fallspeed = 0; + Lara.gunStatus = LG_HANDS_BUSY; + Lara.ropePtr = item->triggerFlags; + Lara.ropeSegment = segment; + Lara.ropeY = l->pos.yRot; + DelAlignLaraToRope(l); + CurrentPendulum.Velocity.x = 0; + CurrentPendulum.Velocity.y = 0; + CurrentPendulum.Velocity.z = 0; + ApplyVelocityToRope(segment, l->pos.yRot, 16 * LaraItem->speed); + } + } + } + + void RopeDynamics(ROPE_STRUCT* rope) + { + int flag, i; + PENDULUM* pendulumPointer; + PHD_VECTOR vec, vec2; + + flag = 0; + if (rope->coiled) + { + --rope->coiled; + if (!rope->coiled) + { + for (i = 0; i < ROPE_SEGMENTS; ++i) + rope->velocity[i].y = 0; + } + } + if (Lara.ropePtr != -1 && rope == &Ropes[Lara.ropePtr]) + { + pendulumPointer = &CurrentPendulum; + if (CurrentPendulum.node != Lara.ropeSegment + 1) + { + _0x0046E1C0(rope, Lara.ropeSegment + 1); + flag = 1; + } + } + else + { + pendulumPointer = &AlternatePendulum; + if (Lara.ropePtr == -1 && CurrentPendulum.Rope) + { + for (i = 0; i < CurrentPendulum.node; ++i) + { + CurrentPendulum.Rope->velocity[i].x = CurrentPendulum.Rope->velocity[CurrentPendulum.node].x; + CurrentPendulum.Rope->velocity[i].y = CurrentPendulum.Rope->velocity[CurrentPendulum.node].y; + CurrentPendulum.Rope->velocity[i].z = CurrentPendulum.Rope->velocity[CurrentPendulum.node].z; + } + CurrentPendulum.Position.x = 0; + CurrentPendulum.Position.y = 0; + CurrentPendulum.Position.z = 0; + + CurrentPendulum.Velocity.x = 0; + CurrentPendulum.Velocity.y = 0; + CurrentPendulum.Velocity.z = 0; + + CurrentPendulum.node = -1; + CurrentPendulum.Rope = NULL; + } + } + if (Lara.ropePtr != -1) + { + vec.x = pendulumPointer->Position.x - rope->segment[0].x; + vec.y = pendulumPointer->Position.y - rope->segment[0].y; + vec.z = pendulumPointer->Position.z - rope->segment[0].z; + NormaliseRopeVector(&vec); + + for (i = pendulumPointer->node; i >= 0; --i) + { + rope->segment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * vec.x >> FP_SHIFT); + rope->segment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * vec.y >> FP_SHIFT); + rope->segment[i].z = rope->meshSegment[i - 1].z + ((int64_t)rope->segmentLength * vec.z >> FP_SHIFT); + rope->velocity[i].x = 0; rope->velocity[i].y = 0; rope->velocity[i].z = 0; } - } - _0x0046E080(rope, pendulumPointer, &rope->velocity[0], &pendulumPointer->Velocity, rope->segmentLength * pendulumPointer->node); - pendulumPointer->Velocity.y += 393216; - pendulumPointer->Position.x += pendulumPointer->Velocity.x; - pendulumPointer->Position.y += pendulumPointer->Velocity.y; - pendulumPointer->Position.z += pendulumPointer->Velocity.z; - pendulumPointer->Velocity.x -= pendulumPointer->Velocity.x >> 8; - pendulumPointer->Velocity.z -= pendulumPointer->Velocity.z >> 8; - } - for (i = pendulumPointer->node; i < 23; ++i) - _0x0046DF00(&rope->segment[i], &rope->segment[i + 1], &rope->velocity[i], &rope->velocity[i + 1], rope->segmentLength); - for (i = 0; i < 24; ++i) - { - rope->segment[i].x += rope->velocity[i].x; - rope->segment[i].y += rope->velocity[i].y; - rope->segment[i].z += rope->velocity[i].z; - } - for (i = pendulumPointer->node; i < 24; ++i) - { - rope->velocity[i].y += 196608; - if (pendulumPointer->Rope) - { - rope->velocity[i].x -= rope->velocity[i].x >> 4; - rope->velocity[i].z -= rope->velocity[i].z >> 4; - } - else - { - rope->velocity[i].x -= rope->velocity[i].x >> 4; - rope->velocity[i].z -= rope->velocity[i].z >> 4; - } - } - rope->segment[0].x = 0; - rope->segment[0].y = 0; - rope->segment[0].z = 0; - rope->velocity[0].x = 0; - rope->velocity[0].y = 0; - rope->velocity[0].z = 0; - for (i = 0; i < 23; ++i) - { - rope->normalisedSegment[i].x = rope->segment[i + 1].x - rope->segment[i].x; - rope->normalisedSegment[i].y = rope->segment[i + 1].y - rope->segment[i].y; - rope->normalisedSegment[i].z = rope->segment[i + 1].z - rope->segment[i].z; - NormaliseRopeVector(&rope->normalisedSegment[i]); - } - if (rope != &Ropes[Lara.ropePtr]) - { - rope->meshSegment[0].x = rope->segment[0].x; - rope->meshSegment[0].y = rope->segment[0].y; - rope->meshSegment[0].z = rope->segment[0].z; - rope->meshSegment[1].x = rope->segment[0].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].x >> 16); - rope->meshSegment[1].y = rope->segment[0].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].y >> 16); - rope->meshSegment[1].z = rope->segment[0].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].z >> 16); - for (i = 2; i < 24; ++i) - { - rope->meshSegment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].x >> 16); - rope->meshSegment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].y >> 16); - rope->meshSegment[i].z = rope->meshSegment[i - 1].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].z >> 16); - } - } - else - { - rope->meshSegment[pendulumPointer->node].x = rope->segment[pendulumPointer->node].x; - rope->meshSegment[pendulumPointer->node].y = rope->segment[pendulumPointer->node].y; - rope->meshSegment[pendulumPointer->node].z = rope->segment[pendulumPointer->node].z; - rope->meshSegment[pendulumPointer->node + 1].x = rope->segment[pendulumPointer->node].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].x >> 16); - rope->meshSegment[pendulumPointer->node + 1].y = rope->segment[pendulumPointer->node].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].y >> 16); - rope->meshSegment[pendulumPointer->node + 1].z = rope->segment[pendulumPointer->node].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].z >> 16); - for (i = pendulumPointer->node + 1; i < 23; ++i) - { - rope->meshSegment[i + 1].x = rope->meshSegment[i].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].x >> 16); - rope->meshSegment[i + 1].y = rope->meshSegment[i].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].y >> 16); - rope->meshSegment[i + 1].z = rope->meshSegment[i].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].z >> 16); - } - for (i = 0; i < pendulumPointer->node; ++i) - { - rope->meshSegment[i].x = rope->segment[i].x; - rope->meshSegment[i].y = rope->segment[i].y; - rope->meshSegment[i].z = rope->segment[i].z; - } - } -} -int _0x0046D200(ROPE_STRUCT* rope, int x, int y, int z, int radius) -{ - int dx, dy, dz; - - for (int i = 0; i < 22; ++i) - { - if (y > rope->position.y + (rope->meshSegment[i].y / 65536) && y < rope->position.y + (rope->meshSegment[i + 1].y / 65536)) - { - dx = x - ((rope->meshSegment[i + 1].x + rope->meshSegment[i].x) / 131072) - rope->position.x; - dy = y - ((rope->meshSegment[i + 1].y + rope->meshSegment[i].y) / 131072) - rope->position.y; - dz = z - ((rope->meshSegment[i + 1].z + rope->meshSegment[i].z) / 131072) - rope->position.z; - if (SQUARE(dx) + SQUARE(dy) + SQUARE(dz) < SQUARE(radius + 64)) - return i; - } - } - return -1; -} - -void ApplyVelocityToRope(int node, short angle, short n) -{ - SetPendulumVelocity( - (unsigned short) n * phd_sin(angle) * 4096, - 0, - (unsigned short) n * phd_cos(angle) * 4096); /* @ORIGINAL_BUG: casting n to unsigned short results in the rope glitch */ -} - -void SetPendulumVelocity(int x, int y, int z) -{ - int node; - - node = 2 * (CurrentPendulum.node >> 1); - if (node < 24) - { - int val = 4096 / (24 - node) * 256; - - x = (int64_t)val * x >> 16; - y = (int64_t)val * y >> 16; - z = (int64_t)val * z >> 16; - } - - CurrentPendulum.Velocity.x += x; - CurrentPendulum.Velocity.y += y; - CurrentPendulum.Velocity.z += z; -} - -void _0x0046E1C0(ROPE_STRUCT* rope, int node) -{ - CurrentPendulum.Position.x = rope->segment[node].x; - CurrentPendulum.Position.y = rope->segment[node].y; - CurrentPendulum.Position.z = rope->segment[node].z; - if (CurrentPendulum.node == -1) - { - CurrentPendulum.Velocity.x += rope->velocity[node].x; - CurrentPendulum.Velocity.y += rope->velocity[node].y; - CurrentPendulum.Velocity.z += rope->velocity[node].z; - } - CurrentPendulum.node = node; - CurrentPendulum.Rope = rope; -} - -void _0x0046E080(ROPE_STRUCT* rope, PENDULUM* pendulumPointer, PHD_VECTOR* ropeVelocity, PHD_VECTOR* pendulumVelocity, int value) -{ - PHD_VECTOR vec; - int result; - - vec.x = pendulumPointer->Position.x + pendulumVelocity->x - rope->segment[0].x; - vec.y = pendulumPointer->Position.y + pendulumVelocity->y - rope->segment[0].y; - vec.z = pendulumPointer->Position.z + pendulumVelocity->z - rope->segment[0].z; - result = 65536 * sqrt(abs(SQUARE(vec.x >> 16) + SQUARE(vec.y >> 16) + SQUARE(vec.z >> 16))) - value; - NormaliseRopeVector(&vec); - pendulumVelocity->x -= (int64_t)result * vec.x >> 16; - pendulumVelocity->y -= (int64_t)result * vec.y >> 16; - pendulumVelocity->z -= (int64_t)result * vec.z >> 16; -} - -void _0x0046DF00(PHD_VECTOR* segment, PHD_VECTOR* nextSegment, PHD_VECTOR* velocity, PHD_VECTOR* nextVelocity, int length) -{ - PHD_VECTOR vec; - int result; - - vec.x = nextSegment->x + nextVelocity->x - segment->x - velocity->x; - vec.y = nextSegment->y + nextVelocity->y - segment->y - velocity->y; - vec.z = nextSegment->z + nextVelocity->z - segment->z - velocity->z; - result = (65536 * sqrt(abs(SQUARE(vec.x >> 16) + SQUARE(vec.y >> 16) + SQUARE(vec.z >> 16))) - length) / 2; - NormaliseRopeVector(&vec); - vec.x = (int64_t)result * vec.x >> 16; - vec.y = (int64_t)result * vec.y >> 16; - vec.z = (int64_t)result * vec.z >> 16; - velocity->x += vec.x; - velocity->y += vec.y; - velocity->z += vec.z; - nextVelocity->x -= vec.x; - nextVelocity->y -= vec.y; - nextVelocity->z -= vec.z; -} - -void UpdateRopeSwing(ITEM_INFO* item) -{ - if (Lara.ropeMaxXForward > 9000) - { - Lara.ropeMaxXForward = 9000; - } - - if (Lara.ropeMaxXBackward > 9000) - { - Lara.ropeMaxXBackward = 9000; - } - - if (Lara.ropeDirection) - { - if (item->pos.xRot > 0 && item->pos.xRot - Lara.ropeLastX < -100) - { - Lara.ropeArcFront = Lara.ropeLastX; - Lara.ropeDirection = 0; - Lara.ropeMaxXBackward = 0; - int frame = 15 * Lara.ropeMaxXForward / 18000 + g_Level.Anims[LA_ROPE_SWING].frameBase + 47 << 8; - if (frame > Lara.ropeDFrame) + if (flag) { - Lara.ropeDFrame = frame; - RopeSwing = 1; + vec2.x = pendulumPointer->Position.x - rope->segment[pendulumPointer->node].x; + vec2.y = pendulumPointer->Position.y - rope->segment[pendulumPointer->node].y; + vec2.z = pendulumPointer->Position.z - rope->segment[pendulumPointer->node].z; + + rope->segment[pendulumPointer->node].x = pendulumPointer->Position.x; + rope->segment[pendulumPointer->node].y = pendulumPointer->Position.y; + rope->segment[pendulumPointer->node].z = pendulumPointer->Position.z; + + for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i) + { + rope->segment[i].x -= vec2.x; + rope->segment[i].y -= vec2.y; + rope->segment[i].z -= vec2.z; + rope->velocity[i].x = 0; + rope->velocity[i].y = 0; + rope->velocity[i].z = 0; + } + } + _0x0046E080(rope, pendulumPointer, &rope->velocity[0], &pendulumPointer->Velocity, rope->segmentLength * pendulumPointer->node); + pendulumPointer->Velocity.y += 393216; + pendulumPointer->Position.x += pendulumPointer->Velocity.x; + pendulumPointer->Position.y += pendulumPointer->Velocity.y; + pendulumPointer->Position.z += pendulumPointer->Velocity.z; + pendulumPointer->Velocity.x -= pendulumPointer->Velocity.x >> 8; + pendulumPointer->Velocity.z -= pendulumPointer->Velocity.z >> 8; + } + for (i = pendulumPointer->node; i < 23; ++i) + _0x0046DF00(&rope->segment[i], &rope->segment[i + 1], &rope->velocity[i], &rope->velocity[i + 1], rope->segmentLength); + + for (i = 0; i < ROPE_SEGMENTS; ++i) + { + rope->segment[i].x += rope->velocity[i].x; + rope->segment[i].y += rope->velocity[i].y; + rope->segment[i].z += rope->velocity[i].z; + } + + for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i) + { + rope->velocity[i].y += 196608; + if (pendulumPointer->Rope) + { + rope->velocity[i].x -= rope->velocity[i].x >> 4; + rope->velocity[i].z -= rope->velocity[i].z >> 4; } else { - RopeSwing = 0; + rope->velocity[i].x -= rope->velocity[i].x >> 4; + rope->velocity[i].z -= rope->velocity[i].z >> 4; } + } + rope->segment[0].x = 0; + rope->segment[0].y = 0; + rope->segment[0].z = 0; - SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->pos, 0); - } - else if (Lara.ropeLastX < 0 && Lara.ropeFrame == Lara.ropeDFrame) - { - RopeSwing = 0; - Lara.ropeDFrame = 15 * Lara.ropeMaxXBackward / 18000 + g_Level.Anims[LA_ROPE_SWING].frameBase + 47 << 8; - Lara.ropeFrameRate = 15 * Lara.ropeMaxXBackward / 9000 + 1; - } - else if (Lara.ropeFrameRate < 512) - { - int num = RopeSwing ? 31 : 7; + rope->velocity[0].x = 0; + rope->velocity[0].y = 0; + rope->velocity[0].z = 0; - Lara.ropeFrameRate += num * Lara.ropeMaxXBackward / 9000 + 1; - } - } - else - { - if (item->pos.xRot < 0 && item->pos.xRot - Lara.ropeLastX > 100) + for (i = 0; i < ROPE_SEGMENTS - 1; ++i) { - Lara.ropeArcBack = Lara.ropeLastX; - Lara.ropeDirection = 1; - Lara.ropeMaxXForward = 0; - int frame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.ropeMaxXBackward / 18000 + 17 << 8; - if (frame < Lara.ropeDFrame) + rope->normalisedSegment[i].x = rope->segment[i + 1].x - rope->segment[i].x; + rope->normalisedSegment[i].y = rope->segment[i + 1].y - rope->segment[i].y; + rope->normalisedSegment[i].z = rope->segment[i + 1].z - rope->segment[i].z; + NormaliseRopeVector(&rope->normalisedSegment[i]); + } + + if (Lara.ropePtr != -1 && rope != &Ropes[Lara.ropePtr]) + { + rope->meshSegment[0].x = rope->segment[0].x; + rope->meshSegment[0].y = rope->segment[0].y; + rope->meshSegment[0].z = rope->segment[0].z; + + rope->meshSegment[1].x = rope->segment[0].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].x >> FP_SHIFT); + rope->meshSegment[1].y = rope->segment[0].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].y >> FP_SHIFT); + rope->meshSegment[1].z = rope->segment[0].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[0].z >> FP_SHIFT); + + for (i = 2; i < ROPE_SEGMENTS; i++) { - Lara.ropeDFrame = frame; - RopeSwing = 1; + rope->meshSegment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].x >> FP_SHIFT); + rope->meshSegment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].y >> FP_SHIFT); + rope->meshSegment[i].z = rope->meshSegment[i - 1].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[i - 1].z >> FP_SHIFT); } - else - { - RopeSwing = 0; - } - - SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->pos, 0); - } - else if (Lara.ropeLastX > 0 && Lara.ropeFrame == Lara.ropeDFrame) - { - RopeSwing = 0; - - Lara.ropeDFrame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.ropeMaxXForward / 18000 + 17 << 8; - Lara.ropeFrameRate = 15 * Lara.ropeMaxXForward / 9000 + 1; - } - else if (Lara.ropeFrameRate < 512) - { - int num = RopeSwing ? 31 : 7; - - Lara.ropeFrameRate += num * Lara.ropeMaxXForward / 9000 + 1; - } - } - - Lara.ropeLastX = item->pos.xRot; - if (Lara.ropeDirection) - { - if (item->pos.xRot > Lara.ropeMaxXForward) - Lara.ropeMaxXForward = item->pos.xRot; - } - else - { - if (item->pos.xRot < -Lara.ropeMaxXBackward) - Lara.ropeMaxXBackward = abs(item->pos.xRot); - } -} - -void JumpOffRope(ITEM_INFO* item) -{ - if (Lara.ropePtr != -1) - { - if (item->pos.xRot >= 0) - { - item->fallspeed = -112; - item->speed = item->pos.xRot / 128; } else { - item->speed = 0; - item->fallspeed = -20; + rope->meshSegment[pendulumPointer->node].x = rope->segment[pendulumPointer->node].x; + rope->meshSegment[pendulumPointer->node].y = rope->segment[pendulumPointer->node].y; + rope->meshSegment[pendulumPointer->node].z = rope->segment[pendulumPointer->node].z; + + rope->meshSegment[pendulumPointer->node + 1].x = rope->segment[pendulumPointer->node].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].x >> FP_SHIFT); + rope->meshSegment[pendulumPointer->node + 1].y = rope->segment[pendulumPointer->node].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].y >> FP_SHIFT); + rope->meshSegment[pendulumPointer->node + 1].z = rope->segment[pendulumPointer->node].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[pendulumPointer->node].z >> FP_SHIFT); + + for (i = pendulumPointer->node + 1; i < ROPE_SEGMENTS - 1; ++i) + { + rope->meshSegment[i + 1].x = rope->meshSegment[i].x + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].x >> FP_SHIFT); + rope->meshSegment[i + 1].y = rope->meshSegment[i].y + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].y >> FP_SHIFT); + rope->meshSegment[i + 1].z = rope->meshSegment[i].z + ((int64_t)rope->segmentLength * rope->normalisedSegment[i].z >> FP_SHIFT); + } + + for (i = 0; i < pendulumPointer->node; i++) + { + rope->meshSegment[i].x = rope->segment[i].x; + rope->meshSegment[i].y = rope->segment[i].y; + rope->meshSegment[i].z = rope->segment[i].z; + } + } + } + + int _0x0046D200(ROPE_STRUCT* rope, int x, int y, int z, int radius) + { + int dx, dy, dz; + + for (int i = 0; i < ROPE_SEGMENTS - 2; ++i) + { + if (y > rope->position.y + (rope->meshSegment[i].y >> FP_SHIFT) + && y < rope->position.y + (rope->meshSegment[i + 1].y >> FP_SHIFT)) + { + dx = x - ((rope->meshSegment[i + 1].x + rope->meshSegment[i].x) >> (FP_SHIFT + 1)) - rope->position.x; + dy = y - ((rope->meshSegment[i + 1].y + rope->meshSegment[i].y) >> (FP_SHIFT + 1)) - rope->position.y; + dz = z - ((rope->meshSegment[i + 1].z + rope->meshSegment[i].z) >> (FP_SHIFT + 1)) - rope->position.z; + if (SQUARE(dx) + SQUARE(dy) + SQUARE(dz) < SQUARE(radius + 64)) + return i; + } + } + return -1; + } + + void ApplyVelocityToRope(int node, short angle, short n) + { + SetPendulumVelocity( + (unsigned short)n * phd_sin(angle) * 4096, + 0, + (unsigned short)n * phd_cos(angle) * 4096); /* @ORIGINAL_BUG: casting n to unsigned short results in the rope glitch */ + } + + void SetPendulumVelocity(int x, int y, int z) + { + int node; + + node = 2 * (CurrentPendulum.node >> 1); + if (node < ROPE_SEGMENTS) + { + int val = 4096 / (ROPE_SEGMENTS - node) * 256; + + x = (int64_t)val * x >> FP_SHIFT; + y = (int64_t)val * y >> FP_SHIFT; + z = (int64_t)val * z >> FP_SHIFT; } + CurrentPendulum.Velocity.x += x; + CurrentPendulum.Velocity.y += y; + CurrentPendulum.Velocity.z += z; + } + + void _0x0046E1C0(ROPE_STRUCT* rope, int node) + { + CurrentPendulum.Position.x = rope->segment[node].x; + CurrentPendulum.Position.y = rope->segment[node].y; + CurrentPendulum.Position.z = rope->segment[node].z; + + if (CurrentPendulum.node == -1) + { + CurrentPendulum.Velocity.x += rope->velocity[node].x; + CurrentPendulum.Velocity.y += rope->velocity[node].y; + CurrentPendulum.Velocity.z += rope->velocity[node].z; + } + + CurrentPendulum.node = node; + CurrentPendulum.Rope = rope; + } + + void _0x0046E080(ROPE_STRUCT* rope, PENDULUM* pendulumPointer, PHD_VECTOR* ropeVelocity, PHD_VECTOR* pendulumVelocity, int value) + { + PHD_VECTOR vec; + int result; + + vec.x = pendulumPointer->Position.x + pendulumVelocity->x - rope->segment[0].x; + vec.y = pendulumPointer->Position.y + pendulumVelocity->y - rope->segment[0].y; + vec.z = pendulumPointer->Position.z + pendulumVelocity->z - rope->segment[0].z; + + result = 65536 * sqrt(abs(SQUARE(vec.x >> FP_SHIFT) + SQUARE(vec.y >> FP_SHIFT) + SQUARE(vec.z >> FP_SHIFT))) - value; + NormaliseRopeVector(&vec); + + pendulumVelocity->x -= (int64_t)result * vec.x >> FP_SHIFT; + pendulumVelocity->y -= (int64_t)result * vec.y >> FP_SHIFT; + pendulumVelocity->z -= (int64_t)result * vec.z >> FP_SHIFT; + } + + void _0x0046DF00(PHD_VECTOR* segment, PHD_VECTOR* nextSegment, PHD_VECTOR* velocity, PHD_VECTOR* nextVelocity, int length) + { + PHD_VECTOR vec; + int result; + + vec.x = nextSegment->x + nextVelocity->x - segment->x - velocity->x; + vec.y = nextSegment->y + nextVelocity->y - segment->y - velocity->y; + vec.z = nextSegment->z + nextVelocity->z - segment->z - velocity->z; + + result = (65536 * sqrt(abs(SQUARE(vec.x >> FP_SHIFT) + SQUARE(vec.y >> FP_SHIFT) + SQUARE(vec.z >> FP_SHIFT))) - length) / 2; + NormaliseRopeVector(&vec); + + vec.x = (int64_t)result * vec.x >> FP_SHIFT; + vec.y = (int64_t)result * vec.y >> FP_SHIFT; + vec.z = (int64_t)result * vec.z >> FP_SHIFT; + + velocity->x += vec.x; + velocity->y += vec.y; + velocity->z += vec.z; + + nextVelocity->x -= vec.x; + nextVelocity->y -= vec.y; + nextVelocity->z -= vec.z; + } + + void UpdateRopeSwing(ITEM_INFO* item) + { + if (Lara.ropeMaxXForward > 9000) + { + Lara.ropeMaxXForward = 9000; + } + + if (Lara.ropeMaxXBackward > 9000) + { + Lara.ropeMaxXBackward = 9000; + } + + if (Lara.ropeDirection) + { + if (item->pos.xRot > 0 && item->pos.xRot - Lara.ropeLastX < -100) + { + Lara.ropeArcFront = Lara.ropeLastX; + Lara.ropeDirection = 0; + Lara.ropeMaxXBackward = 0; + int frame = 15 * Lara.ropeMaxXForward / 18000 + g_Level.Anims[LA_ROPE_SWING].frameBase + 47 << 8; + if (frame > Lara.ropeDFrame) + { + Lara.ropeDFrame = frame; + RopeSwing = 1; + } + else + { + RopeSwing = 0; + } + + SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->pos, 0); + } + else if (Lara.ropeLastX < 0 && Lara.ropeFrame == Lara.ropeDFrame) + { + RopeSwing = 0; + Lara.ropeDFrame = 15 * Lara.ropeMaxXBackward / 18000 + g_Level.Anims[LA_ROPE_SWING].frameBase + 47 << 8; + Lara.ropeFrameRate = 15 * Lara.ropeMaxXBackward / 9000 + 1; + } + else if (Lara.ropeFrameRate < 512) + { + int num = RopeSwing ? 31 : 7; + + Lara.ropeFrameRate += num * Lara.ropeMaxXBackward / 9000 + 1; + } + } + else + { + if (item->pos.xRot < 0 && item->pos.xRot - Lara.ropeLastX > 100) + { + Lara.ropeArcBack = Lara.ropeLastX; + Lara.ropeDirection = 1; + Lara.ropeMaxXForward = 0; + int frame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.ropeMaxXBackward / 18000 + 17 << 8; + if (frame < Lara.ropeDFrame) + { + Lara.ropeDFrame = frame; + RopeSwing = 1; + } + else + { + RopeSwing = 0; + } + + SoundEffect(SFX_TR4_LARA_ROPE_CREAK, &item->pos, 0); + } + else if (Lara.ropeLastX > 0 && Lara.ropeFrame == Lara.ropeDFrame) + { + RopeSwing = 0; + + Lara.ropeDFrame = g_Level.Anims[LA_ROPE_SWING].frameBase - 15 * Lara.ropeMaxXForward / 18000 + 17 << 8; + Lara.ropeFrameRate = 15 * Lara.ropeMaxXForward / 9000 + 1; + } + else if (Lara.ropeFrameRate < 512) + { + int num = RopeSwing ? 31 : 7; + + Lara.ropeFrameRate += num * Lara.ropeMaxXForward / 9000 + 1; + } + } + + Lara.ropeLastX = item->pos.xRot; + if (Lara.ropeDirection) + { + if (item->pos.xRot > Lara.ropeMaxXForward) + Lara.ropeMaxXForward = item->pos.xRot; + } + else + { + if (item->pos.xRot < -Lara.ropeMaxXBackward) + Lara.ropeMaxXBackward = abs(item->pos.xRot); + } + } + + void JumpOffRope(ITEM_INFO* item) + { + if (Lara.ropePtr != -1) + { + if (item->pos.xRot >= 0) + { + item->fallspeed = -112; + item->speed = item->pos.xRot / 128; + } + else + { + item->speed = 0; + item->fallspeed = -20; + } + + item->pos.xRot = 0; + item->gravityStatus = true; + + Lara.gunStatus = LG_NO_ARMS; + + if (item->frameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 42) + { + item->animNumber = LA_ROPE_SWING_TO_REACH_1; + } + else if (item->frameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 21) + { + item->animNumber = LA_ROPE_SWING_TO_REACH_2; + } + else + { + item->animNumber = LA_ROPE_SWING_TO_REACH_3; + } + + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->currentAnimState = LS_REACH; + item->goalAnimState = LS_REACH; + + Lara.ropePtr = -1; + } + } + + void FallFromRope(ITEM_INFO* item) + { + item->speed = abs(CurrentPendulum.Velocity.x >> FP_SHIFT) + abs(CurrentPendulum.Velocity.z >> FP_SHIFT) >> 1; item->pos.xRot = 0; + item->pos.yPos += 320; + + item->animNumber = LA_FALL_START; + item->frameNumber = g_Level.Anims[LA_FALL_START].frameBase; + item->currentAnimState = LS_JUMP_FORWARD; + item->goalAnimState = LS_JUMP_FORWARD; + + item->fallspeed = 0; item->gravityStatus = true; Lara.gunStatus = LG_NO_ARMS; - - if (item->frameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 42) - { - item->animNumber = LA_ROPE_SWING_TO_REACH_1; - } - else if (item->frameNumber - g_Level.Anims[LA_ROPE_SWING].frameBase > 21) - { - item->animNumber = LA_ROPE_SWING_TO_REACH_2; - } - else - { - item->animNumber = LA_ROPE_SWING_TO_REACH_3; - } - - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_REACH; - item->goalAnimState = LS_REACH; - Lara.ropePtr = -1; } -} -void FallFromRope(ITEM_INFO* item) -{ - item->speed = abs(CurrentPendulum.Velocity.x >> 16) + abs(CurrentPendulum.Velocity.z >> 16) >> 1; - item->pos.xRot = 0; - item->pos.yPos += 320; - - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[LA_FALL_START].frameBase; - item->currentAnimState = LS_JUMP_FORWARD; - item->goalAnimState = LS_JUMP_FORWARD; - - item->fallspeed = 0; - item->gravityStatus = true; - - Lara.gunStatus = LG_NO_ARMS; - Lara.ropePtr = -1; -} - -void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll) -{ - if (!(TrInput & IN_ACTION)) + void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll) { - FallFromRope(item); - } - else - { - Camera.targetAngle = ANGLE(30.0f); - if (Lara.ropeCount) + if (!(TrInput & IN_ACTION)) { - if (!Lara.ropeFlag) - { - --Lara.ropeCount; - Lara.ropeOffset += Lara.ropeDownVel; - if (!Lara.ropeCount) - Lara.ropeFlag = 1; - return; - } + FallFromRope(item); } else { - if (!Lara.ropeFlag) + Camera.targetAngle = ANGLE(30.0f); + if (Lara.ropeCount) { - ROPE_STRUCT* rope = &Ropes[Lara.ropePtr]; - Lara.ropeOffset = 0; - Lara.ropeDownVel = (unsigned int)(rope->meshSegment[Lara.ropeSegment + 1].y - rope->meshSegment[Lara.ropeSegment].y) >> 17; - Lara.ropeCount = 0; - Lara.ropeOffset += Lara.ropeDownVel; - Lara.ropeFlag = 1; - return; + if (!Lara.ropeFlag) + { + --Lara.ropeCount; + Lara.ropeOffset += Lara.ropeDownVel; + if (!Lara.ropeCount) + Lara.ropeFlag = 1; + return; + } + } + else + { + if (!Lara.ropeFlag) + { + ROPE_STRUCT* rope = &Ropes[Lara.ropePtr]; + Lara.ropeOffset = 0; + Lara.ropeDownVel = (unsigned int)(rope->meshSegment[Lara.ropeSegment + 1].y - rope->meshSegment[Lara.ropeSegment].y) >> 17; + Lara.ropeCount = 0; + Lara.ropeOffset += Lara.ropeDownVel; + Lara.ropeFlag = 1; + return; + } } - } - if (item->animNumber == LA_ROPE_DOWN && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd) - { - SoundEffect(SFX_TR4_LARA_POLE_LOOP, &LaraItem->pos, 0); - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - Lara.ropeFlag = 0; - ++Lara.ropeSegment; - Lara.ropeOffset = 0; - } + if (item->animNumber == LA_ROPE_DOWN && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd) + { + SoundEffect(SFX_TR4_LARA_POLE_LOOP, &LaraItem->pos, 0); + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + Lara.ropeFlag = 0; + ++Lara.ropeSegment; + Lara.ropeOffset = 0; + } - if (!(TrInput & IN_BACK) || Lara.ropeSegment >= 21) - item->goalAnimState = LS_ROPE_IDLE; + if (!(TrInput & IN_BACK) || Lara.ropeSegment >= 21) + item->goalAnimState = LS_ROPE_IDLE; + } } -} -void DelAlignLaraToRope(ITEM_INFO* item) -{ - ROPE_STRUCT* rope; - short ropeY; - PHD_VECTOR vec, vec2, vec3, vec4, vec5, pos, pos2, diff, diff2; - int matrix[12]; - short angle[3]; - ANIM_FRAME* frame; + void DelAlignLaraToRope(ITEM_INFO* item) + { + ROPE_STRUCT* rope; + short ropeY; + PHD_VECTOR vec, vec2, vec3, vec4, vec5, pos, pos2, diff, diff2; + int matrix[12]; + short angle[3]; + ANIM_FRAME* frame; - vec.x = 4096; - vec.y = 0; - vec.z = 0; - frame = (ANIM_FRAME*)GetBestFrame(item); - ropeY = Lara.ropeY - ANGLE(90); - rope = &Ropes[Lara.ropePtr]; - _0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY, &pos.x, &pos.y, &pos.z); - _0x0046D130(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY - 192, &pos2.x, &pos2.y, &pos2.z); - diff.x = pos.x - pos2.x << 16; - diff.y = pos.y - pos2.y << 16; - diff.z = pos.z - pos2.z << 16; - NormaliseRopeVector(&diff); - diff.x >>= 2; - diff.y >>= 2; - diff.z >>= 2; - ScaleVector(&diff, DotProduct(&vec, &diff), &vec2); - vec2.x = vec.x - vec2.x; - vec2.y = vec.y - vec2.y; - vec2.z = vec.z - vec2.z; - vec3.x = vec2.x; - vec3.y = vec2.y; - vec3.z = vec2.z; - vec4.x = vec2.x; - vec4.y = vec2.y; - vec4.z = vec2.z; - diff2.x = diff.x; - diff2.y = diff.y; - diff2.z = diff.z; - ScaleVector(&vec3, 16384 * phd_cos(ropeY), &vec3); - ScaleVector(&diff2, DotProduct(&diff2, &vec2), &diff2); - ScaleVector(&diff2, 4096 - 16384 * phd_cos(ropeY), &diff2); - CrossProduct(&diff, &vec2, &vec4); - ScaleVector(&vec4, 16384 * phd_sin(ropeY), &vec4); - diff2.x += vec3.x; - diff2.y += vec3.y; - diff2.z += vec3.z; - vec2.x = diff2.x + vec4.x << 16; - vec2.y = diff2.y + vec4.y << 16; - vec2.z = diff2.z + vec4.z << 16; - NormaliseRopeVector(&vec2); - vec2.x >>= 2; - vec2.y >>= 2; - vec2.z >>= 2; - CrossProduct(&diff, &vec2, &vec5); - vec5.x <<= 16; - vec5.y <<= 16; - vec5.z <<= 16; - NormaliseRopeVector(&vec5); - vec5.x >>= 2; - vec5.y >>= 2; - vec5.z >>= 2; - matrix[M00] = vec5.x; - matrix[M01] = diff.x; - matrix[M02] = vec2.x; - matrix[M10] = vec5.y; - matrix[M11] = diff.y; - matrix[M12] = vec2.y; - matrix[M20] = vec5.z; - matrix[M21] = diff.z; - matrix[M22] = vec2.z; - _0x0046D420(matrix, angle); - item->pos.xPos = rope->position.x + (rope->meshSegment[Lara.ropeSegment].x >> 16); - item->pos.yPos = rope->position.y + (rope->meshSegment[Lara.ropeSegment].y >> 16) + Lara.ropeOffset; - item->pos.zPos = rope->position.z + (rope->meshSegment[Lara.ropeSegment].z >> 16); + vec.x = 4096; + vec.y = 0; + vec.z = 0; - Matrix rotMatrix = Matrix::CreateFromYawPitchRoll( - TO_DEGREES(angle[1]), - TO_DEGREES(angle[0]), - TO_DEGREES(angle[2]) - ); + frame = (ANIM_FRAME*)GetBestFrame(item); + ropeY = Lara.ropeY - ANGLE(90); + rope = &Ropes[Lara.ropePtr]; - // PHD_MATH! - item->pos.xPos += -112 * rotMatrix.m[0][2]; // MatrixPtr[M02] >> W2V_SHIFT; - item->pos.yPos += -112 * rotMatrix.m[1][2]; // MatrixPtr[M12] >> W2V_SHIFT; - item->pos.zPos += -112 * rotMatrix.m[2][2]; // MatrixPtr[M22] >> W2V_SHIFT; + GetRopePos(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY, &pos.x, &pos.y, &pos.z); + GetRopePos(rope, (Lara.ropeSegment - 1 << 7) + frame->offsetY - 192, &pos2.x, &pos2.y, &pos2.z); - item->pos.xRot = angle[0]; - item->pos.yRot = angle[1]; - item->pos.zRot = angle[2]; -} + diff.x = pos.x - pos2.x << 16; + diff.y = pos.y - pos2.y << 16; + diff.z = pos.z - pos2.z << 16; + NormaliseRopeVector(&diff); + diff.x >>= 2; + diff.y >>= 2; + diff.z >>= 2; + ScaleVector(&diff, DotProduct(&vec, &diff), &vec2); + vec2.x = vec.x - vec2.x; + vec2.y = vec.y - vec2.y; + vec2.z = vec.z - vec2.z; + + vec3.x = vec2.x; + vec3.y = vec2.y; + vec3.z = vec2.z; + vec4.x = vec2.x; + vec4.y = vec2.y; + vec4.z = vec2.z; + + diff2.x = diff.x; + diff2.y = diff.y; + diff2.z = diff.z; + + ScaleVector(&vec3, 16384 * phd_cos(ropeY), &vec3); + ScaleVector(&diff2, DotProduct(&diff2, &vec2), &diff2); + ScaleVector(&diff2, 4096 - 16384 * phd_cos(ropeY), &diff2); + + CrossProduct(&diff, &vec2, &vec4); + ScaleVector(&vec4, 16384 * phd_sin(ropeY), &vec4); + diff2.x += vec3.x; + diff2.y += vec3.y; + diff2.z += vec3.z; + + vec2.x = diff2.x + vec4.x << 16; + vec2.y = diff2.y + vec4.y << 16; + vec2.z = diff2.z + vec4.z << 16; + NormaliseRopeVector(&vec2); + vec2.x >>= 2; + vec2.y >>= 2; + vec2.z >>= 2; + + CrossProduct(&diff, &vec2, &vec5); + + vec5.x <<= 16; + vec5.y <<= 16; + vec5.z <<= 16; + NormaliseRopeVector(&vec5); + vec5.x >>= 2; + vec5.y >>= 2; + vec5.z >>= 2; + + matrix[M00] = vec5.x; + matrix[M01] = diff.x; + matrix[M02] = vec2.x; + matrix[M10] = vec5.y; + matrix[M11] = diff.y; + matrix[M12] = vec2.y; + matrix[M20] = vec5.z; + matrix[M21] = diff.z; + matrix[M22] = vec2.z; + + phd_GetMatrixAngles(matrix, angle); + + item->pos.xPos = rope->position.x + (rope->meshSegment[Lara.ropeSegment].x >> FP_SHIFT); + item->pos.yPos = rope->position.y + (rope->meshSegment[Lara.ropeSegment].y >> FP_SHIFT) + Lara.ropeOffset; + item->pos.zPos = rope->position.z + (rope->meshSegment[Lara.ropeSegment].z >> FP_SHIFT); + + Matrix rotMatrix = Matrix::CreateFromYawPitchRoll( + TO_RAD(angle[1]), + TO_RAD(angle[0]), + TO_RAD(angle[2]) + ); + + rotMatrix = rotMatrix.Transpose(); + + item->pos.xPos += -112 * rotMatrix.m[0][2]; + item->pos.yPos += -112 * rotMatrix.m[1][2]; + item->pos.zPos += -112 * rotMatrix.m[2][2]; + + item->pos.xRot = angle[0]; + item->pos.yRot = angle[1]; + item->pos.zRot = angle[2]; + } +} \ No newline at end of file diff --git a/TR5Main/Game/rope.h b/TR5Main/Game/rope.h index b6993e911..f7bd5d651 100644 --- a/TR5Main/Game/rope.h +++ b/TR5Main/Game/rope.h @@ -2,51 +2,57 @@ #include "collide.h" -struct ROPE_STRUCT +namespace TEN::Game::Rope { - PHD_VECTOR segment[24]; // size=288, offset=0 - PHD_VECTOR velocity[24]; // size=288, offset=288 - PHD_VECTOR normalisedSegment[24]; // size=288, offset=576 - PHD_VECTOR meshSegment[24]; // size=288, offset=864 - PHD_VECTOR position; // size=12, offset=1152 - PHD_VECTOR Unknown[24]; - int segmentLength; // size=0, offset=1164 - short active; // size=0, offset=1168 - short coiled; // size=0, offset=1170 -}; + struct ROPE_STRUCT + { + PHD_VECTOR segment[24]; // size=288, offset=0 + PHD_VECTOR velocity[24]; // size=288, offset=288 + PHD_VECTOR normalisedSegment[24]; // size=288, offset=576 + PHD_VECTOR meshSegment[24]; // size=288, offset=864 + PHD_VECTOR position; // size=12, offset=1152 + PHD_VECTOR coords[24]; + int segmentLength; // size=0, offset=1164 + short active; // size=0, offset=1168 + short coiled; // size=0, offset=1170 + }; -struct PENDULUM -{ - PHD_VECTOR Position; // size=12, offset=0 - PHD_VECTOR Velocity; // size=12, offset=12 - int node; // size=0, offset=24 - ROPE_STRUCT* Rope; // size=1172, offset=28 -}; + struct PENDULUM + { + PHD_VECTOR Position; // size=12, offset=0 + PHD_VECTOR Velocity; // size=12, offset=12 + int node; // size=0, offset=24 + ROPE_STRUCT* Rope; // size=1172, offset=28 + }; -extern PENDULUM CurrentPendulum; -extern ROPE_STRUCT Ropes[12]; -extern int NumRopes; + constexpr auto ROPE_SEGMENTS = 24; + constexpr auto ROPE_WIDTH = 24; -void InitialiseRope(short itemNumber); -void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item); -PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec); -void _0x0046D130(ROPE_STRUCT* rope, int segmentFrame, int* x, int* y, int* z); -int DotProduct(PHD_VECTOR* u, PHD_VECTOR* v); -void ScaleVector(PHD_VECTOR* src, int c, PHD_VECTOR* dest); -void CrossProduct(PHD_VECTOR* u, PHD_VECTOR* v, PHD_VECTOR* dest); -void _0x0046D420(int* array, short* angle); -void RopeControl(short itemNumber); -void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll); -void RopeDynamics(ROPE_STRUCT* rope); -int _0x0046D200(ROPE_STRUCT* rope, int x, int y, int z, int value); -void ApplyVelocityToRope(int node, short angle, short n); -void SetPendulumVelocity(int x, int y, int z); -void _0x0046E1C0(ROPE_STRUCT* rope, int node); -void _0x0046E080(ROPE_STRUCT* rope, PENDULUM* pendulumPointer, PHD_VECTOR* ropeVelocity, PHD_VECTOR* pendulumVelocity, int value); -void _0x0046DF00(PHD_VECTOR* segment, PHD_VECTOR* nextSegment, PHD_VECTOR* velocity, PHD_VECTOR* nextVelocity, int length); -void UpdateRopeSwing(ITEM_INFO* item); -void JumpOffRope(ITEM_INFO* item); -void FallFromRope(ITEM_INFO* item); -void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll); -void DelAlignLaraToRope(ITEM_INFO* item); + extern PENDULUM CurrentPendulum; + extern PENDULUM AlternatePendulum; + extern std::vector Ropes; + extern int RopeSwing; + void InitialiseRope(short itemNumber); + void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item); + PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec); + void GetRopePos(ROPE_STRUCT* rope, int segmentFrame, int* x, int* y, int* z); + int DotProduct(PHD_VECTOR* u, PHD_VECTOR* v); + void ScaleVector(PHD_VECTOR* src, int c, PHD_VECTOR* dest); + void CrossProduct(PHD_VECTOR* u, PHD_VECTOR* v, PHD_VECTOR* dest); + void phd_GetMatrixAngles(int* array, short* angle); + void RopeControl(short itemNumber); + void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll); + void RopeDynamics(ROPE_STRUCT* rope); + int _0x0046D200(ROPE_STRUCT* rope, int x, int y, int z, int value); + void ApplyVelocityToRope(int node, short angle, short n); + void SetPendulumVelocity(int x, int y, int z); + void _0x0046E1C0(ROPE_STRUCT* rope, int node); + void _0x0046E080(ROPE_STRUCT* rope, PENDULUM* pendulumPointer, PHD_VECTOR* ropeVelocity, PHD_VECTOR* pendulumVelocity, int value); + void _0x0046DF00(PHD_VECTOR* segment, PHD_VECTOR* nextSegment, PHD_VECTOR* velocity, PHD_VECTOR* nextVelocity, int length); + void UpdateRopeSwing(ITEM_INFO* item); + void JumpOffRope(ITEM_INFO* item); + void FallFromRope(ITEM_INFO* item); + void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll); + void DelAlignLaraToRope(ITEM_INFO* item); +} \ No newline at end of file diff --git a/TR5Main/Renderer/Renderer11Draw.cpp b/TR5Main/Renderer/Renderer11Draw.cpp index c1e34c3e9..b3d3e93a4 100644 --- a/TR5Main/Renderer/Renderer11Draw.cpp +++ b/TR5Main/Renderer/Renderer11Draw.cpp @@ -32,6 +32,9 @@ #include #include #include "items.h" +#include "Game/rope.h" + +using namespace TEN::Game::Rope; extern TEN::Renderer::RendererHUDBar *g_DashBar; extern TEN::Renderer::RendererHUDBar *g_SFXVolumeBar; @@ -1960,121 +1963,43 @@ namespace TEN::Renderer } void Renderer11::drawRopes(RenderView& view) -{ - for (int n = 0; n < NumRopes; n++) + { + for (int n = 0; n < Ropes.size(); n++) { - ROPE_STRUCT *rope = &Ropes[n]; + ROPE_STRUCT* rope = &Ropes[n]; if (rope->active) { - // Original algorithm: - // 1) Transform segment coordinates from 3D to 2D + depth - // 2) Get dx, dy and the segment length - // 3) Get sine and cosine from dx / length and dy / length - // 4) Calculate a scale factor - // 5) Get the coordinates of the 4 corners of each sprite iteratively - // 6) Last step only for us, unproject back to 3D coordinates + Matrix world = Matrix::CreateTranslation( + rope->position.x, + rope->position.y, + rope->position.z + ); - // Tranform rope points - Vector3 projected[24]; - Matrix world = Matrix::Identity; + Vector3 absolute[24]; - for (int i = 0; i < 24; i++) + for (int n = 0; n < ROPE_SEGMENTS; n++) { - Vector3 absolutePosition = Vector3(rope->position.x + rope->segment[i].x / 65536.0f, - rope->position.y + rope->segment[i].y / 65536.0f, - rope->position.z + rope->segment[i].z / 65536.0f); + PHD_VECTOR* s = &rope->meshSegment[n]; + Vector3 t; + Vector3 output; - projected[i] = m_viewportToolkit.Project(absolutePosition, Projection, View, world); + t.x = s->x >> FP_SHIFT; + t.y = s->y >> FP_SHIFT; + t.z = s->z >> FP_SHIFT; + + output = Vector3::Transform(t, world); + + Vector3 absolutePosition = Vector3(output.x, output.y, output.z); + absolute[n] = absolutePosition; } - // Now each rope point is transformed in screen X, Y and Z depth - // Let's calculate dx, dy corrections and scaling - float dx = projected[1].x - projected[0].x; - float dy = projected[1].y - projected[0].y; - float length = sqrt(dx * dx + dy * dy); - float s = 0; - float c = 0; - - if (length != 0) + for (int n = 0; n < ROPE_SEGMENTS - 1; n++) { - s = -dy / length; - c = dx / length; - } - - float w = 6.0f; - if (projected[0].z) - { - w = 6.0f * PhdPerspective / projected[0].z / 65536.0f; - if (w < 3) - w = 3; - } - - float sdx = s * w; - float sdy = c * w; - - float x1 = projected[0].x - sdx; - float y1 = projected[0].y - sdy; - - float x2 = projected[0].x + sdx; - float y2 = projected[0].y + sdy; - - float depth = projected[0].z; - - for (int j = 0; j < 24; j++) - { - Vector3 p1 = m_viewportToolkit.Unproject(Vector3(x1, y1, depth), Projection, View, world); - Vector3 p2 = m_viewportToolkit.Unproject(Vector3(x2, y2, depth), Projection, View, world); - - dx = projected[j].x - projected[j - 1].x; - dy = projected[j].y - projected[j - 1].y; - length = sqrt(dx * dx + dy * dy); - s = 0; - c = 0; - - if (length != 0) - { - s = -dy / length; - c = dx / length; - } - - w = 6.0f; - if (projected[j].z) - { - w = 6.0f * PhdPerspective / projected[j].z / 65536.0f; - if (w < 3) - w = 3; - } - - float sdx = s * w; - float sdy = c * w; - - float x3 = projected[j].x - sdx; - float y3 = projected[j].y - sdy; - - float x4 = projected[j].x + sdx; - float y4 = projected[j].y + sdy; - - depth = projected[j].z; - - Vector3 p3 = m_viewportToolkit.Unproject(Vector3(x3, y3, depth), Projection, View, world); - Vector3 p4 = m_viewportToolkit.Unproject(Vector3(x4, y4, depth), Projection, View, world); - - addSprite3D(&m_sprites[20], - Vector3(p1.x, p1.y, p1.z), - Vector3(p2.x, p2.y, p2.z), - Vector3(p3.x, p3.y, p3.z), - Vector3(p4.x, p4.y, p4.z), - Vector4(0.5f, 0.5f, 0.5f, 1.0f), 0, 1, { 0, 0 }, BLENDMODE_OPAQUE,view); - - x1 = x4; - y1 = y4; - x2 = x3; - y2 = y3; + addLine3D(absolute[n], absolute[n + 1], Vector4::One); } } } - } void Renderer11::drawLines2D() diff --git a/TR5Main/Specific/setup.cpp b/TR5Main/Specific/setup.cpp index 521c138fe..a8e45f419 100644 --- a/TR5Main/Specific/setup.cpp +++ b/TR5Main/Specific/setup.cpp @@ -28,7 +28,9 @@ #include "fullblock_switch.h" #include "itemdata/creature_info.h" #include +#include "Game/rope.h" +using namespace TEN::Game::Rope; using namespace TEN::Entities::Switches; OBJECT_INFO Objects[ID_NUMBER_OBJECTS]; diff --git a/TR5Main/Specific/trmath.cpp b/TR5Main/Specific/trmath.cpp index 6e0a4a1f4..d99568d85 100644 --- a/TR5Main/Specific/trmath.cpp +++ b/TR5Main/Specific/trmath.cpp @@ -176,4 +176,89 @@ BoundingOrientedBox TO_DX_BBOX(PHD_3DPOS pos, BOUNDING_BOX* box) BoundingOrientedBox result; BoundingOrientedBox(boxCentre, boxExtent, Vector4::UnitY).Transform(result, 1, rotation, Vector3(pos.xPos, pos.yPos, pos.zPos)); return result; +} + + +__int64 FP_Mul(__int64 a, __int64 b) +{ + return (int)((((__int64)a * (__int64)b)) >> FP_SHIFT); +} + +__int64 FP_Div(__int64 a, __int64 b) +{ + return (int)(((a) / (b >> 8)) << 8); +} + +void FP_VectorMul(PHD_VECTOR* v, int scale, PHD_VECTOR* result) +{ + result->x = FP_FromFixed(v->x * scale); + result->y = FP_FromFixed(v->y * scale); + result->z = FP_FromFixed(v->z * scale); +} + +int FP_DotProduct(PHD_VECTOR* a, PHD_VECTOR* b) +{ + return ((a->x * b->x) + (a->y * b->y) + (a->z * b->z)) >> W2V_SHIFT; +} + +void FP_CrossProduct(PHD_VECTOR* a, PHD_VECTOR* b, PHD_VECTOR* result) +{ + result->x = ((a->y * b->z) - (a->z * b->y)) >> W2V_SHIFT; + result->y = ((a->z * b->x) - (a->x * b->z)) >> W2V_SHIFT; + result->z = ((a->x * b->y) - (a->y * b->x)) >> W2V_SHIFT; +} + +void FP_GetMatrixAngles(MATRIX3D* m, short* angles) +{ + short yaw = phd_atan(m->m22, m->m02); + short pitch = phd_atan(sqrt((m->m22 * m->m22) + (m->m02 * m->m02)), m->m12); + + int sy = phd_sin(yaw); + int cy = phd_cos(yaw); + short roll = phd_atan(((cy * m->m00) - (sy * m->m20)), ((sy * m->m21) - (cy * m->m01))); + + if (((m->m12 >= 0) && pitch > 0) + || ((m->m12 < 0) && pitch < 0)) + pitch = -pitch; + + angles[0] = pitch; + angles[1] = yaw; + angles[2] = roll; +} + +__int64 FP_ToFixed(__int64 value) +{ + return (value << FP_SHIFT); +} + +__int64 FP_FromFixed(__int64 value) +{ + return (value >> FP_SHIFT); +} + +PHD_VECTOR* FP_Normalise(PHD_VECTOR* v) +{ + long a = v->x >> FP_SHIFT; + long b = v->y >> FP_SHIFT; + long c = v->z >> FP_SHIFT; + + if ((a == 0) && (b == 0) && (c == 0)) + return v; + + a = a * a; + b = b * b; + c = c * c; + long d = (a + b + c); + long e = sqrt(abs(d)); + + e <<= FP_SHIFT; + + long mod = FP_Div(FP_ONE << 8, e); + mod >>= 8; + + v->x = FP_Mul(v->x, mod); + v->y = FP_Mul(v->y, mod); + v->z = FP_Mul(v->z, mod); + + return v; } \ No newline at end of file diff --git a/TR5Main/Specific/trmath.h b/TR5Main/Specific/trmath.h index 877287c17..a727a1ec5 100644 --- a/TR5Main/Specific/trmath.h +++ b/TR5Main/Specific/trmath.h @@ -55,4 +55,22 @@ void phd_GetVectorAngles(int x, int y, int z, short* angles); void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, BOUNDING_BOX* bounds, BOUNDING_BOX* tbounds); void InterpolateAngle(short angle, short* rotation, short* outAngle, int shift); -void GetMatrixFromTrAngle(Matrix* matrix, short* frameptr, int index); \ No newline at end of file +void GetMatrixFromTrAngle(Matrix* matrix, short* frameptr, int index); + +constexpr auto FP_SHIFT = 16; +constexpr auto FP_ONE = (1 << FP_SHIFT); +constexpr auto W2V_SHIFT = 14; + +void FP_VectorMul(PHD_VECTOR* v, int scale, PHD_VECTOR* result); +__int64 FP_Mul(__int64 a, __int64 b); +__int64 FP_Div(__int64 a, __int64 b); +int FP_DotProduct(PHD_VECTOR* a, PHD_VECTOR* b); +void FP_CrossProduct(PHD_VECTOR* a, PHD_VECTOR* b, PHD_VECTOR* n); +void FP_GetMatrixAngles(MATRIX3D* m, short* angles); +__int64 FP_ToFixed(__int64 value); +__int64 FP_FromFixed(__int64 value); +PHD_VECTOR* FP_Normalise(PHD_VECTOR* v); + + +#define MULFP(a,b) (int)((((__int64)a*(__int64)b))>>16) +#define DIVFP(a,b) (int)(((a)/(b>>8))<<8) \ No newline at end of file