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]; @@ -1353,6 +1393,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) { @@ -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));