summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-07-27 15:38:34 +0200
committeraap <aap@papnet.eu>2020-07-27 15:38:46 +0200
commit6b7a8f96a6763e9f0f9e94185afe097cb63984ae (patch)
tree5e8189744c28abffa7739a6bc9b35c69ab85f874
parentMerge pull request #664 from aap/miami (diff)
downloadre3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar.gz
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar.bz2
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar.lz
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar.xz
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.tar.zst
re3-6b7a8f96a6763e9f0f9e94185afe097cb63984ae.zip
-rw-r--r--src/core/Collision.cpp367
-rw-r--r--src/core/Collision.h31
-rw-r--r--src/core/FileLoader.cpp10
-rw-r--r--src/core/SurfaceTable.h35
-rw-r--r--src/core/config.h3
-rw-r--r--src/render/Glass.cpp16
-rw-r--r--src/vehicles/Vehicle.cpp10
7 files changed, 272 insertions, 200 deletions
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
index fd172cb8..639962d0 100644
--- a/src/core/Collision.cpp
+++ b/src/core/Collision.cpp
@@ -107,8 +107,11 @@ CCollision::LoadCollisionWhenINeedIt(bool forceChange)
void
CCollision::SortOutCollisionAfterLoad(void)
{
+ CColStore::LoadCollision(TheCamera.GetPosition());
+ CStreaming::LoadAllRequestedModels(false);
}
+//--MIAMI: done
void
CCollision::LoadCollisionScreen(eLevelName level)
{
@@ -251,7 +254,7 @@ CCollision::TestVerticalLineBox(const CColLine &line, const CBox &box)
}
bool
-CCollision::TestLineTriangle(const CColLine &line, const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
+CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
{
float t;
CVector normal;
@@ -266,9 +269,9 @@ CCollision::TestLineTriangle(const CColLine &line, const CVector *verts, const C
// find point of intersection
CVector p = line.p0 + (line.p1-line.p0)*t;
- const CVector &va = verts[tri.a];
- const CVector &vb = verts[tri.b];
- const CVector &vc = verts[tri.c];
+ const CVector &va = verts[tri.a].Get();
+ const CVector &vb = verts[tri.b].Get();
+ const CVector &vc = verts[tri.c].Get();
CVector2D vec1, vec2, vec3, vect;
// We do the test in 2D. With the plane direction we
@@ -361,15 +364,16 @@ CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph)
bool
CCollision::TestSphereTriangle(const CColSphere &sphere,
- const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
+ const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
{
// If sphere and plane don't intersect, no collision
- if(Abs(plane.CalcPoint(sphere.center)) > sphere.radius)
+ float planedist = plane.CalcPoint(sphere.center);
+ if(Abs(planedist) > sphere.radius)
return false;
- const CVector &va = verts[tri.a];
- const CVector &vb = verts[tri.b];
- const CVector &vc = verts[tri.c];
+ const CVector &va = verts[tri.a].Get();
+ const CVector &vb = verts[tri.b].Get();
+ const CVector &vc = verts[tri.c].Get();
// calculate two orthogonal basis vectors for the triangle
CVector vec2 = vb - va;
@@ -393,28 +397,36 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
int testcase = insideAB + insideAC + insideBC;
float dist = 0.0f;
- if(testcase == 1){
+ switch(testcase){
+ case 0:
+ return false; // shouldn't happen
+ case 1:
// closest to a vertex
if(insideAB) dist = (sphere.center - vc).Magnitude();
else if(insideAC) dist = (sphere.center - vb).Magnitude();
else if(insideBC) dist = (sphere.center - va).Magnitude();
else assert(0);
- }else if(testcase == 2){
+ break;
+ case 2:
// closest to an edge
+ // looks like original game as DistToLine manually inlined
if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center);
else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center);
else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center);
else assert(0);
- }else if(testcase == 3){
+ break;
+ case 3:
// center is in triangle
- return true;
- }else
- assert(0); // front fell off
+ dist = Abs(planedist);
+ break;
+ default:
+ assert(0);
+ }
return dist < sphere.radius;
}
-//--MIAMI: TODO
+//--MIAMI: DONE
bool
CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough)
{
@@ -429,25 +441,32 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
if(!TestLineBox(newline, model.boundingBox))
return false;
- for(i = 0; i < model.numSpheres; i++)
- if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH)
- if(TestLineSphere(newline, model.spheres[i]))
- return true;
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;
+ if(TestLineSphere(newline, model.spheres[i]))
+ return true;
+ }
- for(i = 0; i < model.numBoxes; i++)
- if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH)
- if(TestLineBox(newline, model.boxes[i]))
- return true;
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;
+ if(TestLineBox(newline, model.boxes[i]))
+ return true;
+ }
CalculateTrianglePlanes(&model);
- for(i = 0; i < model.numTriangles; i++)
- if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH)
- if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i]))
- return true;
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;
+ if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i]))
+ return true;
+ }
return false;
}
+// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used
//
// Process
@@ -716,18 +735,19 @@ CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CC
return true;
}
+//--MIAMI: unused
bool
CCollision::ProcessVerticalLineTriangle(const CColLine &line,
- const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
+ const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
CColPoint &point, float &mindist, CStoredCollPoly *poly)
{
float t;
CVector normal;
const CVector &p0 = line.p0;
- const CVector &va = verts[tri.a];
- const CVector &vb = verts[tri.b];
- const CVector &vc = verts[tri.c];
+ const CVector &va = verts[tri.a].Get();
+ const CVector &vb = verts[tri.b].Get();
+ const CVector &vc = verts[tri.c].Get();
// early out bound rect test
if(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false;
@@ -792,6 +812,7 @@ CCollision::ProcessVerticalLineTriangle(const CColLine &line,
if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;
if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
+ if(t >= mindist) return false;
point.point = p;
point.normal = normal;
point.surfaceA = 0;
@@ -817,16 +838,12 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol
return false;
// maybe inlined?
- CColTriangle tri;
- tri.a = 0;
- tri.b = 1;
- tri.c = 2;
CColTrianglePlane plane;
- plane.Set(poly->verts, tri);
+ plane.Set(poly->verts[0], poly->verts[1], poly->verts[2]);
- const CVector &va = poly->verts[tri.a];
- const CVector &vb = poly->verts[tri.b];
- const CVector &vc = poly->verts[tri.c];
+ const CVector &va = poly->verts[0];
+ const CVector &vb = poly->verts[1];
+ const CVector &vc = poly->verts[2];
CVector p0 = pos;
CVector p1(pos.x, pos.y, z);
@@ -891,8 +908,8 @@ CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CCol
bool
CCollision::ProcessLineTriangle(const CColLine &line ,
- const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
- CColPoint &point, float &mindist)
+ const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
+ CColPoint &point, float &mindist, CStoredCollPoly *poly)
{
float t;
CVector normal;
@@ -910,9 +927,9 @@ CCollision::ProcessLineTriangle(const CColLine &line ,
// find point of intersection
CVector p = line.p0 + (line.p1-line.p0)*t;
- const CVector &va = verts[tri.a];
- const CVector &vb = verts[tri.b];
- const CVector &vc = verts[tri.c];
+ const CVector &va = verts[tri.a].Get();
+ const CVector &vb = verts[tri.b].Get();
+ const CVector &vc = verts[tri.c].Get();
CVector2D vec1, vec2, vec3, vect;
switch(plane.dir){
@@ -958,19 +975,26 @@ CCollision::ProcessLineTriangle(const CColLine &line ,
if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;
if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
+ if(t >= mindist) return false;
point.point = p;
point.normal = normal;
point.surfaceA = 0;
point.pieceA = 0;
point.surfaceB = tri.surface;
point.pieceB = 0;
+ if(poly){
+ poly->verts[0] = va;
+ poly->verts[1] = vb;
+ poly->verts[2] = vc;
+ poly->valid = true;
+ }
mindist = t;
return true;
}
bool
CCollision::ProcessSphereTriangle(const CColSphere &sphere,
- const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
+ const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
CColPoint &point, float &mindistsq)
{
// If sphere and plane don't intersect, no collision
@@ -979,9 +1003,9 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
if(Abs(planedist) > sphere.radius || distsq > mindistsq)
return false;
- const CVector &va = verts[tri.a];
- const CVector &vb = verts[tri.b];
- const CVector &vc = verts[tri.c];
+ const CVector &va = verts[tri.a].Get();
+ const CVector &vb = verts[tri.b].Get();
+ const CVector &vc = verts[tri.c].Get();
// calculate two orthogonal basis vectors for the triangle
CVector normal;
@@ -1008,25 +1032,33 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
int testcase = insideAB + insideAC + insideBC;
float dist = 0.0f;
CVector p;
- if(testcase == 1){
+ switch(testcase){
+ case 0:
+ return false; // shouldn't happen
+ case 1:
// closest to a vertex
if(insideAB) p = vc;
else if(insideAC) p = vb;
else if(insideBC) p = va;
else assert(0);
dist = (sphere.center - p).Magnitude();
- }else if(testcase == 2){
+ break;
+ case 2:
// closest to an edge
+ // looks like original game as DistToLine manually inlined
if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p);
else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p);
else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p);
else assert(0);
- }else if(testcase == 3){
+ break;
+ case 3:
// center is in triangle
dist = Abs(planedist);
p = sphere.center - normal*planedist;
- }else
- assert(0); // front fell off
+ break;
+ default:
+ assert(0);
+ }
if(dist >= sphere.radius || dist*dist >= mindistsq)
return false;
@@ -1061,18 +1093,24 @@ CCollision::ProcessLineOfSight(const CColLine &line,
return false;
float coldist = mindist;
- for(i = 0; i < model.numSpheres; i++)
- if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessLineSphere(newline, model.spheres[i], point, coldist);
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;
+ ProcessLineSphere(newline, model.spheres[i], point, coldist);
+ }
- for(i = 0; i < model.numBoxes; i++)
- if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessLineBox(newline, model.boxes[i], point, coldist);
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;
+ ProcessLineBox(newline, model.boxes[i], point, coldist);
+ }
CalculateTrianglePlanes(&model);
- for(i = 0; i < model.numTriangles; i++)
- if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist);
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
+ if(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;
+ ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist);
+ }
if(coldist < mindist){
point.point = matrix * point.point;
@@ -1095,31 +1133,33 @@ 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;
- if(!TestVerticalLineBox(newline, model.boundingBox))
+ if(!TestLineBox(newline, model.boundingBox))
return false;
+ // BUG? is IsSeeThroughVertical really the right thing? also not checking shoot through
float coldist = mindist;
- for(i = 0; i < model.numSpheres; i++)
- if(!ignoreSeeThrough || model.spheres[i].surface != SURFACE_GLASS && model.spheres[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessLineSphere(newline, model.spheres[i], point, coldist);
+ for(i = 0; i < model.numSpheres; i++){
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue;
+ ProcessLineSphere(newline, model.spheres[i], point, coldist);
+ }
- for(i = 0; i < model.numBoxes; i++)
- if(!ignoreSeeThrough || model.boxes[i].surface != SURFACE_GLASS && model.boxes[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessLineBox(newline, model.boxes[i], point, coldist);
+ for(i = 0; i < model.numBoxes; i++){
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue;
+ ProcessLineBox(newline, model.boxes[i], point, coldist);
+ }
CalculateTrianglePlanes(&model);
TempStoredPoly.valid = false;
- for(i = 0; i < model.numTriangles; i++)
- if(!ignoreSeeThrough || model.triangles[i].surface != SURFACE_GLASS && model.triangles[i].surface != SURFACE_TRANSPARENT_CLOTH)
- ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);
+ for(i = 0; i < model.numTriangles; i++){
+ if(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue;
+ ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);
+ }
if(coldist < mindist){
point.point = matrix * point.point;
point.normal = Multiply3x3(matrix, point.normal);
- if(poly && TempStoredPoly.valid){
+ if(TempStoredPoly.valid && poly){
*poly = TempStoredPoly;
poly->verts[0] = matrix * poly->verts[0];
poly->verts[1] = matrix * poly->verts[1];
@@ -1354,6 +1394,15 @@ CCollision::CalculateTrianglePlanes(CColModel *model)
}
void
+CCollision::RemoveTrianglePlanes(CColModel *model)
+{
+ if(model->trianglePlanes){
+ ms_colModelCache.Remove(model->GetLinkPtr());
+ model->RemoveTrianglePlanes();
+ }
+}
+
+void
CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)
{
int i;
@@ -1575,15 +1624,75 @@ CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
}
+static void
+GetSurfaceColor(uint8 surf, uint8 &r, uint8 &g, uint8 &b)
+{
+ // game doesn't do this
+ r = 255;
+ g = 128;
+ b = 0;
+
+ switch(CSurfaceTable::GetAdhesionGroup(surf)){
+ case ADHESIVE_RUBBER:
+ r = 255;
+ g = 0;
+ b = 0;
+ break;
+ case ADHESIVE_HARD:
+ r = 255;
+ g = 255;
+ b = 128;
+ break;
+ case ADHESIVE_ROAD:
+ r = 128;
+ g = 128;
+ b = 128;
+ break;
+ case ADHESIVE_LOOSE:
+ r = 0;
+ g = 255;
+ b = 0;
+ break;
+ case ADHESIVE_SAND:
+ r = 255;
+ g = 128;
+ b = 128;
+ break;
+ case ADHESIVE_WET:
+ r = 0;
+ g = 0;
+ b = 255;
+ break;
+ }
+
+ if(surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){
+ r = 255;
+ g = 255;
+ b = 0;
+ }
+
+ float f = (surf & 0xF)/32.0f + 0.5f;
+ r *= f;
+ g *= f;
+ b *= f;
+
+ if(surf == SURFACE_TRANSPARENT_CLOTH || surf == SURFACE_METAL_CHAIN_FENCE ||
+ surf == SURFACE_TRANSPARENT_STONE || surf == SURFACE_SCAFFOLD_POLE)
+ if(CTimer::GetFrameCounter() & 1){
+ r = 0;
+ g = 0;
+ b = 0;
+ }
+}
+
void
CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id)
{
int i;
int s;
- float f;
CVector verts[8];
CVector min, max;
- int r, g, b;
+ uint8 r, g, b;
RwImVertexIndex *iptr;
RwIm3DVertex *vptr;
@@ -1602,53 +1711,8 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
verts[1] = mat * verts[1];
verts[2] = mat * verts[2];
- // game doesn't do this
- r = 255;
- g = 128;
- b = 0;
-
s = colModel.triangles[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
+ GetSurfaceColor(s, r, g, b);
if(s > SURFACE_METAL_GATE){
r = CGeneral::GetRandomNumber();
@@ -1689,47 +1753,7 @@ CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel,
verts[7] = mat * CVector(max.x, max.y, max.z);
s = colModel.boxes[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
+ GetSurfaceColor(s, r, g, b);
RenderBuffer::StartStoring(36, 8, &iptr, &vptr);
RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);
@@ -1833,7 +1857,7 @@ CColLine::Set(const CVector &p0, const CVector &p1)
}
void
-CColTriangle::Set(const CVector *, int a, int b, int c, uint8 surf, uint8 piece)
+CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
{
this->a = a;
this->b = b;
@@ -1842,12 +1866,8 @@ CColTriangle::Set(const CVector *, int a, int b, int c, uint8 surf, uint8 piece)
}
void
-CColTrianglePlane::Set(const CVector *v, CColTriangle &tri)
+CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
{
- const CVector &va = v[tri.a];
- const CVector &vb = v[tri.b];
- const CVector &vc = v[tri.c];
-
normal = CrossProduct(vc-va, vb-va);
normal.Normalise();
dist = DotProduct(normal, va);
@@ -1905,6 +1925,7 @@ CColModel::RemoveCollisionVolumes(void)
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
+ CCollision::RemoveTrianglePlanes(this);
}
numSpheres = 0;
numLines = 0;
@@ -1950,7 +1971,7 @@ CColModel::GetLinkPtr(void)
void
CColModel::GetTrianglePoint(CVector &v, int i) const
{
- v = vertices[i];
+ v = vertices[i].Get();
}
CColModel&
@@ -2029,7 +2050,7 @@ CColModel::operator=(const CColModel &other)
if(vertices)
RwFree(vertices);
if(numVerts){
- vertices = (CVector*)RwMalloc(numVerts*sizeof(CVector));
+ vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
diff --git a/src/core/Collision.h b/src/core/Collision.h
index 09abaa1c..eb11d8c4 100644
--- a/src/core/Collision.h
+++ b/src/core/Collision.h
@@ -10,6 +10,19 @@
#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; };
+#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
{
CVector center;
@@ -63,7 +76,7 @@ struct CColTriangle
uint16 c;
uint8 surface;
- void Set(const CVector *v, int a, int b, int c, uint8 surf, uint8 piece);
+ void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
};
struct CColTrianglePlane
@@ -72,7 +85,8 @@ struct CColTrianglePlane
float dist;
uint8 dir;
- void Set(const CVector *v, CColTriangle &tri);
+ 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 CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
};
@@ -113,7 +127,7 @@ struct CColModel
CColSphere *spheres;
CColLine *lines;
CColBox *boxes;
- CVector *vertices;
+ CompressedVector *vertices;
CColTriangle *triangles;
CColTrianglePlane *trianglePlanes;
@@ -145,24 +159,25 @@ public:
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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
+ 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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
+ 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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
- static bool ProcessLineTriangle(const CColLine &line , const CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, 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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
+ 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);
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 86ebb5dd..635192ea 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -326,13 +326,13 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
int32 numVertices = *(int16*)buf;
buf += 4;
if(numVertices > 0){
- model.vertices = (CVector*)RwMalloc(numVertices*sizeof(CVector));
+ model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));
for(i = 0; i < numVertices; i++){
- model.vertices[i] = *(CVector*)buf;
+ model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8));
#if 0
- if(Abs(model.vertices[i].x) >= 256.0f ||
- Abs(model.vertices[i].y) >= 256.0f ||
- Abs(model.vertices[i].z) >= 256.0f)
+ if(Abs(*(float*)buf) >= 256.0f ||
+ Abs(*(float*)(buf+4)) >= 256.0f ||
+ Abs(*(float*)(buf+8)) >= 256.0f)
printf("%s:Collision volume too big\n", modelname);
#endif
buf += 12;
diff --git a/src/core/SurfaceTable.h b/src/core/SurfaceTable.h
index d8f9be3d..359ebd5c 100644
--- a/src/core/SurfaceTable.h
+++ b/src/core/SurfaceTable.h
@@ -53,6 +53,41 @@ enum
struct CColPoint;
+inline bool
+IsSeeThrough(uint8 surfType)
+{
+ switch(surfType)
+ case SURFACE_GLASS:
+ case SURFACE_TRANSPARENT_CLOTH:
+ case SURFACE_METAL_CHAIN_FENCE:
+ case SURFACE_TRANSPARENT_STONE:
+ case SURFACE_SCAFFOLD_POLE:
+ return true;
+ return false;
+}
+
+// I think the necessity of this function is really a bug
+inline bool
+IsSeeThroughVertical(uint8 surfType)
+{
+ switch(surfType)
+ case SURFACE_GLASS:
+ case SURFACE_TRANSPARENT_CLOTH:
+ return true;
+ return false;
+}
+
+inline bool
+IsShootThrough(uint8 surfType)
+{
+ switch(surfType)
+ case SURFACE_METAL_CHAIN_FENCE:
+ case SURFACE_TRANSPARENT_STONE:
+ case SURFACE_SCAFFOLD_POLE:
+ return true;
+ return false;
+}
+
class CSurfaceTable
{
static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS];
diff --git a/src/core/config.h b/src/core/config.h
index e67db1a3..c9c65051 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -54,7 +54,7 @@ enum Config {
NUMBOATALPHALIST = 20,
NUMALPHAENTITYLIST = 200,
NUMALPHAUNTERWATERENTITYLIST = 30,
- NUMCOLCACHELINKS = 200,
+ NUMCOLCACHELINKS = 50,
NUMREFERENCES = 800,
// Zones
@@ -166,6 +166,7 @@ enum Config {
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
+# define COMPRESSED_COL_VECTORS
#elif defined GTA_PC
# define GTA3_1_1_PATCH
//# define GTA3_STEAM_PATCH
diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp
index ac892ddb..ee36bad3 100644
--- a/src/render/Glass.cpp
+++ b/src/render/Glass.cpp
@@ -424,10 +424,10 @@ CGlass::RenderEntityInGlass(CEntity *entity)
ASSERT(col!=nil);
if ( col->numTriangles >= 2 )
{
- CVector a = object->GetMatrix() * col->vertices[0];
- CVector b = object->GetMatrix() * col->vertices[1];
- CVector c = object->GetMatrix() * col->vertices[2];
- CVector d = object->GetMatrix() * col->vertices[3];
+ CVector a = object->GetMatrix() * col->vertices[0].Get();
+ CVector b = object->GetMatrix() * col->vertices[1].Get();
+ CVector c = object->GetMatrix() * col->vertices[2].Get();
+ CVector d = object->GetMatrix() * col->vertices[3].Get();
if ( object->bGlassCracked )
{
@@ -613,10 +613,10 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed,
CColModel *col = object->GetColModel();
ASSERT(col!=nil);
- CVector a = object->GetMatrix() * col->vertices[0];
- CVector b = object->GetMatrix() * col->vertices[1];
- CVector c = object->GetMatrix() * col->vertices[2];
- CVector d = object->GetMatrix() * col->vertices[3];
+ CVector a = object->GetMatrix() * col->vertices[0].Get();
+ CVector b = object->GetMatrix() * col->vertices[1].Get();
+ CVector c = object->GetMatrix() * col->vertices[2].Get();
+ CVector d = object->GetMatrix() * col->vertices[3].Get();
float minx = Min(Min(a.x, b.x), Min(c.x, d.x));
float maxx = Max(Max(a.x, b.x), Max(c.x, d.x));
diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp
index 2c296ee2..378a4c0a 100644
--- a/src/vehicles/Vehicle.cpp
+++ b/src/vehicles/Vehicle.cpp
@@ -2239,7 +2239,7 @@ CVehicle::DoSunGlare(void)
int a2 = colmodel->triangles[i+1].a;
int b2 = colmodel->triangles[i+1].b;
int c2 = colmodel->triangles[i+1].c;
- CVector vert1 = colmodel->vertices[a1];
+ CVector vert1 = colmodel->vertices[a1].Get();
CVector vert4;
// Need an upward surface
if(vert1.z <= 0.0f)
@@ -2250,23 +2250,23 @@ CVehicle::DoSunGlare(void)
if(a2 != a1 && a2 != b1 && a2 != c1){
// a2 is not in tri1
numTri2Verts++;
- vert4 = colmodel->vertices[a2];
+ vert4 = colmodel->vertices[a2].Get();
}
if(b2 != a1 && b2 != b1 && b2 != c1){
// b2 is not in tri1
numTri2Verts++;
- vert4 = colmodel->vertices[b2];
+ vert4 = colmodel->vertices[b2].Get();
}
if(c2 != a1 && c2 != b1 && c2 != c1){
// c2 is not in tri1
numTri2Verts++;
- vert4 = colmodel->vertices[c2];
+ vert4 = colmodel->vertices[c2].Get();
}
// Need exactly one vertex from tri2 for a quad with tri1
if(numTri2Verts != 1)
continue;
- CVector mid = (vert1 + colmodel->vertices[b1] + colmodel->vertices[c1] + vert4)/4.0f;
+ CVector mid = (vert1 + colmodel->vertices[b1].Get() + colmodel->vertices[c1].Get() + vert4)/4.0f;
float dy = mid.y - vert1.y;
float dx = mid.x - vert1.x;
float dist = 1.4f * Min(Abs(dx), Abs(dy));