mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-14 09:04:31 +02:00
#3 fix flash lights after death, fix check hit (now using OBB and spheres instead of AABB)
This commit is contained in:
@@ -254,16 +254,17 @@ struct Controller {
|
|||||||
return animation.getBoundingBox(vec3(0, 0, 0), oriented ? getEntity().rotation.value / 0x4000 : 0);
|
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();
|
TR::Model *m = getModel();
|
||||||
Basis basis(getMatrix());
|
Basis basis(getMatrix());
|
||||||
|
|
||||||
|
count = 0;
|
||||||
for (int i = 0; i < m->mCount; i++) {
|
for (int i = 0; i < m->mCount; i++) {
|
||||||
TR::Mesh &aMesh = level->meshes[level->meshOffsets[m->mStart + 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;
|
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) {
|
int collide(Controller *controller, bool checkBoxes = true) {
|
||||||
@@ -280,18 +281,18 @@ struct Controller {
|
|||||||
|
|
||||||
Sphere aSpheres[34];
|
Sphere aSpheres[34];
|
||||||
Sphere bSpheres[34];
|
Sphere bSpheres[34];
|
||||||
|
int aCount, bCount;
|
||||||
|
|
||||||
getSpheres(aSpheres);
|
getSpheres(aSpheres, aCount);
|
||||||
controller->getSpheres(bSpheres);
|
controller->getSpheres(bSpheres, bCount);
|
||||||
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
for (int i = 0; i < a->mCount; i++)
|
for (int i = 0; i < aCount; i++)
|
||||||
if (aSpheres[i].radius > 0.0f)
|
for (int j = 0; j < bCount; j++)
|
||||||
for (int j = 0; j < b->mCount; j++)
|
if (bSpheres[j].intersect(aSpheres[i])) {
|
||||||
if (bSpheres[j].radius > 0.0f && bSpheres[j].intersect(aSpheres[i])) {
|
mask |= (1 << i);
|
||||||
mask |= (1 << i);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -498,9 +498,8 @@ namespace Debug {
|
|||||||
|
|
||||||
bool bboxIntersect = false;
|
bool bboxIntersect = false;
|
||||||
|
|
||||||
Sphere spheres[34];
|
|
||||||
ASSERT(m->mCount <= 34);
|
ASSERT(m->mCount <= 34);
|
||||||
controller->getSpheres(spheres);
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
for (int j = 0; j < level.entitiesCount; j++) {
|
for (int j = 0; j < level.entitiesCount; j++) {
|
||||||
TR::Entity &t = level.entities[j];
|
TR::Entity &t = level.entities[j];
|
||||||
@@ -515,8 +514,11 @@ namespace Debug {
|
|||||||
Box box = controller->getBoundingBoxLocal();
|
Box box = controller->getBoundingBoxLocal();
|
||||||
Debug::Draw::box(matrix, box.min, box.max, bboxIntersect ? vec4(1, 0, 0, 1): vec4(1));
|
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];
|
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));
|
Debug::Draw::sphere(sphere.center, sphere.radius, (mask & (1 << joint)) ? vec4(1, 0, 0, 0.5f) : vec4(0, 1, 1, 0.5f));
|
||||||
/*
|
/*
|
||||||
|
30
src/lara.h
30
src/lara.h
@@ -1088,15 +1088,26 @@ struct Lara : Character {
|
|||||||
|
|
||||||
bool checkHit(int target, const vec3 &from, const vec3 &to, vec3 &point) {
|
bool checkHit(int target, const vec3 &from, const vec3 &to, vec3 &point) {
|
||||||
TR::Entity &e = level->entities[target];
|
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;
|
float t;
|
||||||
vec3 v = (to - from);
|
vec3 v = to - from;
|
||||||
vec3 dir = v.normal();
|
|
||||||
if (box.intersect(from, dir, t) && v.length() > t) {
|
if (box.intersect(m, from, v, t)) {
|
||||||
point = from + dir * t;
|
v = v.normal();
|
||||||
return true;
|
Sphere spheres[34];
|
||||||
} else
|
int count;
|
||||||
return false;
|
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() {
|
virtual void cmdEmpty() {
|
||||||
@@ -1145,6 +1156,9 @@ struct Lara : Character {
|
|||||||
|
|
||||||
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
|
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() {
|
bool waterOut() {
|
||||||
|
36
src/utils.h
36
src/utils.h
@@ -868,19 +868,24 @@ struct Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool intersect(const vec3 &rayPos, const vec3 &rayDir, float &t) const {
|
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++)
|
for (int i = 0; i < 3; i++)
|
||||||
if (rayDir[i] != 0) {
|
if (rayDir[i] != 0) {
|
||||||
float lo = (min[i] - rayPos[i]) / rayDir[i];
|
float lo = (min[i] - rayPos[i]) / rayDir[i];
|
||||||
float hi = (max[i] - rayPos[i]) / rayDir[i];
|
float hi = (max[i] - rayPos[i]) / rayDir[i];
|
||||||
t0 = ::max(t0, ::min(lo, hi));
|
tMin = ::max(tMin, ::min(lo, hi));
|
||||||
t1 = ::min(t1, ::max(lo, hi));
|
tMax = ::min(tMax, ::max(lo, hi));
|
||||||
} else
|
} else
|
||||||
if (rayPos[i] < min[i] || rayPos[i] > max[i])
|
if (rayPos[i] < min[i] || rayPos[i] > max[i])
|
||||||
return false;
|
return false;
|
||||||
t = t0;
|
t = tMin;
|
||||||
return (t0 <= t1) && (t1 > 0);
|
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() {}
|
||||||
Sphere(const vec3 ¢er, float radius) : center(center), radius(radius) {}
|
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 d = (center - s.center).length2();
|
||||||
float r = (radius + s.radius);
|
float r = (radius + s.radius);
|
||||||
return d < r * r;
|
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 {
|
struct Stream {
|
||||||
|
Reference in New Issue
Block a user