mirror of
https://git.rip/DMCA_FUCKER/re3.git
synced 2024-12-24 13:20:00 +00:00
Merge branch 'miami' into lcs-dev
This commit is contained in:
commit
ed5a9d5dc1
|
@ -233,6 +233,7 @@ project "reVC"
|
||||||
files { addSrcFiles("src/audio") }
|
files { addSrcFiles("src/audio") }
|
||||||
files { addSrcFiles("src/audio/eax") }
|
files { addSrcFiles("src/audio/eax") }
|
||||||
files { addSrcFiles("src/audio/oal") }
|
files { addSrcFiles("src/audio/oal") }
|
||||||
|
files { addSrcFiles("src/collision") }
|
||||||
files { addSrcFiles("src/control") }
|
files { addSrcFiles("src/control") }
|
||||||
files { addSrcFiles("src/core") }
|
files { addSrcFiles("src/core") }
|
||||||
files { addSrcFiles("src/entities") }
|
files { addSrcFiles("src/entities") }
|
||||||
|
@ -255,6 +256,7 @@ project "reVC"
|
||||||
includedirs { "src/audio" }
|
includedirs { "src/audio" }
|
||||||
includedirs { "src/audio/eax" }
|
includedirs { "src/audio/eax" }
|
||||||
includedirs { "src/audio/oal" }
|
includedirs { "src/audio/oal" }
|
||||||
|
includedirs { "src/collision" }
|
||||||
includedirs { "src/control" }
|
includedirs { "src/control" }
|
||||||
includedirs { "src/core" }
|
includedirs { "src/core" }
|
||||||
includedirs { "src/entities" }
|
includedirs { "src/entities" }
|
||||||
|
|
21
src/collision/ColBox.cpp
Normal file
21
src/collision/ColBox.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColBox.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
|
||||||
|
{
|
||||||
|
this->min = min;
|
||||||
|
this->max = max;
|
||||||
|
this->surface = surf;
|
||||||
|
this->piece = piece;
|
||||||
|
}
|
||||||
|
|
||||||
|
CColBox&
|
||||||
|
CColBox::operator=(const CColBox& other)
|
||||||
|
{
|
||||||
|
min = other.min;
|
||||||
|
max = other.max;
|
||||||
|
surface = other.surface;
|
||||||
|
piece = other.piece;
|
||||||
|
return *this;
|
||||||
|
}
|
22
src/collision/ColBox.h
Normal file
22
src/collision/ColBox.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SurfaceTable.h"
|
||||||
|
|
||||||
|
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 CColBox : public CBox
|
||||||
|
{
|
||||||
|
uint8 surface;
|
||||||
|
uint8 piece;
|
||||||
|
|
||||||
|
void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
|
||||||
|
using CBox::Set;
|
||||||
|
|
||||||
|
CColBox& operator=(const CColBox &other);
|
||||||
|
};
|
9
src/collision/ColLine.cpp
Normal file
9
src/collision/ColLine.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColLine.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
CColLine::Set(const CVector &p0, const CVector &p1)
|
||||||
|
{
|
||||||
|
this->p0 = p0;
|
||||||
|
this->p1 = p1;
|
||||||
|
}
|
14
src/collision/ColLine.h
Normal file
14
src/collision/ColLine.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct CColLine
|
||||||
|
{
|
||||||
|
// NB: this has to be compatible with two CVuVectors
|
||||||
|
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);
|
||||||
|
};
|
201
src/collision/ColModel.cpp
Normal file
201
src/collision/ColModel.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColModel.h"
|
||||||
|
#include "Collision.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "Pools.h"
|
||||||
|
|
||||||
|
CColModel::CColModel(void)
|
||||||
|
{
|
||||||
|
numSpheres = 0;
|
||||||
|
spheres = nil;
|
||||||
|
numLines = 0;
|
||||||
|
lines = nil;
|
||||||
|
numBoxes = 0;
|
||||||
|
boxes = nil;
|
||||||
|
numTriangles = 0;
|
||||||
|
vertices = nil;
|
||||||
|
triangles = nil;
|
||||||
|
trianglePlanes = nil;
|
||||||
|
level = LEVEL_GENERIC; // generic col slot
|
||||||
|
ownsCollisionVolumes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CColModel::~CColModel(void)
|
||||||
|
{
|
||||||
|
RemoveCollisionVolumes();
|
||||||
|
RemoveTrianglePlanes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
CColModel::operator new(size_t)
|
||||||
|
{
|
||||||
|
CColModel* node = CPools::GetColModelPool()->New();
|
||||||
|
assert(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::operator delete(void *p, size_t)
|
||||||
|
{
|
||||||
|
CPools::GetColModelPool()->Delete((CColModel*)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::RemoveCollisionVolumes(void)
|
||||||
|
{
|
||||||
|
if(ownsCollisionVolumes){
|
||||||
|
RwFree(spheres);
|
||||||
|
RwFree(lines);
|
||||||
|
RwFree(boxes);
|
||||||
|
RwFree(vertices);
|
||||||
|
RwFree(triangles);
|
||||||
|
CCollision::RemoveTrianglePlanes(this);
|
||||||
|
}
|
||||||
|
numSpheres = 0;
|
||||||
|
numLines = 0;
|
||||||
|
numBoxes = 0;
|
||||||
|
numTriangles = 0;
|
||||||
|
spheres = nil;
|
||||||
|
lines = nil;
|
||||||
|
boxes = nil;
|
||||||
|
vertices = nil;
|
||||||
|
triangles = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::CalculateTrianglePlanes(void)
|
||||||
|
{
|
||||||
|
// HACK: allocate space for one more element to stuff the link pointer into
|
||||||
|
trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
|
||||||
|
for(int i = 0; i < numTriangles; i++)
|
||||||
|
trianglePlanes[i].Set(vertices, triangles[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::RemoveTrianglePlanes(void)
|
||||||
|
{
|
||||||
|
RwFree(trianglePlanes);
|
||||||
|
trianglePlanes = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
|
||||||
|
{
|
||||||
|
assert(trianglePlanes);
|
||||||
|
*(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLink<CColModel*>*
|
||||||
|
CColModel::GetLinkPtr(void)
|
||||||
|
{
|
||||||
|
assert(trianglePlanes);
|
||||||
|
return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CColModel::GetTrianglePoint(CVector &v, int i) const
|
||||||
|
{
|
||||||
|
v = vertices[i].Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
CColModel&
|
||||||
|
CColModel::operator=(const CColModel &other)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int numVerts;
|
||||||
|
|
||||||
|
boundingSphere = other.boundingSphere;
|
||||||
|
boundingBox = other.boundingBox;
|
||||||
|
|
||||||
|
// copy spheres
|
||||||
|
if(other.numSpheres){
|
||||||
|
if(numSpheres != other.numSpheres){
|
||||||
|
numSpheres = other.numSpheres;
|
||||||
|
if(spheres)
|
||||||
|
RwFree(spheres);
|
||||||
|
spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
|
||||||
|
}
|
||||||
|
for(i = 0; i < numSpheres; i++)
|
||||||
|
spheres[i] = other.spheres[i];
|
||||||
|
}else{
|
||||||
|
numSpheres = 0;
|
||||||
|
if(spheres)
|
||||||
|
RwFree(spheres);
|
||||||
|
spheres = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy lines
|
||||||
|
if(other.numLines){
|
||||||
|
if(numLines != other.numLines){
|
||||||
|
numLines = other.numLines;
|
||||||
|
if(lines)
|
||||||
|
RwFree(lines);
|
||||||
|
lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
|
||||||
|
}
|
||||||
|
for(i = 0; i < numLines; i++)
|
||||||
|
lines[i] = other.lines[i];
|
||||||
|
}else{
|
||||||
|
numLines = 0;
|
||||||
|
if(lines)
|
||||||
|
RwFree(lines);
|
||||||
|
lines = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy boxes
|
||||||
|
if(other.numBoxes){
|
||||||
|
if(numBoxes != other.numBoxes){
|
||||||
|
numBoxes = other.numBoxes;
|
||||||
|
if(boxes)
|
||||||
|
RwFree(boxes);
|
||||||
|
boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
|
||||||
|
}
|
||||||
|
for(i = 0; i < numBoxes; i++)
|
||||||
|
boxes[i] = other.boxes[i];
|
||||||
|
}else{
|
||||||
|
numBoxes = 0;
|
||||||
|
if(boxes)
|
||||||
|
RwFree(boxes);
|
||||||
|
boxes = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy mesh
|
||||||
|
if(other.numTriangles){
|
||||||
|
// copy vertices
|
||||||
|
numVerts = 0;
|
||||||
|
for(i = 0; i < other.numTriangles; i++){
|
||||||
|
if(other.triangles[i].a > numVerts)
|
||||||
|
numVerts = other.triangles[i].a;
|
||||||
|
if(other.triangles[i].b > numVerts)
|
||||||
|
numVerts = other.triangles[i].b;
|
||||||
|
if(other.triangles[i].c > numVerts)
|
||||||
|
numVerts = other.triangles[i].c;
|
||||||
|
}
|
||||||
|
numVerts++;
|
||||||
|
if(vertices)
|
||||||
|
RwFree(vertices);
|
||||||
|
if(numVerts){
|
||||||
|
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
|
||||||
|
for(i = 0; i < numVerts; i++)
|
||||||
|
vertices[i] = other.vertices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy triangles
|
||||||
|
if(numTriangles != other.numTriangles){
|
||||||
|
numTriangles = other.numTriangles;
|
||||||
|
if(triangles)
|
||||||
|
RwFree(triangles);
|
||||||
|
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
|
||||||
|
}
|
||||||
|
for(i = 0; i < numTriangles; i++)
|
||||||
|
triangles[i] = other.triangles[i];
|
||||||
|
}else{
|
||||||
|
numTriangles = 0;
|
||||||
|
if(triangles)
|
||||||
|
RwFree(triangles);
|
||||||
|
triangles = nil;
|
||||||
|
if(vertices)
|
||||||
|
RwFree(vertices);
|
||||||
|
vertices = nil;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
39
src/collision/ColModel.h
Normal file
39
src/collision/ColModel.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "templates.h"
|
||||||
|
#include "ColBox.h"
|
||||||
|
#include "ColSphere.h"
|
||||||
|
#include "ColLine.h"
|
||||||
|
#include "ColPoint.h"
|
||||||
|
#include "ColTriangle.h"
|
||||||
|
|
||||||
|
struct CColModel
|
||||||
|
{
|
||||||
|
CSphere boundingSphere;
|
||||||
|
CBox boundingBox;
|
||||||
|
int16 numSpheres;
|
||||||
|
int16 numBoxes;
|
||||||
|
int16 numTriangles;
|
||||||
|
int8 numLines;
|
||||||
|
uint8 level; // colstore slot but probably still named level
|
||||||
|
bool ownsCollisionVolumes;
|
||||||
|
CColSphere *spheres;
|
||||||
|
CColLine *lines;
|
||||||
|
CColBox *boxes;
|
||||||
|
CompressedVector *vertices;
|
||||||
|
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;
|
||||||
|
|
||||||
|
void *operator new(size_t);
|
||||||
|
void operator delete(void *p, size_t);
|
||||||
|
CColModel& operator=(const CColModel& other);
|
||||||
|
};
|
16
src/collision/ColPoint.cpp
Normal file
16
src/collision/ColPoint.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColPoint.h"
|
||||||
|
|
||||||
|
CColPoint&
|
||||||
|
CColPoint::operator=(const CColPoint &other)
|
||||||
|
{
|
||||||
|
point = other.point;
|
||||||
|
normal = other.normal;
|
||||||
|
surfaceA = other.surfaceA;
|
||||||
|
pieceA = other.pieceA;
|
||||||
|
surfaceB = other.surfaceB;
|
||||||
|
pieceB = other.pieceB;
|
||||||
|
|
||||||
|
// no depth?
|
||||||
|
return *this;
|
||||||
|
}
|
34
src/collision/ColPoint.h
Normal file
34
src/collision/ColPoint.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
const CVector &GetNormal() { return normal; }
|
||||||
|
float GetDepth() { return depth; }
|
||||||
|
void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
|
||||||
|
this->depth = depth;
|
||||||
|
this->surfaceA = surfA;
|
||||||
|
this->pieceA = pieceA;
|
||||||
|
this->surfaceB = surfB;
|
||||||
|
this->pieceB = pieceB;
|
||||||
|
}
|
||||||
|
void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
|
||||||
|
this->surfaceA = surfA;
|
||||||
|
this->pieceA = pieceA;
|
||||||
|
this->surfaceB = surfB;
|
||||||
|
this->pieceB = pieceB;
|
||||||
|
}
|
||||||
|
|
||||||
|
CColPoint &operator=(const CColPoint &other);
|
||||||
|
};
|
||||||
|
|
27
src/collision/ColSphere.cpp
Normal file
27
src/collision/ColSphere.cpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColSphere.h"
|
||||||
|
#include "General.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
CColSphere::Set(float radius, const CVector ¢er, uint8 surf, uint8 piece)
|
||||||
|
{
|
||||||
|
this->radius = radius;
|
||||||
|
this->center = center;
|
||||||
|
this->surface = surf;
|
||||||
|
this->piece = piece;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit)
|
||||||
|
{
|
||||||
|
CVector distToCenter = from - center;
|
||||||
|
float distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius);
|
||||||
|
float root1, root2;
|
||||||
|
|
||||||
|
if (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
entry = from + dir * root1;
|
||||||
|
exit = from + dir * root2;
|
||||||
|
return true;
|
||||||
|
}
|
21
src/collision/ColSphere.h
Normal file
21
src/collision/ColSphere.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SurfaceTable.h"
|
||||||
|
|
||||||
|
struct CSphere
|
||||||
|
{
|
||||||
|
// NB: this has to be compatible with a CVuVector
|
||||||
|
CVector center;
|
||||||
|
float radius;
|
||||||
|
void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CColSphere : public CSphere
|
||||||
|
{
|
||||||
|
uint8 surface;
|
||||||
|
uint8 piece;
|
||||||
|
|
||||||
|
void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece);
|
||||||
|
bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
|
||||||
|
using CSphere::Set;
|
||||||
|
};
|
32
src/collision/ColTriangle.cpp
Normal file
32
src/collision/ColTriangle.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "ColTriangle.h"
|
||||||
|
|
||||||
|
#ifdef VU_COLLISION
|
||||||
|
void
|
||||||
|
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
|
||||||
|
{
|
||||||
|
CVector norm = CrossProduct(vc-va, vb-va);
|
||||||
|
norm.Normalise();
|
||||||
|
float d = DotProduct(norm, va);
|
||||||
|
normal.x = norm.x*4096.0f;
|
||||||
|
normal.y = norm.y*4096.0f;
|
||||||
|
normal.z = norm.z*4096.0f;
|
||||||
|
dist = d*128.0f;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
|
||||||
|
{
|
||||||
|
normal = CrossProduct(vc-va, vb-va);
|
||||||
|
normal.Normalise();
|
||||||
|
dist = DotProduct(normal, va);
|
||||||
|
CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
|
||||||
|
// find out largest component and its direction
|
||||||
|
if(an.x > an.y && an.x > an.z)
|
||||||
|
dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
|
||||||
|
else if(an.y > an.z)
|
||||||
|
dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
|
||||||
|
else
|
||||||
|
dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
|
||||||
|
}
|
||||||
|
#endif
|
77
src/collision/ColTriangle.h
Normal file
77
src/collision/ColTriangle.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CompressedVector.h"
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
DIR_X_POS,
|
||||||
|
DIR_X_NEG,
|
||||||
|
DIR_Y_POS,
|
||||||
|
DIR_Y_NEG,
|
||||||
|
DIR_Z_POS,
|
||||||
|
DIR_Z_NEG,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CColTriangle
|
||||||
|
{
|
||||||
|
uint16 a;
|
||||||
|
uint16 b;
|
||||||
|
uint16 c;
|
||||||
|
uint8 surface;
|
||||||
|
|
||||||
|
void Set(int a, int b, int c, uint8 surf)
|
||||||
|
{
|
||||||
|
this->a = a;
|
||||||
|
this->b = b;
|
||||||
|
this->c = c;
|
||||||
|
this->surface = surf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CColTrianglePlane
|
||||||
|
{
|
||||||
|
#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
|
||||||
|
CVector normal;
|
||||||
|
float dist;
|
||||||
|
uint8 dir;
|
||||||
|
|
||||||
|
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 = normal; }
|
||||||
|
float GetNormalX() const { return normal.x; }
|
||||||
|
float GetNormalY() const { return normal.y; }
|
||||||
|
float GetNormalZ() const { return normal.z; }
|
||||||
|
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
|
||||||
|
#endif
|
||||||
|
};
|
|
@ -26,303 +26,8 @@
|
||||||
|
|
||||||
//--MIAMI: file done
|
//--MIAMI: file done
|
||||||
|
|
||||||
|
|
||||||
// TODO: where do these go?
|
|
||||||
|
|
||||||
#ifdef VU_COLLISION
|
#ifdef VU_COLLISION
|
||||||
|
#include "VuCollision.h"
|
||||||
struct VuTriangle
|
|
||||||
{
|
|
||||||
// Compressed int16 but unpacked
|
|
||||||
#ifdef GTA_PS2
|
|
||||||
uint128 v0;
|
|
||||||
uint128 v1;
|
|
||||||
uint128 v2;
|
|
||||||
uint128 plane;
|
|
||||||
#else
|
|
||||||
int32 v0[4];
|
|
||||||
int32 v1[4];
|
|
||||||
int32 v2[4];
|
|
||||||
int32 plane[4];
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef GTA_PS2
|
|
||||||
static int16 vi01;
|
|
||||||
static CVuVector vf01;
|
|
||||||
static CVuVector vf02;
|
|
||||||
static CVuVector vf03;
|
|
||||||
|
|
||||||
CVuVector
|
|
||||||
DistanceBetweenSphereAndLine(const CVuVector ¢er, const CVuVector &p0, const CVuVector &line)
|
|
||||||
{
|
|
||||||
// center VF12
|
|
||||||
// p0 VF14
|
|
||||||
// line VF15
|
|
||||||
CVuVector ret; // VF16
|
|
||||||
CVuVector p1 = p0+line;
|
|
||||||
CVuVector dist0 = center - p0; // VF20
|
|
||||||
CVuVector dist1 = center - p1; // VF25
|
|
||||||
float lenSq = line.MagnitudeSqr(); // VF21
|
|
||||||
float distSq0 = dist0.MagnitudeSqr(); // VF22
|
|
||||||
float distSq1 = dist1.MagnitudeSqr();
|
|
||||||
float dot = DotProduct(dist0, line); // VF23
|
|
||||||
if(dot < 0.0f){
|
|
||||||
// not above line, closest to p0
|
|
||||||
ret = p0;
|
|
||||||
ret.w = distSq0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
float t = dot/lenSq; // param of nearest point on infinite line
|
|
||||||
if(t > 1.0f){
|
|
||||||
// not above line, closest to p1
|
|
||||||
ret = p1;
|
|
||||||
ret.w = distSq1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// closest to line
|
|
||||||
ret = p0 + line*t;
|
|
||||||
ret.w = (ret - center).MagnitudeSqr();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
inline int SignFlags(const CVector &v)
|
|
||||||
{
|
|
||||||
int f = 0;
|
|
||||||
if(v.x < 0.0f) f |= 1;
|
|
||||||
if(v.y < 0.0f) f |= 2;
|
|
||||||
if(v.z < 0.0f) f |= 4;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
|
|
||||||
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
|
|
||||||
const CVuVector &plane)
|
|
||||||
{
|
|
||||||
#ifdef GTA_PS2
|
|
||||||
__asm__ volatile (
|
|
||||||
".set noreorder\n"
|
|
||||||
"lqc2 vf12, 0x0(%0)\n"
|
|
||||||
"lqc2 vf13, 0x0(%1)\n"
|
|
||||||
"lqc2 vf14, 0x0(%2)\n"
|
|
||||||
"lqc2 vf15, 0x0(%3)\n"
|
|
||||||
"lqc2 vf16, 0x0(%4)\n"
|
|
||||||
"lqc2 vf17, 0x0(%5)\n"
|
|
||||||
"vcallms Vu0LineToTriangleCollisionStart\n"
|
|
||||||
".set reorder\n"
|
|
||||||
:
|
|
||||||
: "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
float dot0 = DotProduct(plane, p0);
|
|
||||||
float dot1 = DotProduct(plane, p1);
|
|
||||||
float dist0 = plane.w - dot0;
|
|
||||||
float dist1 = plane.w - dot1;
|
|
||||||
|
|
||||||
// if points are on the same side, no collision
|
|
||||||
if(dist0 * dist1 > 0.0f){
|
|
||||||
vi01 = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVuVector diff = p1 - p0;
|
|
||||||
float t = dist0/(dot1 - dot0);
|
|
||||||
CVuVector p = p0 + diff*t;
|
|
||||||
p.w = 0.0f;
|
|
||||||
vf01 = p;
|
|
||||||
vf03.x = t;
|
|
||||||
|
|
||||||
// Check if point is inside
|
|
||||||
CVector cross1 = CrossProduct(p-v0, v1-v0);
|
|
||||||
CVector cross2 = CrossProduct(p-v1, v2-v1);
|
|
||||||
CVector cross3 = CrossProduct(p-v2, v0-v2);
|
|
||||||
// Only check relevant directions
|
|
||||||
int flagmask = 0;
|
|
||||||
if(Abs(plane.x) > 0.5f) flagmask |= 1;
|
|
||||||
if(Abs(plane.y) > 0.5f) flagmask |= 2;
|
|
||||||
if(Abs(plane.z) > 0.5f) flagmask |= 4;
|
|
||||||
int flags1 = SignFlags(cross1) & flagmask;
|
|
||||||
int flags2 = SignFlags(cross2) & flagmask;
|
|
||||||
int flags3 = SignFlags(cross3) & flagmask;
|
|
||||||
// inside if on the same side of all edges
|
|
||||||
if(flags1 != flags2 || flags1 != flags3){
|
|
||||||
vi01 = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vi01 = 1;
|
|
||||||
vf02 = plane;
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
|
|
||||||
{
|
|
||||||
#ifdef GTA_PS2
|
|
||||||
__asm__ volatile (
|
|
||||||
".set noreorder\n"
|
|
||||||
"lqc2 vf12, 0x0(%0)\n"
|
|
||||||
"lqc2 vf13, 0x0(%1)\n"
|
|
||||||
"lqc2 vf14, 0x0(%2)\n"
|
|
||||||
"lqc2 vf15, 0x10(%2)\n"
|
|
||||||
"lqc2 vf16, 0x20(%2)\n"
|
|
||||||
"lqc2 vf17, 0x30(%2)\n"
|
|
||||||
"vcallms Vu0LineToTriangleCollisionCompressedStart\n"
|
|
||||||
".set reorder\n"
|
|
||||||
:
|
|
||||||
: "r" (&p0), "r" (&p1), "r" (&tri)
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
CVuVector v0, v1, v2, plane;
|
|
||||||
v0.x = tri.v0[0]/128.0f;
|
|
||||||
v0.y = tri.v0[1]/128.0f;
|
|
||||||
v0.z = tri.v0[2]/128.0f;
|
|
||||||
v0.w = tri.v0[3]/128.0f;
|
|
||||||
v1.x = tri.v1[0]/128.0f;
|
|
||||||
v1.y = tri.v1[1]/128.0f;
|
|
||||||
v1.z = tri.v1[2]/128.0f;
|
|
||||||
v1.w = tri.v1[3]/128.0f;
|
|
||||||
v2.x = tri.v2[0]/128.0f;
|
|
||||||
v2.y = tri.v2[1]/128.0f;
|
|
||||||
v2.z = tri.v2[2]/128.0f;
|
|
||||||
v2.w = tri.v2[3]/128.0f;
|
|
||||||
plane.x = tri.plane[0]/4096.0f;
|
|
||||||
plane.y = tri.plane[1]/4096.0f;
|
|
||||||
plane.z = tri.plane[2]/4096.0f;
|
|
||||||
plane.w = tri.plane[3]/128.0f;
|
|
||||||
LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
SphereToTriangleCollision(const CVuVector &sph,
|
|
||||||
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
|
|
||||||
const CVuVector &plane)
|
|
||||||
{
|
|
||||||
#ifdef GTA_PS2
|
|
||||||
__asm__ volatile (
|
|
||||||
".set noreorder\n"
|
|
||||||
"lqc2 vf12, 0x0(%0)\n"
|
|
||||||
"lqc2 vf14, 0x0(%1)\n"
|
|
||||||
"lqc2 vf15, 0x0(%2)\n"
|
|
||||||
"lqc2 vf16, 0x0(%3)\n"
|
|
||||||
"lqc2 vf17, 0x0(%4)\n"
|
|
||||||
"vcallms Vu0SphereToTriangleCollisionStart\n"
|
|
||||||
".set reorder\n"
|
|
||||||
:
|
|
||||||
: "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
float planedist = DotProduct(plane, sph) - plane.w; // VF02
|
|
||||||
if(Abs(planedist) > sph.w){
|
|
||||||
vi01 = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// point on plane
|
|
||||||
CVuVector p = sph - planedist*plane;
|
|
||||||
p.w = 0.0f;
|
|
||||||
vf01 = p;
|
|
||||||
planedist = Abs(planedist);
|
|
||||||
// edges
|
|
||||||
CVuVector v01 = v1 - v0;
|
|
||||||
CVuVector v12 = v2 - v1;
|
|
||||||
CVuVector v20 = v0 - v2;
|
|
||||||
// VU code calculates normal again for some weird reason...
|
|
||||||
// Check sides of point
|
|
||||||
CVector cross1 = CrossProduct(p-v0, v01);
|
|
||||||
CVector cross2 = CrossProduct(p-v1, v12);
|
|
||||||
CVector cross3 = CrossProduct(p-v2, v20);
|
|
||||||
// Only check relevant directions
|
|
||||||
int flagmask = 0;
|
|
||||||
if(Abs(plane.x) > 0.1f) flagmask |= 1;
|
|
||||||
if(Abs(plane.y) > 0.1f) flagmask |= 2;
|
|
||||||
if(Abs(plane.z) > 0.1f) flagmask |= 4;
|
|
||||||
int nflags = SignFlags(plane) & flagmask;
|
|
||||||
int flags1 = SignFlags(cross1) & flagmask;
|
|
||||||
int flags2 = SignFlags(cross2) & flagmask;
|
|
||||||
int flags3 = SignFlags(cross3) & flagmask;
|
|
||||||
int testcase = 0;
|
|
||||||
CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
|
|
||||||
if(flags1 == nflags){
|
|
||||||
closest += v2;
|
|
||||||
testcase++;
|
|
||||||
}
|
|
||||||
if(flags2 == nflags){
|
|
||||||
closest += v0;
|
|
||||||
testcase++;
|
|
||||||
}
|
|
||||||
if(flags3 == nflags){
|
|
||||||
closest += v1;
|
|
||||||
testcase++;
|
|
||||||
}
|
|
||||||
if(testcase == 3){
|
|
||||||
// inside triangle - dist to plane already checked
|
|
||||||
vf02 = plane;
|
|
||||||
vf02.w = vf03.x = planedist;
|
|
||||||
vi01 = 1;
|
|
||||||
}else if(testcase == 1){
|
|
||||||
// outside two sides - closest to point opposide inside edge
|
|
||||||
vf01 = closest;
|
|
||||||
vf02 = sph - closest;
|
|
||||||
float distSq = vf02.MagnitudeSqr();
|
|
||||||
vi01 = sph.w*sph.w > distSq;
|
|
||||||
vf03.x = Sqrt(distSq);
|
|
||||||
vf02 *= 1.0f/vf03.x;
|
|
||||||
}else{
|
|
||||||
// inside two sides - closest to third edge
|
|
||||||
if(flags1 != nflags)
|
|
||||||
closest = DistanceBetweenSphereAndLine(sph, v0, v01);
|
|
||||||
else if(flags2 != nflags)
|
|
||||||
closest = DistanceBetweenSphereAndLine(sph, v1, v12);
|
|
||||||
else
|
|
||||||
closest = DistanceBetweenSphereAndLine(sph, v2, v20);
|
|
||||||
vi01 = sph.w*sph.w > closest.w;
|
|
||||||
vf01 = closest;
|
|
||||||
vf02 = sph - closest;
|
|
||||||
vf03.x = Sqrt(closest.w);
|
|
||||||
vf02 *= 1.0f/vf03.x;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
|
|
||||||
{
|
|
||||||
#ifdef GTA_PS2
|
|
||||||
__asm__ volatile (
|
|
||||||
".set noreorder\n"
|
|
||||||
"lqc2 vf12, 0x0(%0)\n"
|
|
||||||
"lqc2 vf14, 0x0(%1)\n"
|
|
||||||
"lqc2 vf15, 0x10(%1)\n"
|
|
||||||
"lqc2 vf16, 0x20(%1)\n"
|
|
||||||
"lqc2 vf17, 0x30(%1)\n"
|
|
||||||
"vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
|
|
||||||
".set reorder\n"
|
|
||||||
:
|
|
||||||
: "r" (&sph), "r" (&tri)
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
CVuVector v0, v1, v2, plane;
|
|
||||||
v0.x = tri.v0[0]/128.0f;
|
|
||||||
v0.y = tri.v0[1]/128.0f;
|
|
||||||
v0.z = tri.v0[2]/128.0f;
|
|
||||||
v0.w = tri.v0[3]/128.0f;
|
|
||||||
v1.x = tri.v1[0]/128.0f;
|
|
||||||
v1.y = tri.v1[1]/128.0f;
|
|
||||||
v1.z = tri.v1[2]/128.0f;
|
|
||||||
v1.w = tri.v1[3]/128.0f;
|
|
||||||
v2.x = tri.v2[0]/128.0f;
|
|
||||||
v2.y = tri.v2[1]/128.0f;
|
|
||||||
v2.z = tri.v2[2]/128.0f;
|
|
||||||
v2.w = tri.v2[3]/128.0f;
|
|
||||||
plane.x = tri.plane[0]/4096.0f;
|
|
||||||
plane.y = tri.plane[1]/4096.0f;
|
|
||||||
plane.z = tri.plane[2]/4096.0f;
|
|
||||||
plane.w = tri.plane[3]/128.0f;
|
|
||||||
SphereToTriangleCollision(sph, v0, v1, v2, plane);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
GetVUresult(void)
|
GetVUresult(void)
|
||||||
|
@ -365,17 +70,6 @@ GetVUresult(CVuVector &point, CVuVector &normal, float &dist)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
enum Direction
|
|
||||||
{
|
|
||||||
DIR_X_POS,
|
|
||||||
DIR_X_NEG,
|
|
||||||
DIR_Y_POS,
|
|
||||||
DIR_Y_NEG,
|
|
||||||
DIR_Z_POS,
|
|
||||||
DIR_Z_NEG,
|
|
||||||
};
|
|
||||||
|
|
||||||
eLevelName CCollision::ms_collisionInMemory;
|
eLevelName CCollision::ms_collisionInMemory;
|
||||||
CLinkList<CColModel*> CCollision::ms_colModelCache;
|
CLinkList<CColModel*> CCollision::ms_colModelCache;
|
||||||
|
|
||||||
|
@ -2261,11 +1955,12 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||||
assert(modelA.numLines <= MAXNUMLINES);
|
assert(modelA.numLines <= MAXNUMLINES);
|
||||||
|
|
||||||
// From model A space to model B space
|
// From model A space to model B space
|
||||||
Invert(matrixB, matAB);
|
matAB = Invert(matrixB, matAB);
|
||||||
matAB *= matrixA;
|
matAB *= matrixA;
|
||||||
|
|
||||||
CColSphere bsphereAB; // bounding sphere of A in B space
|
CColSphere bsphereAB; // bounding sphere of A in B space
|
||||||
bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center);
|
bsphereAB.radius = modelA.boundingSphere.radius;
|
||||||
|
bsphereAB.center = matAB * modelA.boundingSphere.center;
|
||||||
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
|
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
|
||||||
return 0;
|
return 0;
|
||||||
// B to A space
|
// B to A space
|
||||||
|
@ -2298,7 +1993,8 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
|
||||||
int numBoxesB = 0;
|
int numBoxesB = 0;
|
||||||
int numTrianglesB = 0;
|
int numTrianglesB = 0;
|
||||||
for(i = 0; i < modelB.numSpheres; i++){
|
for(i = 0; i < modelB.numSpheres; i++){
|
||||||
s.Set(modelB.spheres[i].radius, matBA * modelB.spheres[i].center);
|
s.radius = modelB.spheres[i].radius;
|
||||||
|
s.center = matBA * modelB.spheres[i].center;
|
||||||
if(TestSphereBox(s, modelA.boundingBox))
|
if(TestSphereBox(s, modelA.boundingBox))
|
||||||
aSphereIndicesB[numSpheresB++] = i;
|
aSphereIndicesB[numSpheresB++] = i;
|
||||||
}
|
}
|
||||||
|
@ -2871,294 +2567,3 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
|
||||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
||||||
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
|
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ColModel code
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
CColSphere::Set(float radius, const CVector ¢er, uint8 surf, uint8 piece)
|
|
||||||
{
|
|
||||||
this->radius = radius;
|
|
||||||
this->center = center;
|
|
||||||
this->surface = surf;
|
|
||||||
this->piece = piece;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit)
|
|
||||||
{
|
|
||||||
CVector distToCenter = from - center;
|
|
||||||
float distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius);
|
|
||||||
float root1, root2;
|
|
||||||
|
|
||||||
if (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
entry = from + dir * root1;
|
|
||||||
exit = from + dir * root2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
|
|
||||||
{
|
|
||||||
this->min = min;
|
|
||||||
this->max = max;
|
|
||||||
this->surface = surf;
|
|
||||||
this->piece = piece;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColLine::Set(const CVector &p0, const CVector &p1)
|
|
||||||
{
|
|
||||||
this->p0 = p0;
|
|
||||||
this->p1 = p1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
|
|
||||||
{
|
|
||||||
this->a = a;
|
|
||||||
this->b = b;
|
|
||||||
this->c = c;
|
|
||||||
this->surface = surf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VU_COLLISION
|
|
||||||
void
|
|
||||||
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
|
|
||||||
{
|
|
||||||
CVector norm = CrossProduct(vc-va, vb-va);
|
|
||||||
norm.Normalise();
|
|
||||||
float d = DotProduct(norm, va);
|
|
||||||
normal.x = norm.x*4096.0f;
|
|
||||||
normal.y = norm.y*4096.0f;
|
|
||||||
normal.z = norm.z*4096.0f;
|
|
||||||
dist = d*128.0f;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
|
|
||||||
{
|
|
||||||
normal = CrossProduct(vc-va, vb-va);
|
|
||||||
normal.Normalise();
|
|
||||||
dist = DotProduct(normal, va);
|
|
||||||
CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
|
|
||||||
// find out largest component and its direction
|
|
||||||
if(an.x > an.y && an.x > an.z)
|
|
||||||
dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
|
|
||||||
else if(an.y > an.z)
|
|
||||||
dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
|
|
||||||
else
|
|
||||||
dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CColPoint&
|
|
||||||
CColPoint::operator=(const CColPoint& other)
|
|
||||||
{
|
|
||||||
point = other.point;
|
|
||||||
normal = other.normal;
|
|
||||||
surfaceA = other.surfaceA;
|
|
||||||
pieceA = other.pieceA;
|
|
||||||
surfaceB = other.surfaceB;
|
|
||||||
pieceB = other.pieceB;
|
|
||||||
// doesn't copy depth
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CColModel::CColModel(void)
|
|
||||||
{
|
|
||||||
numSpheres = 0;
|
|
||||||
spheres = nil;
|
|
||||||
numLines = 0;
|
|
||||||
lines = nil;
|
|
||||||
numBoxes = 0;
|
|
||||||
boxes = nil;
|
|
||||||
numTriangles = 0;
|
|
||||||
vertices = nil;
|
|
||||||
triangles = nil;
|
|
||||||
trianglePlanes = nil;
|
|
||||||
level = 0; // generic col slot
|
|
||||||
ownsCollisionVolumes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CColModel::~CColModel(void)
|
|
||||||
{
|
|
||||||
RemoveCollisionVolumes();
|
|
||||||
RemoveTrianglePlanes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::RemoveCollisionVolumes(void)
|
|
||||||
{
|
|
||||||
if(ownsCollisionVolumes){
|
|
||||||
RwFree(spheres);
|
|
||||||
RwFree(lines);
|
|
||||||
RwFree(boxes);
|
|
||||||
RwFree(vertices);
|
|
||||||
RwFree(triangles);
|
|
||||||
CCollision::RemoveTrianglePlanes(this);
|
|
||||||
}
|
|
||||||
numSpheres = 0;
|
|
||||||
numLines = 0;
|
|
||||||
numBoxes = 0;
|
|
||||||
numTriangles = 0;
|
|
||||||
spheres = nil;
|
|
||||||
lines = nil;
|
|
||||||
boxes = nil;
|
|
||||||
vertices = nil;
|
|
||||||
triangles = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::CalculateTrianglePlanes(void)
|
|
||||||
{
|
|
||||||
// HACK: allocate space for one more element to stuff the link pointer into
|
|
||||||
trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
|
|
||||||
for(int i = 0; i < numTriangles; i++)
|
|
||||||
trianglePlanes[i].Set(vertices, triangles[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::RemoveTrianglePlanes(void)
|
|
||||||
{
|
|
||||||
RwFree(trianglePlanes);
|
|
||||||
trianglePlanes = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
|
|
||||||
{
|
|
||||||
assert(trianglePlanes);
|
|
||||||
*(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLink<CColModel*>*
|
|
||||||
CColModel::GetLinkPtr(void)
|
|
||||||
{
|
|
||||||
assert(trianglePlanes);
|
|
||||||
return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::GetTrianglePoint(CVector &v, int i) const
|
|
||||||
{
|
|
||||||
v = vertices[i].Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
CColModel::operator new(size_t){
|
|
||||||
CColModel *node = CPools::GetColModelPool()->New();
|
|
||||||
assert(node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CColModel::operator delete(void *p, size_t){
|
|
||||||
CPools::GetColModelPool()->Delete((CColModel*)p);
|
|
||||||
}
|
|
||||||
|
|
||||||
CColModel&
|
|
||||||
CColModel::operator=(const CColModel &other)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int numVerts;
|
|
||||||
|
|
||||||
boundingSphere = other.boundingSphere;
|
|
||||||
boundingBox = other.boundingBox;
|
|
||||||
|
|
||||||
// copy spheres
|
|
||||||
if(other.numSpheres){
|
|
||||||
if(numSpheres != other.numSpheres){
|
|
||||||
numSpheres = other.numSpheres;
|
|
||||||
if(spheres)
|
|
||||||
RwFree(spheres);
|
|
||||||
spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
|
|
||||||
}
|
|
||||||
for(i = 0; i < numSpheres; i++)
|
|
||||||
spheres[i] = other.spheres[i];
|
|
||||||
}else{
|
|
||||||
numSpheres = 0;
|
|
||||||
if(spheres)
|
|
||||||
RwFree(spheres);
|
|
||||||
spheres = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy lines
|
|
||||||
if(other.numLines){
|
|
||||||
if(numLines != other.numLines){
|
|
||||||
numLines = other.numLines;
|
|
||||||
if(lines)
|
|
||||||
RwFree(lines);
|
|
||||||
lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
|
|
||||||
}
|
|
||||||
for(i = 0; i < numLines; i++)
|
|
||||||
lines[i] = other.lines[i];
|
|
||||||
}else{
|
|
||||||
numLines = 0;
|
|
||||||
if(lines)
|
|
||||||
RwFree(lines);
|
|
||||||
lines = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy boxes
|
|
||||||
if(other.numBoxes){
|
|
||||||
if(numBoxes != other.numBoxes){
|
|
||||||
numBoxes = other.numBoxes;
|
|
||||||
if(boxes)
|
|
||||||
RwFree(boxes);
|
|
||||||
boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
|
|
||||||
}
|
|
||||||
for(i = 0; i < numBoxes; i++)
|
|
||||||
boxes[i] = other.boxes[i];
|
|
||||||
}else{
|
|
||||||
numBoxes = 0;
|
|
||||||
if(boxes)
|
|
||||||
RwFree(boxes);
|
|
||||||
boxes = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy mesh
|
|
||||||
if(other.numTriangles){
|
|
||||||
// copy vertices
|
|
||||||
numVerts = 0;
|
|
||||||
for(i = 0; i < other.numTriangles; i++){
|
|
||||||
if(other.triangles[i].a > numVerts)
|
|
||||||
numVerts = other.triangles[i].a;
|
|
||||||
if(other.triangles[i].b > numVerts)
|
|
||||||
numVerts = other.triangles[i].b;
|
|
||||||
if(other.triangles[i].c > numVerts)
|
|
||||||
numVerts = other.triangles[i].c;
|
|
||||||
}
|
|
||||||
numVerts++;
|
|
||||||
if(vertices)
|
|
||||||
RwFree(vertices);
|
|
||||||
if(numVerts){
|
|
||||||
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
|
|
||||||
for(i = 0; i < numVerts; i++)
|
|
||||||
vertices[i] = other.vertices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy triangles
|
|
||||||
if(numTriangles != other.numTriangles){
|
|
||||||
numTriangles = other.numTriangles;
|
|
||||||
if(triangles)
|
|
||||||
RwFree(triangles);
|
|
||||||
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
|
|
||||||
}
|
|
||||||
for(i = 0; i < numTriangles; i++)
|
|
||||||
triangles[i] = other.triangles[i];
|
|
||||||
}else{
|
|
||||||
numTriangles = 0;
|
|
||||||
if(triangles)
|
|
||||||
RwFree(triangles);
|
|
||||||
triangles = nil;
|
|
||||||
if(vertices)
|
|
||||||
RwFree(vertices);
|
|
||||||
vertices = nil;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
68
src/collision/Collision.h
Normal file
68
src/collision/Collision.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ColModel.h"
|
||||||
|
#include "Game.h" // for eLevelName
|
||||||
|
#ifdef VU_COLLISION
|
||||||
|
#include "VuVector.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct CStoredCollPoly
|
||||||
|
{
|
||||||
|
#ifdef VU_COLLISION
|
||||||
|
CVuVector verts[3];
|
||||||
|
#else
|
||||||
|
CVector verts[3];
|
||||||
|
#endif
|
||||||
|
bool valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
|
||||||
|
#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
|
||||||
|
#define MAX_COLLISION_POINTS 64
|
||||||
|
#else
|
||||||
|
#define MAX_COLLISION_POINTS 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CCollision
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static eLevelName ms_collisionInMemory;
|
||||||
|
static CLinkList<CColModel*> ms_colModelCache;
|
||||||
|
|
||||||
|
static void Init(void);
|
||||||
|
static void Shutdown(void);
|
||||||
|
static void Update(void);
|
||||||
|
static void LoadCollisionWhenINeedIt(bool changeLevel);
|
||||||
|
static void SortOutCollisionAfterLoad(void);
|
||||||
|
static void LoadCollisionScreen(eLevelName level);
|
||||||
|
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);
|
||||||
|
static void RemoveTrianglePlanes(CColModel *model);
|
||||||
|
|
||||||
|
// all these return true if there's a collision
|
||||||
|
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);
|
||||||
|
static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
||||||
|
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
|
||||||
|
static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
||||||
|
static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
|
||||||
|
static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
|
||||||
|
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);
|
||||||
|
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
|
||||||
|
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
36
src/collision/CompressedVector.h
Normal file
36
src/collision/CompressedVector.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
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; };
|
||||||
|
#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
|
||||||
|
#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
|
||||||
|
};
|
|
@ -1,7 +1,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include "TempColModels.h"
|
#include "TempColModels.h"
|
||||||
#include "SurfaceTable.h"
|
|
||||||
|
|
||||||
CColModel CTempColModels::ms_colModelPed1;
|
CColModel CTempColModels::ms_colModelPed1;
|
||||||
CColModel CTempColModels::ms_colModelPed2;
|
CColModel CTempColModels::ms_colModelPed2;
|
282
src/collision/VuCollision.cpp
Normal file
282
src/collision/VuCollision.cpp
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
#include "common.h"
|
||||||
|
#ifdef VU_COLLISION
|
||||||
|
#include "VuVector.h"
|
||||||
|
#include "VuCollision.h"
|
||||||
|
|
||||||
|
#ifndef GTA_PS2
|
||||||
|
int16 vi01;
|
||||||
|
CVuVector vf01;
|
||||||
|
CVuVector vf02;
|
||||||
|
CVuVector vf03;
|
||||||
|
|
||||||
|
CVuVector
|
||||||
|
DistanceBetweenSphereAndLine(const CVuVector ¢er, const CVuVector &p0, const CVuVector &line)
|
||||||
|
{
|
||||||
|
// center VF12
|
||||||
|
// p0 VF14
|
||||||
|
// line VF15
|
||||||
|
CVuVector ret; // VF16
|
||||||
|
CVuVector p1 = p0+line;
|
||||||
|
CVuVector dist0 = center - p0; // VF20
|
||||||
|
CVuVector dist1 = center - p1; // VF25
|
||||||
|
float lenSq = line.MagnitudeSqr(); // VF21
|
||||||
|
float distSq0 = dist0.MagnitudeSqr(); // VF22
|
||||||
|
float distSq1 = dist1.MagnitudeSqr();
|
||||||
|
float dot = DotProduct(dist0, line); // VF23
|
||||||
|
if(dot < 0.0f){
|
||||||
|
// not above line, closest to p0
|
||||||
|
ret = p0;
|
||||||
|
ret.w = distSq0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
float t = dot/lenSq; // param of nearest point on infinite line
|
||||||
|
if(t > 1.0f){
|
||||||
|
// not above line, closest to p1
|
||||||
|
ret = p1;
|
||||||
|
ret.w = distSq1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// closest to line
|
||||||
|
ret = p0 + line*t;
|
||||||
|
ret.w = (ret - center).MagnitudeSqr();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
inline int SignFlags(const CVector &v)
|
||||||
|
{
|
||||||
|
int f = 0;
|
||||||
|
if(v.x < 0.0f) f |= 1;
|
||||||
|
if(v.y < 0.0f) f |= 2;
|
||||||
|
if(v.z < 0.0f) f |= 4;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
|
||||||
|
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
|
||||||
|
const CVuVector &plane)
|
||||||
|
{
|
||||||
|
#ifdef GTA_PS2
|
||||||
|
__asm__ volatile (
|
||||||
|
".set noreorder\n"
|
||||||
|
"lqc2 vf12, 0x0(%0)\n"
|
||||||
|
"lqc2 vf13, 0x0(%1)\n"
|
||||||
|
"lqc2 vf14, 0x0(%2)\n"
|
||||||
|
"lqc2 vf15, 0x0(%3)\n"
|
||||||
|
"lqc2 vf16, 0x0(%4)\n"
|
||||||
|
"lqc2 vf17, 0x0(%5)\n"
|
||||||
|
"vcallms Vu0LineToTriangleCollisionStart\n"
|
||||||
|
".set reorder\n"
|
||||||
|
:
|
||||||
|
: "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
float dot0 = DotProduct(plane, p0);
|
||||||
|
float dot1 = DotProduct(plane, p1);
|
||||||
|
float dist0 = plane.w - dot0;
|
||||||
|
float dist1 = plane.w - dot1;
|
||||||
|
|
||||||
|
// if points are on the same side, no collision
|
||||||
|
if(dist0 * dist1 > 0.0f){
|
||||||
|
vi01 = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVuVector diff = p1 - p0;
|
||||||
|
float t = dist0/(dot1 - dot0);
|
||||||
|
CVuVector p = p0 + diff*t;
|
||||||
|
p.w = 0.0f;
|
||||||
|
vf01 = p;
|
||||||
|
vf03.x = t;
|
||||||
|
|
||||||
|
// Check if point is inside
|
||||||
|
CVector cross1 = CrossProduct(p-v0, v1-v0);
|
||||||
|
CVector cross2 = CrossProduct(p-v1, v2-v1);
|
||||||
|
CVector cross3 = CrossProduct(p-v2, v0-v2);
|
||||||
|
// Only check relevant directions
|
||||||
|
int flagmask = 0;
|
||||||
|
if(Abs(plane.x) > 0.5f) flagmask |= 1;
|
||||||
|
if(Abs(plane.y) > 0.5f) flagmask |= 2;
|
||||||
|
if(Abs(plane.z) > 0.5f) flagmask |= 4;
|
||||||
|
int flags1 = SignFlags(cross1) & flagmask;
|
||||||
|
int flags2 = SignFlags(cross2) & flagmask;
|
||||||
|
int flags3 = SignFlags(cross3) & flagmask;
|
||||||
|
// inside if on the same side of all edges
|
||||||
|
if(flags1 != flags2 || flags1 != flags3){
|
||||||
|
vi01 = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vi01 = 1;
|
||||||
|
vf02 = plane;
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
|
||||||
|
{
|
||||||
|
#ifdef GTA_PS2
|
||||||
|
__asm__ volatile (
|
||||||
|
".set noreorder\n"
|
||||||
|
"lqc2 vf12, 0x0(%0)\n"
|
||||||
|
"lqc2 vf13, 0x0(%1)\n"
|
||||||
|
"lqc2 vf14, 0x0(%2)\n"
|
||||||
|
"lqc2 vf15, 0x10(%2)\n"
|
||||||
|
"lqc2 vf16, 0x20(%2)\n"
|
||||||
|
"lqc2 vf17, 0x30(%2)\n"
|
||||||
|
"vcallms Vu0LineToTriangleCollisionCompressedStart\n"
|
||||||
|
".set reorder\n"
|
||||||
|
:
|
||||||
|
: "r" (&p0), "r" (&p1), "r" (&tri)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
CVuVector v0, v1, v2, plane;
|
||||||
|
v0.x = tri.v0[0]/128.0f;
|
||||||
|
v0.y = tri.v0[1]/128.0f;
|
||||||
|
v0.z = tri.v0[2]/128.0f;
|
||||||
|
v0.w = tri.v0[3]/128.0f;
|
||||||
|
v1.x = tri.v1[0]/128.0f;
|
||||||
|
v1.y = tri.v1[1]/128.0f;
|
||||||
|
v1.z = tri.v1[2]/128.0f;
|
||||||
|
v1.w = tri.v1[3]/128.0f;
|
||||||
|
v2.x = tri.v2[0]/128.0f;
|
||||||
|
v2.y = tri.v2[1]/128.0f;
|
||||||
|
v2.z = tri.v2[2]/128.0f;
|
||||||
|
v2.w = tri.v2[3]/128.0f;
|
||||||
|
plane.x = tri.plane[0]/4096.0f;
|
||||||
|
plane.y = tri.plane[1]/4096.0f;
|
||||||
|
plane.z = tri.plane[2]/4096.0f;
|
||||||
|
plane.w = tri.plane[3]/128.0f;
|
||||||
|
LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
SphereToTriangleCollision(const CVuVector &sph,
|
||||||
|
const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
|
||||||
|
const CVuVector &plane)
|
||||||
|
{
|
||||||
|
#ifdef GTA_PS2
|
||||||
|
__asm__ volatile (
|
||||||
|
".set noreorder\n"
|
||||||
|
"lqc2 vf12, 0x0(%0)\n"
|
||||||
|
"lqc2 vf14, 0x0(%1)\n"
|
||||||
|
"lqc2 vf15, 0x0(%2)\n"
|
||||||
|
"lqc2 vf16, 0x0(%3)\n"
|
||||||
|
"lqc2 vf17, 0x0(%4)\n"
|
||||||
|
"vcallms Vu0SphereToTriangleCollisionStart\n"
|
||||||
|
".set reorder\n"
|
||||||
|
:
|
||||||
|
: "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
float planedist = DotProduct(plane, sph) - plane.w; // VF02
|
||||||
|
if(Abs(planedist) > sph.w){
|
||||||
|
vi01 = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// point on plane
|
||||||
|
CVuVector p = sph - planedist*plane;
|
||||||
|
p.w = 0.0f;
|
||||||
|
vf01 = p;
|
||||||
|
planedist = Abs(planedist);
|
||||||
|
// edges
|
||||||
|
CVuVector v01 = v1 - v0;
|
||||||
|
CVuVector v12 = v2 - v1;
|
||||||
|
CVuVector v20 = v0 - v2;
|
||||||
|
// VU code calculates normal again for some weird reason...
|
||||||
|
// Check sides of point
|
||||||
|
CVector cross1 = CrossProduct(p-v0, v01);
|
||||||
|
CVector cross2 = CrossProduct(p-v1, v12);
|
||||||
|
CVector cross3 = CrossProduct(p-v2, v20);
|
||||||
|
// Only check relevant directions
|
||||||
|
int flagmask = 0;
|
||||||
|
if(Abs(plane.x) > 0.1f) flagmask |= 1;
|
||||||
|
if(Abs(plane.y) > 0.1f) flagmask |= 2;
|
||||||
|
if(Abs(plane.z) > 0.1f) flagmask |= 4;
|
||||||
|
int nflags = SignFlags(plane) & flagmask;
|
||||||
|
int flags1 = SignFlags(cross1) & flagmask;
|
||||||
|
int flags2 = SignFlags(cross2) & flagmask;
|
||||||
|
int flags3 = SignFlags(cross3) & flagmask;
|
||||||
|
int testcase = 0;
|
||||||
|
CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
|
||||||
|
if(flags1 == nflags){
|
||||||
|
closest += v2;
|
||||||
|
testcase++;
|
||||||
|
}
|
||||||
|
if(flags2 == nflags){
|
||||||
|
closest += v0;
|
||||||
|
testcase++;
|
||||||
|
}
|
||||||
|
if(flags3 == nflags){
|
||||||
|
closest += v1;
|
||||||
|
testcase++;
|
||||||
|
}
|
||||||
|
if(testcase == 3){
|
||||||
|
// inside triangle - dist to plane already checked
|
||||||
|
vf02 = plane;
|
||||||
|
vf02.w = vf03.x = planedist;
|
||||||
|
vi01 = 1;
|
||||||
|
}else if(testcase == 1){
|
||||||
|
// outside two sides - closest to point opposide inside edge
|
||||||
|
vf01 = closest;
|
||||||
|
vf02 = sph - closest;
|
||||||
|
float distSq = vf02.MagnitudeSqr();
|
||||||
|
vi01 = sph.w*sph.w > distSq;
|
||||||
|
vf03.x = Sqrt(distSq);
|
||||||
|
vf02 *= 1.0f/vf03.x;
|
||||||
|
}else{
|
||||||
|
// inside two sides - closest to third edge
|
||||||
|
if(flags1 != nflags)
|
||||||
|
closest = DistanceBetweenSphereAndLine(sph, v0, v01);
|
||||||
|
else if(flags2 != nflags)
|
||||||
|
closest = DistanceBetweenSphereAndLine(sph, v1, v12);
|
||||||
|
else
|
||||||
|
closest = DistanceBetweenSphereAndLine(sph, v2, v20);
|
||||||
|
vi01 = sph.w*sph.w > closest.w;
|
||||||
|
vf01 = closest;
|
||||||
|
vf02 = sph - closest;
|
||||||
|
vf03.x = Sqrt(closest.w);
|
||||||
|
vf02 *= 1.0f/vf03.x;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
|
||||||
|
{
|
||||||
|
#ifdef GTA_PS2
|
||||||
|
__asm__ volatile (
|
||||||
|
".set noreorder\n"
|
||||||
|
"lqc2 vf12, 0x0(%0)\n"
|
||||||
|
"lqc2 vf14, 0x0(%1)\n"
|
||||||
|
"lqc2 vf15, 0x10(%1)\n"
|
||||||
|
"lqc2 vf16, 0x20(%1)\n"
|
||||||
|
"lqc2 vf17, 0x30(%1)\n"
|
||||||
|
"vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
|
||||||
|
".set reorder\n"
|
||||||
|
:
|
||||||
|
: "r" (&sph), "r" (&tri)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
CVuVector v0, v1, v2, plane;
|
||||||
|
v0.x = tri.v0[0]/128.0f;
|
||||||
|
v0.y = tri.v0[1]/128.0f;
|
||||||
|
v0.z = tri.v0[2]/128.0f;
|
||||||
|
v0.w = tri.v0[3]/128.0f;
|
||||||
|
v1.x = tri.v1[0]/128.0f;
|
||||||
|
v1.y = tri.v1[1]/128.0f;
|
||||||
|
v1.z = tri.v1[2]/128.0f;
|
||||||
|
v1.w = tri.v1[3]/128.0f;
|
||||||
|
v2.x = tri.v2[0]/128.0f;
|
||||||
|
v2.y = tri.v2[1]/128.0f;
|
||||||
|
v2.z = tri.v2[2]/128.0f;
|
||||||
|
v2.w = tri.v2[3]/128.0f;
|
||||||
|
plane.x = tri.plane[0]/4096.0f;
|
||||||
|
plane.y = tri.plane[1]/4096.0f;
|
||||||
|
plane.z = tri.plane[2]/4096.0f;
|
||||||
|
plane.w = tri.plane[3]/128.0f;
|
||||||
|
SphereToTriangleCollision(sph, v0, v1, v2, plane);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
32
src/collision/VuCollision.h
Normal file
32
src/collision/VuCollision.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
struct VuTriangle
|
||||||
|
{
|
||||||
|
// Compressed int16 but unpacked
|
||||||
|
#ifdef GTA_PS2
|
||||||
|
uint128 v0;
|
||||||
|
uint128 v1;
|
||||||
|
uint128 v2;
|
||||||
|
uint128 plane;
|
||||||
|
#else
|
||||||
|
int32 v0[4];
|
||||||
|
int32 v1[4];
|
||||||
|
int32 v2[4];
|
||||||
|
int32 plane[4];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef GTA_PS2
|
||||||
|
extern int16 vi01;
|
||||||
|
extern CVuVector vf01;
|
||||||
|
extern CVuVector vf02;
|
||||||
|
extern CVuVector vf03;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
|
||||||
|
void LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri);
|
||||||
|
void SphereToTriangleCollision(const CVuVector &sph, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);
|
||||||
|
void SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri);
|
||||||
|
}
|
|
@ -2148,8 +2148,9 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
|
||||||
pVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,
|
pVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,
|
||||||
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,
|
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,
|
||||||
pVehicle, nil, 999999.9f, -1);
|
pVehicle, nil, 999999.9f, -1);
|
||||||
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 1)
|
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2)
|
||||||
return true;
|
return true;
|
||||||
|
pVehicle->AutoPilot.RemoveOnePathNode();
|
||||||
}
|
}
|
||||||
CPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
|
CPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
|
||||||
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
||||||
|
|
|
@ -1,257 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "templates.h"
|
|
||||||
#include "Game.h" // for eLevelName
|
|
||||||
#ifdef VU_COLLISION
|
|
||||||
#include "VuVector.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
|
|
||||||
#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
|
|
||||||
#define MAX_COLLISION_POINTS 64
|
|
||||||
#else
|
|
||||||
#define MAX_COLLISION_POINTS 32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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; };
|
|
||||||
#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
|
|
||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CSphere
|
|
||||||
{
|
|
||||||
// NB: this has to be compatible with a CVuVector
|
|
||||||
CVector center;
|
|
||||||
float radius;
|
|
||||||
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
|
|
||||||
{
|
|
||||||
uint8 surface;
|
|
||||||
uint8 piece;
|
|
||||||
|
|
||||||
void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece);
|
|
||||||
bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
|
|
||||||
using CSphere::Set;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CColBox : public CBox
|
|
||||||
{
|
|
||||||
uint8 surface;
|
|
||||||
uint8 piece;
|
|
||||||
|
|
||||||
void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
|
|
||||||
using CBox::Set;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CColLine
|
|
||||||
{
|
|
||||||
// NB: this has to be compatible with two CVuVectors
|
|
||||||
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;
|
|
||||||
|
|
||||||
void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CColTrianglePlane
|
|
||||||
{
|
|
||||||
#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
|
|
||||||
CVector normal;
|
|
||||||
float dist;
|
|
||||||
uint8 dir;
|
|
||||||
|
|
||||||
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 = normal; }
|
|
||||||
float GetNormalX() const { return normal.x; }
|
|
||||||
float GetNormalY() const { return normal.y; }
|
|
||||||
float GetNormalZ() const { return normal.z; }
|
|
||||||
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
CColPoint& operator=(const CColPoint& other);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CStoredCollPoly
|
|
||||||
{
|
|
||||||
#ifdef VU_COLLISION
|
|
||||||
CVuVector verts[3];
|
|
||||||
#else
|
|
||||||
CVector verts[3];
|
|
||||||
#endif
|
|
||||||
bool valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CColModel
|
|
||||||
{
|
|
||||||
CSphere boundingSphere;
|
|
||||||
CBox boundingBox;
|
|
||||||
int16 numSpheres;
|
|
||||||
int16 numBoxes;
|
|
||||||
int16 numTriangles;
|
|
||||||
int8 numLines;
|
|
||||||
uint8 level; // colstore slot but probably still named level
|
|
||||||
bool ownsCollisionVolumes;
|
|
||||||
CColSphere *spheres;
|
|
||||||
CColLine *lines;
|
|
||||||
CColBox *boxes;
|
|
||||||
CompressedVector *vertices;
|
|
||||||
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;
|
|
||||||
|
|
||||||
void *operator new(size_t);
|
|
||||||
void operator delete(void *p, size_t);
|
|
||||||
CColModel& operator=(const CColModel& other);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CCollision
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static eLevelName ms_collisionInMemory;
|
|
||||||
static CLinkList<CColModel*> ms_colModelCache;
|
|
||||||
|
|
||||||
static void Init(void);
|
|
||||||
static void Shutdown(void);
|
|
||||||
static void Update(void);
|
|
||||||
static void LoadCollisionWhenINeedIt(bool changeLevel);
|
|
||||||
static void SortOutCollisionAfterLoad(void);
|
|
||||||
static void LoadCollisionScreen(eLevelName level);
|
|
||||||
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);
|
|
||||||
static void RemoveTrianglePlanes(CColModel *model);
|
|
||||||
|
|
||||||
// all these return true if there's a collision
|
|
||||||
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);
|
|
||||||
static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
|
||||||
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
|
|
||||||
static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
|
||||||
static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);
|
|
||||||
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
|
|
||||||
static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
|
|
||||||
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);
|
|
||||||
static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
|
|
||||||
static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
|
@ -345,7 +345,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
|
||||||
if(model.numTriangles > 0){
|
if(model.numTriangles > 0){
|
||||||
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
|
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
|
||||||
for(i = 0; i < model.numTriangles; i++){
|
for(i = 0; i < model.numTriangles; i++){
|
||||||
model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]);
|
model.triangles[i].Set(*(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12]);
|
||||||
buf += 16;
|
buf += 16;
|
||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
|
|
|
@ -1833,7 +1833,7 @@ void CPad::Update(int16 pad)
|
||||||
{
|
{
|
||||||
if ( ShakeDur )
|
if ( ShakeDur )
|
||||||
{
|
{
|
||||||
ShakeDur = Max(ShakeDur - CTimer::GetTimeStepInMilliseconds(), 0);
|
ShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0);
|
||||||
|
|
||||||
if ( ShakeDur == 0 )
|
if ( ShakeDur == 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -633,7 +633,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
|
||||||
if(IsGlass(B->GetModelIndex()))
|
if(IsGlass(B->GetModelIndex()))
|
||||||
CGlass::WindowRespondsToSoftCollision(B, impulseA);
|
CGlass::WindowRespondsToSoftCollision(B, impulseA);
|
||||||
if(!A->bInfiniteMass)
|
if(!A->bInfiniteMass)
|
||||||
A->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA);
|
A->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}else if(!B->bInfiniteMass)
|
}else if(!B->bInfiniteMass)
|
||||||
|
@ -688,7 +688,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
|
||||||
}else{
|
}else{
|
||||||
if(IsGlass(B->GetModelIndex()))
|
if(IsGlass(B->GetModelIndex()))
|
||||||
CGlass::WindowRespondsToSoftCollision(B, impulseA);
|
CGlass::WindowRespondsToSoftCollision(B, impulseA);
|
||||||
CVector f = colpoint.normal * impulseA;
|
CVector f = colpoint.GetNormal() * impulseA;
|
||||||
if(A->IsVehicle() && colpoint.normal.z < 0.7f)
|
if(A->IsVehicle() && colpoint.normal.z < 0.7f)
|
||||||
f.z *= 0.3f;
|
f.z *= 0.3f;
|
||||||
if(!A->bInfiniteMass){
|
if(!A->bInfiniteMass){
|
||||||
|
@ -1303,43 +1303,43 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
|
||||||
|
|
||||||
mostColliding = 0;
|
mostColliding = 0;
|
||||||
for(j = 1; j < numCollisions; j++)
|
for(j = 1; j < numCollisions; j++)
|
||||||
if(colpoints[j].depth > colpoints[mostColliding].depth)
|
if (colpoints[j].GetDepth() > colpoints[mostColliding].GetDepth())
|
||||||
mostColliding = j;
|
mostColliding = j;
|
||||||
|
|
||||||
if(CWorld::bSecondShift)
|
if(CWorld::bSecondShift)
|
||||||
for(j = 0; j < numCollisions; j++)
|
for(j = 0; j < numCollisions; j++)
|
||||||
shift += colpoints[j].normal * colpoints[j].depth * 1.5f/numCollisions;
|
shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.5f / numCollisions;
|
||||||
else
|
else
|
||||||
for(j = 0; j < numCollisions; j++)
|
for(j = 0; j < numCollisions; j++)
|
||||||
shift += colpoints[j].normal * colpoints[j].depth * 1.2f/numCollisions;
|
shift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.2f / numCollisions;
|
||||||
|
|
||||||
if(A->IsVehicle() && B->IsVehicle()){
|
if(A->IsVehicle() && B->IsVehicle()){
|
||||||
CVector dir = A->GetPosition() - B->GetPosition();
|
CVector dir = A->GetPosition() - B->GetPosition();
|
||||||
dir.Normalise();
|
dir.Normalise();
|
||||||
if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z)
|
if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z)
|
||||||
dir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z));
|
dir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z));
|
||||||
shift += dir * colpoints[mostColliding].depth * 0.5f;
|
shift += dir * colpoints[mostColliding].GetDepth() * 0.5f;
|
||||||
}else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){
|
}else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){
|
||||||
CVector dir = colpoints[mostColliding].normal;
|
CVector dir = colpoints[mostColliding].GetNormal();
|
||||||
float f = Min(Abs(dir.z), 0.9f);
|
float f = Min(Abs(dir.z), 0.9f);
|
||||||
dir.z = 0.0f;
|
dir.z = 0.0f;
|
||||||
dir.Normalise();
|
dir.Normalise();
|
||||||
shift += dir * colpoints[mostColliding].depth / (1.0f - f);
|
shift += dir * colpoints[mostColliding].GetDepth() / (1.0f - f);
|
||||||
boat = B;
|
boat = B;
|
||||||
}else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
|
}else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
|
||||||
CVector dir = colpoints[mostColliding].normal * -1.0f;
|
CVector dir = colpoints[mostColliding].GetNormal() * -1.0f;
|
||||||
float f = Min(Abs(dir.z), 0.9f);
|
float f = Min(Abs(dir.z), 0.9f);
|
||||||
dir.z = 0.0f;
|
dir.z = 0.0f;
|
||||||
dir.Normalise();
|
dir.Normalise();
|
||||||
B->GetMatrix().Translate(dir * colpoints[mostColliding].depth / (1.0f - f));
|
B->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f));
|
||||||
// BUG? how can that ever happen? A is a Ped
|
// BUG? how can that ever happen? A is a Ped
|
||||||
if(B->IsVehicle())
|
if(B->IsVehicle())
|
||||||
B->ProcessEntityCollision(A, colpoints);
|
B->ProcessEntityCollision(A, colpoints);
|
||||||
}else{
|
}else{
|
||||||
if(CWorld::bSecondShift)
|
if(CWorld::bSecondShift)
|
||||||
shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.4f;
|
shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.4f;
|
||||||
else
|
else
|
||||||
shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.2f;
|
shift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
doShift = true;
|
doShift = true;
|
||||||
|
|
|
@ -943,7 +943,9 @@ RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return
|
||||||
RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags)
|
RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags)
|
||||||
{
|
{
|
||||||
#ifdef RW_GL3
|
#ifdef RW_GL3
|
||||||
return '3LGO';
|
if(flags & (rwRASTERFORMATPAL8 | rwRASTERFORMAT8888))
|
||||||
|
return 'NOPE';
|
||||||
|
return 'YUP';
|
||||||
#endif
|
#endif
|
||||||
return flags & 0xF00;
|
return flags & 0xF00;
|
||||||
}
|
}
|
||||||
|
|
739
src/peds/Ped.cpp
739
src/peds/Ped.cpp
File diff suppressed because it is too large
Load diff
|
@ -451,9 +451,7 @@ public:
|
||||||
uint32 bVehExitWillBeInstant : 1;
|
uint32 bVehExitWillBeInstant : 1;
|
||||||
uint32 bHasAlreadyBeenRecorded : 1;
|
uint32 bHasAlreadyBeenRecorded : 1;
|
||||||
uint32 bFallenDown : 1;
|
uint32 bFallenDown : 1;
|
||||||
#ifdef PED_SKIN
|
uint32 bDontAcceptIKLookAts : 1;
|
||||||
uint32 bDontAcceptIKLookAts : 1; // TODO: find uses of this
|
|
||||||
#endif
|
|
||||||
uint32 bReachedAttractorHeadingTarget : 1;
|
uint32 bReachedAttractorHeadingTarget : 1;
|
||||||
uint32 bTurnedAroundOnAttractor : 1;
|
uint32 bTurnedAroundOnAttractor : 1;
|
||||||
|
|
||||||
|
@ -513,10 +511,7 @@ public:
|
||||||
CEntity* m_pEventEntity;
|
CEntity* m_pEventEntity;
|
||||||
float m_fAngleToEvent;
|
float m_fAngleToEvent;
|
||||||
AnimBlendFrameData *m_pFrames[PED_NODE_MAX];
|
AnimBlendFrameData *m_pFrames[PED_NODE_MAX];
|
||||||
#ifdef PED_SKIN
|
|
||||||
// stored inside the clump with non-skin ped
|
|
||||||
RpAtomic *m_pWeaponModel;
|
RpAtomic *m_pWeaponModel;
|
||||||
#endif
|
|
||||||
AssocGroupId m_animGroup;
|
AssocGroupId m_animGroup;
|
||||||
CAnimBlendAssociation *m_pVehicleAnim;
|
CAnimBlendAssociation *m_pVehicleAnim;
|
||||||
CVector2D m_vecAnimMoveDelta;
|
CVector2D m_vecAnimMoveDelta;
|
||||||
|
@ -579,8 +574,7 @@ public:
|
||||||
CAccident *m_lastAccident;
|
CAccident *m_lastAccident;
|
||||||
uint32 m_nPedType;
|
uint32 m_nPedType;
|
||||||
CPedStats *m_pedStats;
|
CPedStats *m_pedStats;
|
||||||
float m_fleeFromPosX;
|
CVector2D m_fleeFromPos;
|
||||||
float m_fleeFromPosY;
|
|
||||||
CEntity *m_fleeFrom;
|
CEntity *m_fleeFrom;
|
||||||
uint32 m_fleeTimer;
|
uint32 m_fleeTimer;
|
||||||
CEntity* m_threatEx; // TODO(Miami): What is this?
|
CEntity* m_threatEx; // TODO(Miami): What is this?
|
||||||
|
|
|
@ -75,28 +75,29 @@ CPed::ServiceTalkingWhenDead(void)
|
||||||
void
|
void
|
||||||
CPed::ServiceTalking(void)
|
CPed::ServiceTalking(void)
|
||||||
{
|
{
|
||||||
if (!bBodyPartJustCameOff || m_bodyPartBleeding != PED_HEAD) {
|
if (bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD)
|
||||||
if (!CGame::germanGame && m_pFire)
|
return;
|
||||||
m_queuedSound = SOUND_PED_BURNING;
|
|
||||||
|
|
||||||
if (m_queuedSound != SOUND_NO_SOUND) {
|
if (!CGame::germanGame && m_pFire)
|
||||||
if (m_queuedSound == SOUND_PED_DEATH)
|
m_queuedSound = SOUND_PED_BURNING;
|
||||||
m_soundStart = CTimer::GetTimeInMilliseconds() - 1;
|
|
||||||
|
|
||||||
if (CTimer::GetTimeInMilliseconds() > m_soundStart) {
|
if (m_queuedSound != SOUND_NO_SOUND) {
|
||||||
DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);
|
if (m_queuedSound == SOUND_PED_DEATH)
|
||||||
m_lastSoundStart = CTimer::GetTimeInMilliseconds();
|
m_soundStart = CTimer::GetTimeInMilliseconds() - 1;
|
||||||
m_soundStart =
|
|
||||||
CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime
|
|
||||||
+ CTimer::GetTimeInMilliseconds()
|
|
||||||
+ CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);
|
|
||||||
|
|
||||||
if (m_queuedSound == SOUND_PED_PLAYER_BEFORESEX && IsPlayer())
|
if (CTimer::GetTimeInMilliseconds() > m_soundStart) {
|
||||||
m_soundStart += 2000;
|
DMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);
|
||||||
|
m_lastSoundStart = CTimer::GetTimeInMilliseconds();
|
||||||
|
m_soundStart =
|
||||||
|
CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime
|
||||||
|
+ CTimer::GetTimeInMilliseconds()
|
||||||
|
+ CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);
|
||||||
|
|
||||||
m_lastQueuedSound = m_queuedSound;
|
if (m_queuedSound == SOUND_PED_PLAYER_BEFORESEX && IsPlayer())
|
||||||
m_queuedSound = SOUND_NO_SOUND;
|
m_soundStart += 2000;
|
||||||
}
|
|
||||||
|
m_lastQueuedSound = m_queuedSound;
|
||||||
|
m_queuedSound = SOUND_NO_SOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,8 +105,6 @@ CPed::ServiceTalking(void)
|
||||||
void
|
void
|
||||||
CPed::Say(uint16 audio)
|
CPed::Say(uint16 audio)
|
||||||
{
|
{
|
||||||
uint16 audioToPlay = audio;
|
|
||||||
|
|
||||||
if (3.0f + TheCamera.GetPosition().z < GetPosition().z)
|
if (3.0f + TheCamera.GetPosition().z < GetPosition().z)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -138,19 +137,19 @@ CPed::Say(uint16 audio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioToPlay < m_queuedSound) {
|
if (audio < m_queuedSound) {
|
||||||
if (audioToPlay != m_lastQueuedSound || audioToPlay == SOUND_PED_DEATH
|
if (audio != m_lastQueuedSound || audio == SOUND_PED_DEATH
|
||||||
|
|
||||||
// See VC Ped Speech patch
|
// See VC Ped Speech patch
|
||||||
#ifdef FIX_BUGS
|
#ifdef FIX_BUGS
|
||||||
|| CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
|
|| CommentWaitTime[audio - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
|
||||||
+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime)
|
+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audio - SOUND_PED_DEATH].m_nMaxRandomDelayTime)
|
||||||
#else
|
#else
|
||||||
|| CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
|
|| CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime
|
||||||
+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nMaxRandomDelayTime)
|
+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nMaxRandomDelayTime)
|
||||||
#endif
|
#endif
|
||||||
+ m_lastSoundStart <= CTimer::GetTimeInMilliseconds()) {
|
+ m_lastSoundStart <= CTimer::GetTimeInMilliseconds()) {
|
||||||
m_queuedSound = audioToPlay;
|
m_queuedSound = audio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,8 +268,7 @@ CPlayerPed::SetInitialState(void)
|
||||||
CTimer::SetTimeScale(1.0f);
|
CTimer::SetTimeScale(1.0f);
|
||||||
m_pSeekTarget = nil;
|
m_pSeekTarget = nil;
|
||||||
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
|
m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
|
||||||
m_fleeFromPosX = 0.0f;
|
m_fleeFromPos = CVector2D(0.0f, 0.0f);
|
||||||
m_fleeFromPosY = 0.0f;
|
|
||||||
m_fleeFrom = nil;
|
m_fleeFrom = nil;
|
||||||
m_fleeTimer = 0;
|
m_fleeTimer = 0;
|
||||||
m_objective = OBJECTIVE_NONE;
|
m_objective = OBJECTIVE_NONE;
|
||||||
|
|
Loading…
Reference in a new issue