mirror of
https://gitlab.com/skmp/dca3-game.git
synced 2025-09-03 03:32:37 +02:00
DCA Liberty working minimal changes.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
struct CColLine
|
||||
struct alignas(8) CColLine
|
||||
{
|
||||
// NB: this has to be compatible with two CVuVectors
|
||||
CVector p0;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
struct CColPoint
|
||||
struct alignas(8) CColPoint
|
||||
{
|
||||
CVector point;
|
||||
int pad1;
|
||||
|
@@ -2,12 +2,17 @@
|
||||
|
||||
#include "SurfaceTable.h"
|
||||
|
||||
struct CColSphere
|
||||
struct alignas(8) CColSphere
|
||||
{
|
||||
// NB: this has to be compatible with a CVuVector
|
||||
CVector center;
|
||||
float radius;
|
||||
uint8 surface;
|
||||
uint8 piece;
|
||||
void Set(float radius, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0) {
|
||||
this->radius = radius;
|
||||
this->surface = surf;
|
||||
this->piece = piece;
|
||||
}
|
||||
void Set(float radius, const CVector ¢er, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
|
||||
};
|
@@ -23,6 +23,10 @@
|
||||
#include "Collision.h"
|
||||
#include "Frontend.h"
|
||||
|
||||
#ifdef DC_SH4
|
||||
#include "VuCollision.h"
|
||||
#endif
|
||||
|
||||
#ifdef VU_COLLISION
|
||||
#include "VuCollision.h"
|
||||
|
||||
@@ -737,7 +741,12 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
|
||||
|
||||
// transform line to model space
|
||||
Invert(matrix, matTransform);
|
||||
CColLine newline(matTransform * line.p0, matTransform * line.p1);
|
||||
CColLine newline;
|
||||
#ifndef DC_SH4
|
||||
newline.Set(matTransform * line.p0, matTransform * line.p1);
|
||||
#else
|
||||
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
|
||||
#endif
|
||||
|
||||
// If we don't intersect with the bounding box, no chance on the rest
|
||||
if(!TestLineBox(newline, model.boundingBox))
|
||||
@@ -778,12 +787,13 @@ bool
|
||||
CCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq)
|
||||
{
|
||||
CVector dist = s1.center - s2.center;
|
||||
float d = dist.Magnitude() - s2.radius; // distance from s1's center to s2
|
||||
float mag = dist.Magnitude();
|
||||
float d = mag - s2.radius; // distance from s1's center to s2
|
||||
float depth = s1.radius - d; // sphere overlap
|
||||
if(d < 0.0f) d = 0.0f; // clamp to zero, i.e. if s1's center is inside s2
|
||||
// no collision if sphere is not close enough
|
||||
if(d*d < mindistsq && d < s1.radius){
|
||||
dist.Normalise();
|
||||
dist *= Invert<true, false>(mag);
|
||||
point.point = s1.center - dist*d;
|
||||
point.normal = dist;
|
||||
#ifndef VU_COLLISION
|
||||
@@ -1577,7 +1587,12 @@ CCollision::ProcessLineOfSight(const CColLine &line,
|
||||
|
||||
// transform line to model space
|
||||
Invert(matrix, matTransform);
|
||||
CColLine newline(matTransform * line.p0, matTransform * line.p1);
|
||||
CColLine newline;
|
||||
#ifdef DC_SH4
|
||||
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
|
||||
#else
|
||||
newline.Set(matTransform * line.p0, matTransform * line.p1);
|
||||
#endif
|
||||
|
||||
// If we don't intersect with the bounding box, no chance on the rest
|
||||
if(!TestLineBox(newline, model.boundingBox))
|
||||
@@ -1601,8 +1616,18 @@ CCollision::ProcessLineOfSight(const CColLine &line,
|
||||
}
|
||||
|
||||
if(coldist < mindist){
|
||||
#ifndef DC_SH4
|
||||
point.point = matrix * point.point;
|
||||
point.normal = Multiply3x3(matrix, point.normal);
|
||||
#else
|
||||
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
|
||||
mat_trans_single3_nodiv(point.point.x,
|
||||
point.point.y,
|
||||
point.point.z);
|
||||
mat_trans_normal3(point.normal.x,
|
||||
point.normal.y,
|
||||
point.normal.z);
|
||||
#endif
|
||||
mindist = coldist;
|
||||
return true;
|
||||
}
|
||||
@@ -1739,9 +1764,14 @@ CCollision::ProcessVerticalLine(const CColLine &line,
|
||||
|
||||
// transform line to model space
|
||||
// Why does the game seem to do this differently than above?
|
||||
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
|
||||
newline.p1.x = newline.p0.x;
|
||||
newline.p1.y = newline.p0.y;
|
||||
CMatrix matTransform;
|
||||
Invert(matrix, matTransform);
|
||||
CColLine newline;
|
||||
#ifndef DC_SH4
|
||||
newline.Set(matTransform * line.p0, matTransform * line.p1);
|
||||
#else
|
||||
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
|
||||
#endif
|
||||
|
||||
if(!TestVerticalLineBox(newline, model.boundingBox))
|
||||
return false;
|
||||
@@ -1765,14 +1795,31 @@ CCollision::ProcessVerticalLine(const CColLine &line,
|
||||
}
|
||||
|
||||
if(coldist < mindist){
|
||||
#ifndef DC_SH4
|
||||
point.point = matrix * point.point;
|
||||
point.normal = Multiply3x3(matrix, point.normal);
|
||||
#else
|
||||
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
|
||||
mat_trans_single3_nodiv(point.point.x,
|
||||
point.point.y,
|
||||
point.point.z);
|
||||
mat_trans_normal3(point.normal.x,
|
||||
point.normal.y,
|
||||
point.normal.z);
|
||||
#endif
|
||||
if(TempStoredPoly.valid && poly){
|
||||
*poly = TempStoredPoly;
|
||||
#ifndef DC_SH4
|
||||
poly->verts[0] = matrix * poly->verts[0];
|
||||
poly->verts[1] = matrix * poly->verts[1];
|
||||
poly->verts[2] = matrix * poly->verts[2];
|
||||
#else
|
||||
mat_trans_single3_nodiv(poly->verts[0].x, poly->verts[0].y, poly->verts[0].z);
|
||||
mat_trans_single3_nodiv(poly->verts[1].x, poly->verts[1].y, poly->verts[1].z);
|
||||
mat_trans_single3_nodiv(poly->verts[2].x, poly->verts[2].y, poly->verts[2].z);
|
||||
#endif
|
||||
}
|
||||
|
||||
mindist = coldist;
|
||||
return true;
|
||||
}
|
||||
@@ -2128,20 +2175,52 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||
|
||||
CColSphere bsphereAB; // bounding sphere of A in B space
|
||||
bsphereAB.radius = modelA.boundingSphere.radius;
|
||||
#ifndef DC_SH4
|
||||
bsphereAB.center = matAB * modelA.boundingSphere.center;
|
||||
#else
|
||||
/* No need to reload the matrix, since it's already banked.
|
||||
mat_load(reinterpret_cast<const matrix_t *>(&matAB)); */
|
||||
mat_trans_single3_nodiv_nomod(modelA.boundingSphere.center.x,
|
||||
modelA.boundingSphere.center.y,
|
||||
modelA.boundingSphere.center.z,
|
||||
bsphereAB.center.x,
|
||||
bsphereAB.center.y,
|
||||
bsphereAB.center.z);
|
||||
#endif
|
||||
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
|
||||
return 0;
|
||||
// B to A space
|
||||
matBA = Invert(matrixA, matBA);
|
||||
matBA *= matrixB;
|
||||
|
||||
// transform modelA's spheres and lines to B space
|
||||
for(i = 0; i < modelA.numSpheres; i++){
|
||||
CColSphere &s = modelA.spheres[i];
|
||||
#ifndef DC_SH4
|
||||
aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece);
|
||||
#else
|
||||
auto &d = aSpheresA[i];
|
||||
mat_trans_single3_nodiv_nomod(s.center.x, s.center.y, s.center.z,
|
||||
d.center.x, d.center.y, d.center.z);
|
||||
d.Set(s.radius, s.surface, s.piece);
|
||||
#endif
|
||||
}
|
||||
for(i = 0; i < modelA.numLines; i++)
|
||||
|
||||
for(i = 0; i < modelA.numLines; i++) {
|
||||
#ifndef DC_SH4
|
||||
aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);
|
||||
#else
|
||||
mat_trans_single3_nodiv_nomod(modelA.lines[i].p0.x,
|
||||
modelA.lines[i].p0.y,
|
||||
modelA.lines[i].p0.z,
|
||||
aLinesA[i].p0.x,
|
||||
aLinesA[i].p0.y,
|
||||
aLinesA[i].p0.z);
|
||||
mat_trans_single3_nodiv_nomod(modelA.lines[i].p1.x,
|
||||
modelA.lines[i].p1.y,
|
||||
modelA.lines[i].p1.z,
|
||||
aLinesA[i].p1.x,
|
||||
aLinesA[i].p1.y,
|
||||
aLinesA[i].p1.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test them against model B's bounding volumes
|
||||
int numSpheresA = 0;
|
||||
@@ -2160,9 +2239,25 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||
int numSpheresB = 0;
|
||||
int numBoxesB = 0;
|
||||
int numTrianglesB = 0;
|
||||
// B to A space
|
||||
matBA = Invert(matrixA, matBA);
|
||||
matBA *= matrixB;
|
||||
#ifdef DC_SH4
|
||||
/* No need to reload the matrix, since it's already banked.
|
||||
mat_load(reinterpret_cast<const matrix_t *>(&matBA)); */
|
||||
#endif
|
||||
for(i = 0; i < modelB.numSpheres; i++){
|
||||
s.radius = modelB.spheres[i].radius;
|
||||
#ifndef DC_SH4
|
||||
s.center = matBA * modelB.spheres[i].center;
|
||||
#else
|
||||
mat_trans_single3_nodiv_nomod(modelB.spheres[i].center.x,
|
||||
modelB.spheres[i].center.y,
|
||||
modelB.spheres[i].center.z,
|
||||
s.center.x,
|
||||
s.center.y,
|
||||
s.center.z);
|
||||
#endif
|
||||
if(TestSphereBox(s, modelA.boundingBox))
|
||||
aSphereIndicesB[numSpheresB++] = i;
|
||||
}
|
||||
@@ -2209,9 +2304,22 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||
if(hasCollided)
|
||||
numCollisions++;
|
||||
}
|
||||
|
||||
#ifdef DC_SH4
|
||||
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrixB)));
|
||||
#endif
|
||||
for(i = 0; i < numCollisions; i++){
|
||||
#ifndef DC_SH4
|
||||
spherepoints[i].point = matrixB * spherepoints[i].point;
|
||||
spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
|
||||
#else
|
||||
mat_trans_single3_nodiv(spherepoints[i].point.x,
|
||||
spherepoints[i].point.y,
|
||||
spherepoints[i].point.z);
|
||||
mat_trans_normal3(spherepoints[i].normal.x,
|
||||
spherepoints[i].normal.y,
|
||||
spherepoints[i].normal.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
// And the same thing for the lines in A
|
||||
@@ -2242,8 +2350,17 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||
for(i = 0; i < numLinesA; i++)
|
||||
if(aCollided[i]){
|
||||
j = aLineIndicesA[i];
|
||||
#ifndef DC_SH4
|
||||
linepoints[j].point = matrixB * linepoints[j].point;
|
||||
linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal);
|
||||
#else
|
||||
mat_trans_single3_nodiv(linepoints[j].point.x,
|
||||
linepoints[j].point.y,
|
||||
linepoints[j].point.z);
|
||||
mat_trans_normal3(linepoints[j].normal.x,
|
||||
linepoints[j].normal.y,
|
||||
linepoints[j].normal.z);
|
||||
#endif
|
||||
}
|
||||
|
||||
return numCollisions; // sphere collisions
|
||||
|
@@ -1,11 +1,5 @@
|
||||
#include "common.h"
|
||||
|
||||
CMatrix::CMatrix(void)
|
||||
{
|
||||
m_attachment = nil;
|
||||
m_hasRwMatrix = false;
|
||||
}
|
||||
|
||||
CMatrix::CMatrix(CMatrix const &m)
|
||||
{
|
||||
m_attachment = nil;
|
||||
@@ -510,14 +504,9 @@ operator*(const CMatrix &m1, const CMatrix &m2)
|
||||
{
|
||||
// TODO: VU0 code
|
||||
CMatrix out;
|
||||
#if defined(RW_DC) && 0 // THIS IS BROKEN, 4th element shouldn't be processed
|
||||
# ifdef DC_SH4
|
||||
MATH_Load_Matrix_Product(reinterpret_cast<const matrix_t *>(&m1), reinterpret_cast<const matrix_t *>(&m2));
|
||||
|
||||
# elif defined(RW_DC)
|
||||
mat_load(reinterpret_cast<const matrix_t *>(&m2));
|
||||
mat_apply(reinterpret_cast<const matrix_t *>(&m1));
|
||||
# endif
|
||||
#if defined(RW_DC)
|
||||
mat_load(reinterpret_cast<const matrix_t *>(&m1));
|
||||
mat_apply(reinterpret_cast<const matrix_t *>(&m2));
|
||||
mat_store(reinterpret_cast<matrix_t *>(&out));
|
||||
#else
|
||||
out.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
class CMatrix
|
||||
class alignas(8) CMatrix
|
||||
{
|
||||
public:
|
||||
union
|
||||
@@ -8,17 +8,17 @@ public:
|
||||
alignas(8) float f[4][4];
|
||||
struct alignas(8)
|
||||
{
|
||||
float rx, ry, rz, rw;
|
||||
float fx, fy, fz, fw;
|
||||
float ux, uy, uz, uw;
|
||||
float px, py, pz, pw;
|
||||
float rx, ry, rz, rw=0.0f;
|
||||
float fx, fy, fz, fw=0.0f;
|
||||
float ux, uy, uz, uw=0.0f;
|
||||
float px, py, pz, pw=1.0f;
|
||||
};
|
||||
};
|
||||
|
||||
RwMatrix *m_attachment;
|
||||
bool m_hasRwMatrix; // are we the owner?
|
||||
RwMatrix *m_attachment = nil;
|
||||
bool m_hasRwMatrix = false; // are we the owner?
|
||||
|
||||
CMatrix(void);
|
||||
CMatrix(void) = default;
|
||||
CMatrix(CMatrix const &m);
|
||||
CMatrix(RwMatrix *matrix, bool owner = false);
|
||||
CMatrix(float scale){
|
||||
|
@@ -80,7 +80,6 @@ __always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const Rw
|
||||
|
||||
__always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)
|
||||
{
|
||||
assert(false);
|
||||
#ifdef GTA_PS2
|
||||
__asm__ __volatile__("\n\
|
||||
paddub $3,%4,$0\n\
|
||||
@@ -110,9 +109,11 @@ __always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat,
|
||||
": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory");
|
||||
#elif defined(DC_SH4)
|
||||
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
|
||||
mat_transform(reinterpret_cast<vector_t *>(const_cast<RwV3d *>(in)),
|
||||
reinterpret_cast<vector_t *>(out),
|
||||
n, stride - sizeof(vector_t));
|
||||
while(n--) {
|
||||
mat_trans_single3_nodiv_nomod(in->x, in->y, in->z, out->x, out->y, out->z);
|
||||
in = reinterpret_cast<const RwV3d *>(reinterpret_cast<const uint8_t *>(in) + stride);
|
||||
++out;
|
||||
}
|
||||
#else
|
||||
while(n--){
|
||||
*out = mat * *in;
|
||||
|
Reference in New Issue
Block a user