Cleanup collision detection
This commit is contained in:
parent
e99822ae3c
commit
235ed4a274
6 changed files with 20 additions and 64 deletions
|
@ -98,13 +98,7 @@ bool CollisionDetector::rayTestObjects(const RaycastProperties &props, RaycastRe
|
|||
// Test using AABB
|
||||
shared_ptr<ModelSceneNode> model(object->getModelSceneNode());
|
||||
if (model) {
|
||||
// Prevent division by zero
|
||||
if (objSpaceDir.x == 0.0f) objSpaceDir.x = 1e-7f;
|
||||
if (objSpaceDir.y == 0.0f) objSpaceDir.y = 1e-7f;
|
||||
if (objSpaceDir.z == 0.0f) objSpaceDir.z = 1e-7f;
|
||||
glm::vec3 invDir(1.0f / objSpaceDir);
|
||||
|
||||
if (model->aabb().raycast(objSpaceOrigin, invDir, distance) &&
|
||||
if (model->aabb().raycast(objSpaceOrigin, objSpaceDir, distance) &&
|
||||
distance >= 0.0f && distance <= props.distance) {
|
||||
|
||||
collisions.push_back(make_pair(object, distance));
|
||||
|
|
|
@ -127,18 +127,20 @@ bool AABB::intersect(const AABB &other) const {
|
|||
}
|
||||
|
||||
// Algorithm adapted from https://gamedev.stackexchange.com/a/18459
|
||||
bool AABB::raycast(const glm::vec3 &origin, const glm::vec3 &invDir, float &distance) const {
|
||||
float tx1 = (_min.x - origin.x) * invDir.x;
|
||||
float tx2 = (_max.x - origin.x) * invDir.x;
|
||||
float ty1 = (_min.y - origin.y) * invDir.y;
|
||||
float ty2 = (_max.y - origin.y) * invDir.y;
|
||||
float tz1 = (_min.z - origin.z) * invDir.z;
|
||||
float tz2 = (_max.z - origin.z) * invDir.z;
|
||||
bool AABB::raycast(const glm::vec3 &origin, const glm::vec3 &dir, float &distance) const {
|
||||
glm::vec3 dirfrac(1.0f / dir);
|
||||
|
||||
float tx1 = (_min.x - origin.x) * dirfrac.x;
|
||||
float tx2 = (_max.x - origin.x) * dirfrac.x;
|
||||
float ty1 = (_min.y - origin.y) * dirfrac.y;
|
||||
float ty2 = (_max.y - origin.y) * dirfrac.y;
|
||||
float tz1 = (_min.z - origin.z) * dirfrac.z;
|
||||
float tz2 = (_max.z - origin.z) * dirfrac.z;
|
||||
float tmin = glm::max(glm::max(glm::min(tx1, tx2), glm::min(ty1, ty2)), glm::min(tz1, tz2));
|
||||
float tmax = glm::min(glm::min(glm::max(tx1, tx2), glm::max(ty1, ty2)), glm::max(tz1, tz2));
|
||||
|
||||
if (tmax < 0.0f) return false; // backside intersection
|
||||
if (tmax < tmin) return false; // neither backside nor frontside
|
||||
if (tmax < 0.0f) return false; // AABB is behind
|
||||
if (tmax < tmin) return false; // no intersection
|
||||
|
||||
distance = tmin;
|
||||
|
||||
|
@ -149,28 +151,6 @@ glm::vec3 AABB::getSize() const {
|
|||
return _max - _min;
|
||||
}
|
||||
|
||||
float AABB::getDistanceFromClosestPoint(const glm::vec3 &point) const {
|
||||
return glm::distance(getClosestPoint(point), point);
|
||||
}
|
||||
|
||||
glm::vec3 AABB::getClosestPoint(const glm::vec3 &point) const {
|
||||
glm::vec3 closest;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (point[i] > _max[i]) {
|
||||
closest[i] = _max[i];
|
||||
} else if (point[i] < _min[i]) {
|
||||
closest[i] = _min[i];
|
||||
} else {
|
||||
closest[i] = point[i];
|
||||
}
|
||||
}
|
||||
return move(closest);
|
||||
}
|
||||
|
||||
float AABB::getDistanceFromClosestPoint2(const glm::vec3 &point) const {
|
||||
return glm::distance2(getClosestPoint(point), point);
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -43,23 +43,13 @@ public:
|
|||
* Casts a ray and tests if it intersects this AABB.
|
||||
*
|
||||
* @param origin ray origin
|
||||
* @param invDir ray direction inverse
|
||||
* @param dir ray direction
|
||||
* @param[out] distance to the intersection point (negative if ray origin is inside this AABB)
|
||||
*/
|
||||
bool raycast(const glm::vec3 &origin, const glm::vec3 &invDir, float &distance) const;
|
||||
bool raycast(const glm::vec3 &origin, const glm::vec3 &dir, float &distance) const;
|
||||
|
||||
glm::vec3 getSize() const;
|
||||
|
||||
/**
|
||||
* @return distance from the closest point of this AABB to the specified point
|
||||
*/
|
||||
float getDistanceFromClosestPoint(const glm::vec3 &point) const;
|
||||
|
||||
/**
|
||||
* @return squared distance from the closest point of this AABB to the specified point
|
||||
*/
|
||||
float getDistanceFromClosestPoint2(const glm::vec3 &point) const;
|
||||
|
||||
const glm::vec3 &min() const { return _min; }
|
||||
const glm::vec3 &max() const { return _max; }
|
||||
const glm::vec3 ¢er() const { return _center; }
|
||||
|
@ -73,8 +63,6 @@ private:
|
|||
glm::mat4 _transform { 1.0f };
|
||||
|
||||
void updateTransform();
|
||||
|
||||
inline glm::vec3 getClosestPoint(const glm::vec3 &point) const;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
|
|
|
@ -147,9 +147,8 @@ glm::vec2 Mesh::getFaceCenterUV(int faceIdx) const {
|
|||
if (faceIdx < 0 || faceIdx >= _indices.size() / 3) {
|
||||
throw out_of_range("faceIdx out of range");
|
||||
}
|
||||
if (_offsets.texCoords1 == -1) {
|
||||
throw logic_error("texCoords1 undefined");
|
||||
}
|
||||
if (_offsets.texCoords1 == -1) return glm::vec2(0.0f);
|
||||
|
||||
glm::vec2 result(0.0f);
|
||||
const uint16_t *indices = &_indices[3 * faceIdx];
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
@ -159,6 +158,7 @@ glm::vec2 Mesh::getFaceCenterUV(int faceIdx) const {
|
|||
}
|
||||
result /= 3.0f;
|
||||
result = glm::clamp(result);
|
||||
|
||||
return move(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ bool Walkmesh::raycast(const glm::vec3 &origin, const glm::vec3 &dir, bool walka
|
|||
const glm::vec3 &p1 = face.vertices[1];
|
||||
const glm::vec3 &p2 = face.vertices[2];
|
||||
|
||||
if (glm::intersectRayTriangle(origin, dir, p0, p1, p2, baryPosition, localDistance) && localDistance >= 0.0f && localDistance < minDistance) {
|
||||
if (glm::intersectRayTriangle(origin, dir, p0, p1, p2, baryPosition, localDistance) && localDistance > 0.0f && localDistance < minDistance) {
|
||||
minDistance = localDistance;
|
||||
material = static_cast<int>(face.material);
|
||||
}
|
||||
|
|
|
@ -74,19 +74,13 @@ float SceneNode::getDistanceTo2(const glm::vec3 &point) const {
|
|||
}
|
||||
|
||||
float SceneNode::getDistanceTo(const SceneNode &other) const {
|
||||
return glm::sqrt(getDistanceTo2(other));
|
||||
return glm::distance(getOrigin(), other.getOrigin());
|
||||
}
|
||||
|
||||
float SceneNode::getDistanceTo2(const SceneNode &other) const {
|
||||
if (!other.isVolumetric()) {
|
||||
return glm::distance2(getOrigin(), other.getOrigin());
|
||||
}
|
||||
|
||||
glm::vec3 aabbSpaceOrigin(other._absoluteTransformInv * glm::vec4(getOrigin(), 1.0f));
|
||||
|
||||
return other.aabb().getDistanceFromClosestPoint2(aabbSpaceOrigin);
|
||||
}
|
||||
|
||||
void SceneNode::setParent(const SceneNode *parent) {
|
||||
_parent = parent;
|
||||
updateAbsoluteTransform();
|
||||
|
|
Loading…
Reference in a new issue