Fixing ropes and added debug ropes drawing

This commit is contained in:
MontyTRC89 2021-09-28 13:01:28 +02:00
parent 08703a5d57
commit 85bb127b12
8 changed files with 924 additions and 838 deletions

View file

@ -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;

View file

@ -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.*/

View file

@ -9,13 +9,15 @@
#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
{
PENDULUM CurrentPendulum;
PENDULUM AlternatePendulum;
std::vector<ROPE_STRUCT> Ropes;
int RopeSwing = 0;
void InitialiseRope(short itemNumber)
{
PHD_VECTOR itemPos;
ITEM_INFO* item = &g_Level.Items[itemNumber];
@ -33,16 +35,16 @@ void InitialiseRope(short itemNumber)
pos.y = 16384;
pos.z = 0;
ROPE_STRUCT* rope = &Ropes[NumRopes];
ROPE_STRUCT rope;
PrepareRope(&rope, &itemPos, &pos, 128, item);
PrepareRope(rope, &itemPos, &pos, 128, item);
item->triggerFlags = Ropes.size();
item->triggerFlags = NumRopes;
NumRopes++;
}
Ropes.push_back(rope);
}
void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item)
{
void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int length, ITEM_INFO* item)
{
rope->position = *pos1;
rope->segmentLength = length << 16;
@ -61,11 +63,11 @@ void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int leng
int sum = 0;
int il = 3145728;
for (int i = 0; i < 24; ++i)
for (int i = 0; i < ROPE_SEGMENTS; ++i)
{
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;
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 = 0;
rope->velocity[i].y = 0;
@ -87,13 +89,13 @@ void PrepareRope(ROPE_STRUCT* rope, PHD_VECTOR* pos1, PHD_VECTOR* pos2, int leng
}
rope->active = 0;
}
}
PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec)
{
int x = vec->x >> 16;
int y = vec->y >> 16;
int z = vec->z >> 16;
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;
@ -104,54 +106,55 @@ PHD_VECTOR* NormaliseRopeVector(PHD_VECTOR* vec)
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;
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 _0x0046D130(ROPE_STRUCT* rope, int segmentFrame, int* x, int* y, int* z)
{
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 >> 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;
}
*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;
}
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;
}
int DotProduct(PHD_VECTOR* u, PHD_VECTOR* v)
{
return (u->x * v->x + u->y * v->y + u->z * v->z) >> W2V_SHIFT;
}
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 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 _0x0046D420(int* matrix, short* angle)
{
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)
{
void RopeControl(short itemNumber)
{
ITEM_INFO* item;
ROPE_STRUCT* rope;
@ -166,10 +169,10 @@ void RopeControl(short itemNumber)
{
rope->active = 0;
}
}
}
void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{
void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
{
ITEM_INFO* item;
ROPE_STRUCT* rope;
BOUNDING_BOX* frame;
@ -209,10 +212,10 @@ void RopeCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
ApplyVelocityToRope(segment, l->pos.yRot, 16 * LaraItem->speed);
}
}
}
}
void RopeDynamics(ROPE_STRUCT* rope)
{
void RopeDynamics(ROPE_STRUCT* rope)
{
int flag, i;
PENDULUM* pendulumPointer;
PHD_VECTOR vec, vec2;
@ -223,11 +226,11 @@ void RopeDynamics(ROPE_STRUCT* rope)
--rope->coiled;
if (!rope->coiled)
{
for (i = 0; i < 24; ++i)
for (i = 0; i < ROPE_SEGMENTS; ++i)
rope->velocity[i].y = 0;
}
}
if (rope == &Ropes[Lara.ropePtr])
if (Lara.ropePtr != -1 && rope == &Ropes[Lara.ropePtr])
{
pendulumPointer = &CurrentPendulum;
if (CurrentPendulum.node != Lara.ropeSegment + 1)
@ -250,9 +253,11 @@ void RopeDynamics(ROPE_STRUCT* rope)
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;
}
@ -263,24 +268,29 @@ void RopeDynamics(ROPE_STRUCT* rope)
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->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;
}
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)
for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
{
rope->segment[i].x -= vec2.x;
rope->segment[i].y -= vec2.y;
@ -300,13 +310,15 @@ void RopeDynamics(ROPE_STRUCT* rope)
}
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)
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 < 24; ++i)
for (i = pendulumPointer->node; i < ROPE_SEGMENTS; ++i)
{
rope->velocity[i].y += 196608;
if (pendulumPointer->Rope)
@ -323,29 +335,34 @@ void RopeDynamics(ROPE_STRUCT* rope)
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)
for (i = 0; i < ROPE_SEGMENTS - 1; ++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])
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 >> 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[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++)
{
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);
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
@ -353,122 +370,134 @@ void RopeDynamics(ROPE_STRUCT* rope)
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[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 >> 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);
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)
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 _0x0046D200(ROPE_STRUCT* rope, int x, int y, int z, int radius)
{
int dx, dy, dz;
for (int i = 0; i < 22; ++i)
for (int i = 0; i < ROPE_SEGMENTS - 2; ++i)
{
if (y > rope->position.y + (rope->meshSegment[i].y / 65536) && y < rope->position.y + (rope->meshSegment[i + 1].y / 65536))
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) / 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;
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)
{
void ApplyVelocityToRope(int node, short angle, short n)
{
SetPendulumVelocity(
(unsigned short) n * phd_sin(angle) * 4096,
(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 */
}
(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)
{
void SetPendulumVelocity(int x, int y, int z)
{
int node;
node = 2 * (CurrentPendulum.node >> 1);
if (node < 24)
if (node < ROPE_SEGMENTS)
{
int val = 4096 / (24 - node) * 256;
int val = 4096 / (ROPE_SEGMENTS - node) * 256;
x = (int64_t)val * x >> 16;
y = (int64_t)val * y >> 16;
z = (int64_t)val * z >> 16;
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)
{
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)
{
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)
{
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 >> 16) + SQUARE(vec.y >> 16) + SQUARE(vec.z >> 16))) - length) / 2;
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 >> 16;
vec.y = (int64_t)result * vec.y >> 16;
vec.z = (int64_t)result * vec.z >> 16;
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)
{
void UpdateRopeSwing(ITEM_INFO* item)
{
if (Lara.ropeMaxXForward > 9000)
{
Lara.ropeMaxXForward = 9000;
@ -558,10 +587,10 @@ void UpdateRopeSwing(ITEM_INFO* item)
if (item->pos.xRot < -Lara.ropeMaxXBackward)
Lara.ropeMaxXBackward = abs(item->pos.xRot);
}
}
}
void JumpOffRope(ITEM_INFO* item)
{
void JumpOffRope(ITEM_INFO* item)
{
if (Lara.ropePtr != -1)
{
if (item->pos.xRot >= 0)
@ -599,11 +628,11 @@ void JumpOffRope(ITEM_INFO* item)
Lara.ropePtr = -1;
}
}
}
void FallFromRope(ITEM_INFO* item)
{
item->speed = abs(CurrentPendulum.Velocity.x >> 16) + abs(CurrentPendulum.Velocity.z >> 16) >> 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;
@ -617,10 +646,10 @@ void FallFromRope(ITEM_INFO* item)
Lara.gunStatus = LG_NO_ARMS;
Lara.ropePtr = -1;
}
}
void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll)
{
void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll)
{
if (!(TrInput & IN_ACTION))
{
FallFromRope(item);
@ -665,10 +694,10 @@ void LaraClimbRope(ITEM_INFO* item, COLL_INFO* coll)
if (!(TrInput & IN_BACK) || Lara.ropeSegment >= 21)
item->goalAnimState = LS_ROPE_IDLE;
}
}
}
void DelAlignLaraToRope(ITEM_INFO* item)
{
void DelAlignLaraToRope(ITEM_INFO* item)
{
ROPE_STRUCT* rope;
short ropeY;
PHD_VECTOR vec, vec2, vec3, vec4, vec5, pos, pos2, diff, diff2;
@ -679,11 +708,14 @@ void DelAlignLaraToRope(ITEM_INFO* item)
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);
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);
diff.x = pos.x - pos2.x << 16;
diff.y = pos.y - pos2.y << 16;
diff.z = pos.z - pos2.z << 16;
@ -695,23 +727,28 @@ void DelAlignLaraToRope(ITEM_INFO* item)
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;
@ -719,7 +756,9 @@ void DelAlignLaraToRope(ITEM_INFO* item)
vec2.x >>= 2;
vec2.y >>= 2;
vec2.z >>= 2;
CrossProduct(&diff, &vec2, &vec5);
vec5.x <<= 16;
vec5.y <<= 16;
vec5.z <<= 16;
@ -727,6 +766,7 @@ void DelAlignLaraToRope(ITEM_INFO* item)
vec5.x >>= 2;
vec5.y >>= 2;
vec5.z >>= 2;
matrix[M00] = vec5.x;
matrix[M01] = diff.x;
matrix[M02] = vec2.x;
@ -736,23 +776,27 @@ void DelAlignLaraToRope(ITEM_INFO* item)
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);
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_DEGREES(angle[1]),
TO_DEGREES(angle[0]),
TO_DEGREES(angle[2])
TO_RAD(angle[1]),
TO_RAD(angle[0]),
TO_RAD(angle[2])
);
// 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;
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];
}
}

