2019-05-15 16:52:37 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "templates.h"
|
|
|
|
#include "Game.h" // for eLevelName
|
2020-08-03 12:58:37 +02:00
|
|
|
#ifdef VU_COLLISION
|
|
|
|
#include "VuVector.h"
|
|
|
|
#endif
|
2019-05-15 16:52:37 +02:00
|
|
|
|
2020-04-15 18:19:45 +02:00
|
|
|
// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
|
2020-08-03 03:00:12 +02:00
|
|
|
#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
|
2020-04-15 18:19:45 +02:00
|
|
|
#define MAX_COLLISION_POINTS 64
|
|
|
|
#else
|
|
|
|
#define MAX_COLLISION_POINTS 32
|
|
|
|
#endif
|
|
|
|
|
2020-07-27 15:38:34 +02:00
|
|
|
struct CompressedVector
|
|
|
|
{
|
|
|
|
#ifdef COMPRESSED_COL_VECTORS
|
|
|
|
int16 x, y, z;
|
|
|
|
CVector Get(void) const { return CVector(x, y, z)/128.0f; };
|
|
|
|
void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
|
2020-08-03 12:58:37 +02:00
|
|
|
#ifdef GTA_PS2
|
|
|
|
void Unpack(uint128 &qword) const {
|
|
|
|
__asm__ volatile (
|
|
|
|
"lh $8, 0(%1)\n"
|
|
|
|
"lh $9, 2(%1)\n"
|
|
|
|
"lh $10, 4(%1)\n"
|
|
|
|
"pextlw $10, $8\n"
|
|
|
|
"pextlw $2, $9, $10\n"
|
|
|
|
"sq $2, %0\n"
|
|
|
|
: "=m" (qword)
|
|
|
|
: "r" (this)
|
|
|
|
: "$8", "$9", "$10", "$2"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void Unpack(int32 *qword) const {
|
|
|
|
qword[0] = x;
|
|
|
|
qword[1] = y;
|
|
|
|
qword[2] = z;
|
|
|
|
qword[3] = 0; // junk
|
|
|
|
}
|
|
|
|
#endif
|
2020-07-27 15:38:34 +02:00
|
|
|
#else
|
|
|
|
float x, y, z;
|
|
|
|
CVector Get(void) const { return CVector(x, y, z); };
|
|
|
|
void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2020-05-06 17:56:38 +02:00
|
|
|
struct CSphere
|
2019-05-15 16:52:37 +02:00
|
|
|
{
|
2020-08-03 12:58:37 +02:00
|
|
|
// NB: this has to be compatible with a CVuVector
|
2019-05-15 16:52:37 +02:00
|
|
|
CVector center;
|
|
|
|
float radius;
|
2020-05-06 17:56:38 +02:00
|
|
|
void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CBox
|
|
|
|
{
|
|
|
|
CVector min;
|
|
|
|
CVector max;
|
|
|
|
CVector GetSize(void) { return max - min; }
|
|
|
|
void Set(const CVector &min, const CVector &max) { this->min = min; this->max = max; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CColSphere : public CSphere
|
|
|
|
{
|
2019-05-15 16:52:37 +02:00
|
|
|
uint8 surface;
|
|
|
|
uint8 piece;
|
|
|
|
|
|
|
|
void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece);
|
2020-06-13 22:39:14 +02:00
|
|
|
bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
|
2020-05-06 17:56:38 +02:00
|
|
|
using CSphere::Set;
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
2020-05-06 17:56:38 +02:00
|
|
|
struct CColBox : public CBox
|
2019-05-15 16:52:37 +02:00
|
|
|
{
|
|
|
|
uint8 surface;
|
|
|
|
uint8 piece;
|
|
|
|
|
|
|
|
void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
|
2020-05-06 17:56:38 +02:00
|
|
|
using CBox::Set;
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CColLine
|
|
|
|
{
|
2020-08-03 12:58:37 +02:00
|
|
|
// NB: this has to be compatible with two CVuVectors
|
2019-05-15 16:52:37 +02:00
|
|
|
CVector p0;
|
|
|
|
int pad0;
|
|
|
|
CVector p1;
|
|
|
|
int pad1;
|
|
|
|
|
|
|
|
CColLine(void) { };
|
|
|
|
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
|
|
|
|
void Set(const CVector &p0, const CVector &p1);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CColTriangle
|
|
|
|
{
|
|
|
|
uint16 a;
|
|
|
|
uint16 b;
|
|
|
|
uint16 c;
|
|
|
|
uint8 surface;
|
|
|
|
|
2020-07-27 15:38:34 +02:00
|
|
|
void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CColTrianglePlane
|
|
|
|
{
|
2020-08-03 12:58:37 +02:00
|
|
|
#ifdef VU_COLLISION
|
|
|
|
CompressedVector normal;
|
|
|
|
int16 dist;
|
|
|
|
|
|
|
|
void Set(const CVector &va, const CVector &vb, const CVector &vc);
|
|
|
|
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
|
|
|
|
void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
|
|
|
|
float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
|
|
|
|
#ifdef GTA_PS2
|
|
|
|
void Unpack(uint128 &qword) const {
|
|
|
|
__asm__ volatile (
|
|
|
|
"lh $8, 0(%1)\n"
|
|
|
|
"lh $9, 2(%1)\n"
|
|
|
|
"lh $10, 4(%1)\n"
|
|
|
|
"lh $11, 6(%1)\n"
|
|
|
|
"pextlw $10, $8\n"
|
|
|
|
"pextlw $11, $9\n"
|
|
|
|
"pextlw $2, $11, $10\n"
|
|
|
|
"sq $2, %0\n"
|
|
|
|
: "=m" (qword)
|
|
|
|
: "r" (this)
|
|
|
|
: "$8", "$9", "$10", "$11", "$2"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void Unpack(int32 *qword) const {
|
|
|
|
qword[0] = normal.x;
|
|
|
|
qword[1] = normal.y;
|
|
|
|
qword[2] = normal.z;
|
|
|
|
qword[3] = dist;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#else
|
2019-05-15 16:52:37 +02:00
|
|
|
CVector normal;
|
|
|
|
float dist;
|
|
|
|
uint8 dir;
|
|
|
|
|
2020-07-27 15:38:34 +02:00
|
|
|
void Set(const CVector &va, const CVector &vb, const CVector &vc);
|
|
|
|
void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
|
2019-05-15 16:52:37 +02:00
|
|
|
void GetNormal(CVector &n) const { n = normal; }
|
2020-07-29 11:17:53 +02:00
|
|
|
float GetNormalX() const { return normal.x; }
|
|
|
|
float GetNormalY() const { return normal.y; }
|
|
|
|
float GetNormalZ() const { return normal.z; }
|
2019-05-15 16:52:37 +02:00
|
|
|
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
|
2020-08-03 12:58:37 +02:00
|
|
|
#endif
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CColPoint
|
|
|
|
{
|
|
|
|
CVector point;
|
|
|
|
int pad1;
|
|
|
|
// the surface normal on the surface of point
|
|
|
|
CVector normal;
|
|
|
|
int pad2;
|
|
|
|
uint8 surfaceA;
|
|
|
|
uint8 pieceA;
|
|
|
|
uint8 surfaceB;
|
|
|
|
uint8 pieceB;
|
|
|
|
float depth;
|
2020-06-20 15:23:32 +02:00
|
|
|
|
|
|
|
CColPoint& operator=(const CColPoint& other);
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CStoredCollPoly
|
|
|
|
{
|
2020-08-03 12:58:37 +02:00
|
|
|
#ifdef VU_COLLISION
|
|
|
|
CVuVector verts[3];
|
|
|
|
#else
|
2019-05-15 16:52:37 +02:00
|
|
|
CVector verts[3];
|
2020-08-03 12:58:37 +02:00
|
|
|
#endif
|
2019-05-15 16:52:37 +02:00
|
|
|
bool valid;
|
|
|
|
};
|
|
|
|
|
2020-05-06 17:56:38 +02:00
|
|
|
//--MIAMI: done struct
|
2019-05-15 16:52:37 +02:00
|
|
|
struct CColModel
|
|
|
|
{
|
2020-05-06 17:56:38 +02:00
|
|
|
CSphere boundingSphere;
|
|
|
|
CBox boundingBox;
|
2020-05-05 13:02:42 +02:00
|
|
|
int16 numSpheres;
|
|
|
|
int16 numBoxes;
|
|
|
|
int16 numTriangles;
|
2020-05-06 17:56:38 +02:00
|
|
|
int8 numLines;
|
2020-05-05 18:06:38 +02:00
|
|
|
uint8 level; // colstore slot but probably still named level
|
2019-05-15 16:52:37 +02:00
|
|
|
bool ownsCollisionVolumes;
|
|
|
|
CColSphere *spheres;
|
|
|
|
CColLine *lines;
|
|
|
|
CColBox *boxes;
|
2020-07-27 15:38:34 +02:00
|
|
|
CompressedVector *vertices;
|
2019-05-15 16:52:37 +02:00
|
|
|
CColTriangle *triangles;
|
|
|
|
CColTrianglePlane *trianglePlanes;
|
|
|
|
|
|
|
|
CColModel(void);
|
|
|
|
~CColModel(void);
|
|
|
|
void RemoveCollisionVolumes(void);
|
|
|
|
void CalculateTrianglePlanes(void);
|
|
|
|
void RemoveTrianglePlanes(void);
|
|
|
|
CLink<CColModel*> *GetLinkPtr(void);
|
|
|
|
void SetLinkPtr(CLink<CColModel*>*);
|
|
|
|
void GetTrianglePoint(CVector &v, int i) const;
|
|
|
|
|
2019-06-25 00:42:23 +02:00
|
|
|
CColModel& operator=(const CColModel& other);
|
2019-05-15 16:52:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class CCollision
|
|
|
|
{
|
|
|
|
public:
|
2020-04-15 18:19:45 +02:00
|
|
|
static eLevelName ms_collisionInMemory;
|
|
|
|
static CLinkList<CColModel*> ms_colModelCache;
|
2019-05-15 16:52:37 +02:00
|
|
|
|
|
|
|
static void Init(void);
|
2019-06-28 19:23:28 +02:00
|
|
|
static void Shutdown(void);
|
2019-05-15 16:52:37 +02:00
|
|
|
static void Update(void);
|
|
|
|
static void LoadCollisionWhenINeedIt(bool changeLevel);
|
2019-06-25 00:42:23 +02:00
|
|
|
static void SortOutCollisionAfterLoad(void);
|
2019-06-28 19:23:28 +02:00
|
|
|
static void LoadCollisionScreen(eLevelName level);
|
2019-05-15 16:52:37 +02:00
|
|
|
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
|
|
|
|
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
|
|
|
|
|
|
|
|
static void CalculateTrianglePlanes(CColModel *model);
|
2020-07-27 15:38:34 +02:00
|
|
|
static void RemoveTrianglePlanes(CColModel *model);
|
2019-05-15 16:52:37 +02:00
|
|
|
|
|
|
|
// all these return true if there's a collision
|
2020-05-06 17:56:38 +02:00
|
|
|
static bool TestSphereSphere(const CSphere &s1, const CSphere &s2);
|
|
|
|
static bool TestSphereBox(const CSphere &sph, const CBox &box);
|
|
|
|
static bool TestLineBox(const CColLine &line, const CBox &box);
|
|
|
|
static bool TestVerticalLineBox(const CColLine &line, const CBox &box);
|
2020-07-27 15:38:34 +02:00
|
|
|
static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
2019-05-15 16:52:37 +02:00
|
|
|
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
|
2020-07-27 15:38:34 +02:00
|
|
|
static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
2020-05-24 15:14:27 +02:00
|
|
|
static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);
|
2019-05-15 16:52:37 +02:00
|
|
|
|
|
|
|
static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
|
|
|
|
static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
|
|
|
|
static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
|
2020-07-27 15:38:34 +02:00
|
|
|
static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
|
|
|
|
static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly = nil);
|
2019-05-15 16:52:37 +02:00
|
|
|
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
|
2020-07-27 15:38:34 +02:00
|
|
|
static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
|
2020-05-24 15:14:27 +02:00
|
|
|
static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough);
|
|
|
|
static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly);
|
2019-07-09 09:57:44 +02:00
|
|
|
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
|
2019-09-14 19:58:09 +02:00
|
|
|
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
|
2019-05-15 16:52:37 +02:00
|
|
|
|
|
|
|
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
|
|
|
|
static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
|
|
|
|
};
|