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

File diff suppressed because it is too large Load diff

View file

@ -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<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++)
{
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()

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

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

View file

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