View file

@ -2,51 +2,57 @@
#include "collide.h"
struct ROPE_STRUCT
namespace TEN::Game::Rope
{
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 Unknown[24];
PHD_VECTOR coords[24];
int segmentLength; // size=0, offset=1164
short active; // size=0, offset=1168
short coiled; // size=0, offset=1170
};
};
struct PENDULUM
{
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<ROPE_STRUCT> 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);
}

View file

@ -32,6 +32,9 @@
#include <Objects/Effects/tr4_locusts.h>
#include <control\volume.h>
#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++)
{
ROPE_STRUCT *rope = &Ropes[n];
for (int n = 0; n < Ropes.size(); 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()

View file

@ -28,7 +28,9 @@
#include "fullblock_switch.h"
#include "itemdata/creature_info.h"
#include <Objects/Effects/effect_objects.h>
#include "Game/rope.h"
using namespace TEN::Game::Rope;
using namespace TEN::Entities::Switches;
OBJECT_INFO Objects[ID_NUMBER_OBJECTS];

View file

@ -177,3 +177,88 @@ BoundingOrientedBox TO_DX_BBOX(PHD_3DPOS pos, BOUNDING_BOX* box)
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;
}

View file

@ -56,3 +56,21 @@ void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, BOUNDING_BOX* bounds, BOUNDING_BO
void InterpolateAngle(short angle, short* rotation, short* outAngle, int shift);
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)