diff --git a/src/controller.h b/src/controller.h index 40c4902..c5a898a 100644 --- a/src/controller.h +++ b/src/controller.h @@ -254,16 +254,17 @@ struct Controller { return animation.getBoundingBox(vec3(0, 0, 0), oriented ? getEntity().rotation.value / 0x4000 : 0); } - void getSpheres(Sphere *spheres) { + void getSpheres(Sphere *spheres, int &count) { TR::Model *m = getModel(); Basis basis(getMatrix()); + count = 0; for (int i = 0; i < m->mCount; i++) { TR::Mesh &aMesh = level->meshes[level->meshOffsets[m->mStart + i]]; + if (aMesh.radius <= 0) continue; vec3 center = animation.getJoints(basis, i, true) * aMesh.center; - spheres[i] = Sphere(center, aMesh.radius); + spheres[count++] = Sphere(center, aMesh.radius); } - } int collide(Controller *controller, bool checkBoxes = true) { @@ -280,18 +281,18 @@ struct Controller { Sphere aSpheres[34]; Sphere bSpheres[34]; + int aCount, bCount; - getSpheres(aSpheres); - controller->getSpheres(bSpheres); + getSpheres(aSpheres, aCount); + controller->getSpheres(bSpheres, bCount); int mask = 0; - for (int i = 0; i < a->mCount; i++) - if (aSpheres[i].radius > 0.0f) - for (int j = 0; j < b->mCount; j++) - if (bSpheres[j].radius > 0.0f && bSpheres[j].intersect(aSpheres[i])) { - mask |= (1 << i); - break; - } + for (int i = 0; i < aCount; i++) + for (int j = 0; j < bCount; j++) + if (bSpheres[j].intersect(aSpheres[i])) { + mask |= (1 << i); + break; + } return mask; } diff --git a/src/debug.h b/src/debug.h index 64565a6..1e19566 100644 --- a/src/debug.h +++ b/src/debug.h @@ -498,9 +498,8 @@ namespace Debug { bool bboxIntersect = false; - Sphere spheres[34]; ASSERT(m->mCount <= 34); - controller->getSpheres(spheres); + int mask = 0; for (int j = 0; j < level.entitiesCount; j++) { TR::Entity &t = level.entities[j]; @@ -515,8 +514,11 @@ namespace Debug { Box box = controller->getBoundingBoxLocal(); Debug::Draw::box(matrix, box.min, box.max, bboxIntersect ? vec4(1, 0, 0, 1): vec4(1)); + Sphere spheres[34]; + int count; + controller->getSpheres(spheres, count); - for (int joint = 0; joint < m->mCount; joint++) { + for (int joint = 0; joint < count; joint++) { Sphere &sphere = spheres[joint]; Debug::Draw::sphere(sphere.center, sphere.radius, (mask & (1 << joint)) ? vec4(1, 0, 0, 0.5f) : vec4(0, 1, 1, 0.5f)); /* diff --git a/src/lara.h b/src/lara.h index 9a6e091..67da9a1 100644 --- a/src/lara.h +++ b/src/lara.h @@ -1088,15 +1088,26 @@ struct Lara : Character { bool checkHit(int target, const vec3 &from, const vec3 &to, vec3 &point) { TR::Entity &e = level->entities[target]; - Box box = ((Controller*)e.controller)->getBoundingBox(); + Controller *controller = (Controller*)e.controller; + + Box box = controller->getBoundingBoxLocal(); + mat4 m = controller->getMatrix(); + float t; - vec3 v = (to - from); - vec3 dir = v.normal(); - if (box.intersect(from, dir, t) && v.length() > t) { - point = from + dir * t; - return true; - } else - return false; + vec3 v = to - from; + + if (box.intersect(m, from, v, t)) { + v = v.normal(); + Sphere spheres[34]; + int count; + controller->getSpheres(spheres, count); + for (int i = 0; i < count; i++) + if (spheres[i].intersect(from, v, t)) { + point = from + v * t; + return true; + } + } + return false; } virtual void cmdEmpty() { @@ -1145,6 +1156,9 @@ struct Lara : Character { animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1); } + + if (health <= 0) + Core::lightColor[1 + 0] = Core::lightColor[1 + 1] = vec4(0, 0, 0, 1); }; bool waterOut() { diff --git a/src/utils.h b/src/utils.h index 900c33c..b8241df 100644 --- a/src/utils.h +++ b/src/utils.h @@ -868,19 +868,24 @@ struct Box { } bool intersect(const vec3 &rayPos, const vec3 &rayDir, float &t) const { - float t1 = INF, t0 = -t1; + float tMax = INF, tMin = -tMax; for (int i = 0; i < 3; i++) if (rayDir[i] != 0) { float lo = (min[i] - rayPos[i]) / rayDir[i]; float hi = (max[i] - rayPos[i]) / rayDir[i]; - t0 = ::max(t0, ::min(lo, hi)); - t1 = ::min(t1, ::max(lo, hi)); + tMin = ::max(tMin, ::min(lo, hi)); + tMax = ::min(tMax, ::max(lo, hi)); } else if (rayPos[i] < min[i] || rayPos[i] > max[i]) return false; - t = t0; - return (t0 <= t1) && (t1 > 0); + t = tMin; + return (tMin <= tMax) && (tMax > 0.0f); + } + + bool intersect(const mat4 &matrix, const vec3 &rayPos, const vec3 &rayDir, float &t) const { + mat4 mInv = matrix.inverse(); + return intersect(mInv * rayPos, (mInv * vec4(rayDir, 0)).xyz, t); } }; @@ -891,11 +896,30 @@ struct Sphere { Sphere() {} Sphere(const vec3 ¢er, float radius) : center(center), radius(radius) {} - bool intersect(const Sphere &s) { + bool intersect(const Sphere &s) const { float d = (center - s.center).length2(); float r = (radius + s.radius); return d < r * r; } + + bool intersect(const vec3 &rayPos, const vec3 &rayDir, float &t) const { + vec3 v = rayPos - center; + float h = -v.dot(rayDir); + float d = h * h + radius * radius - v.length2(); + + if (d > 0.0f) { + d = sqrtf(d); + float tMin = h - d; + float tMax = h + d; + if (tMax > 0.0f) { + if (tMin < 0.0f) + tMin = 0.0f; + t = tMin; + return true; + } + } + return false; + } }; struct Stream {