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
|
// Test using AABB
|
||||||
shared_ptr<ModelSceneNode> model(object->getModelSceneNode());
|
shared_ptr<ModelSceneNode> model(object->getModelSceneNode());
|
||||||
if (model) {
|
if (model) {
|
||||||
// Prevent division by zero
|
if (model->aabb().raycast(objSpaceOrigin, objSpaceDir, distance) &&
|
||||||
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) &&
|
|
||||||
distance >= 0.0f && distance <= props.distance) {
|
distance >= 0.0f && distance <= props.distance) {
|
||||||
|
|
||||||
collisions.push_back(make_pair(object, 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
|
// Algorithm adapted from https://gamedev.stackexchange.com/a/18459
|
||||||
bool AABB::raycast(const glm::vec3 &origin, const glm::vec3 &invDir, float &distance) const {
|
bool AABB::raycast(const glm::vec3 &origin, const glm::vec3 &dir, float &distance) const {
|
||||||
float tx1 = (_min.x - origin.x) * invDir.x;
|
glm::vec3 dirfrac(1.0f / dir);
|
||||||
float tx2 = (_max.x - origin.x) * invDir.x;
|
|
||||||
float ty1 = (_min.y - origin.y) * invDir.y;
|
float tx1 = (_min.x - origin.x) * dirfrac.x;
|
||||||
float ty2 = (_max.y - origin.y) * invDir.y;
|
float tx2 = (_max.x - origin.x) * dirfrac.x;
|
||||||
float tz1 = (_min.z - origin.z) * invDir.z;
|
float ty1 = (_min.y - origin.y) * dirfrac.y;
|
||||||
float tz2 = (_max.z - origin.z) * invDir.z;
|
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 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));
|
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 < 0.0f) return false; // AABB is behind
|
||||||
if (tmax < tmin) return false; // neither backside nor frontside
|
if (tmax < tmin) return false; // no intersection
|
||||||
|
|
||||||
distance = tmin;
|
distance = tmin;
|
||||||
|
|
||||||
|
@ -149,28 +151,6 @@ glm::vec3 AABB::getSize() const {
|
||||||
return _max - _min;
|
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 graphics
|
||||||
|
|
||||||
} // namespace reone
|
} // namespace reone
|
||||||
|
|
|
@ -43,23 +43,13 @@ public:
|
||||||
* Casts a ray and tests if it intersects this AABB.
|
* Casts a ray and tests if it intersects this AABB.
|
||||||
*
|
*
|
||||||
* @param origin ray origin
|
* @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)
|
* @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;
|
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 &min() const { return _min; }
|
||||||
const glm::vec3 &max() const { return _max; }
|
const glm::vec3 &max() const { return _max; }
|
||||||
const glm::vec3 ¢er() const { return _center; }
|
const glm::vec3 ¢er() const { return _center; }
|
||||||
|
@ -73,8 +63,6 @@ private:
|
||||||
glm::mat4 _transform { 1.0f };
|
glm::mat4 _transform { 1.0f };
|
||||||
|
|
||||||
void updateTransform();
|
void updateTransform();
|
||||||
|
|
||||||
inline glm::vec3 getClosestPoint(const glm::vec3 &point) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|
|
@ -147,9 +147,8 @@ glm::vec2 Mesh::getFaceCenterUV(int faceIdx) const {
|
||||||
if (faceIdx < 0 || faceIdx >= _indices.size() / 3) {
|
if (faceIdx < 0 || faceIdx >= _indices.size() / 3) {
|
||||||
throw out_of_range("faceIdx out of range");
|
throw out_of_range("faceIdx out of range");
|
||||||
}
|
}
|
||||||
if (_offsets.texCoords1 == -1) {
|
if (_offsets.texCoords1 == -1) return glm::vec2(0.0f);
|
||||||
throw logic_error("texCoords1 undefined");
|
|
||||||
}
|
|
||||||
glm::vec2 result(0.0f);
|
glm::vec2 result(0.0f);
|
||||||
const uint16_t *indices = &_indices[3 * faceIdx];
|
const uint16_t *indices = &_indices[3 * faceIdx];
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
@ -159,6 +158,7 @@ glm::vec2 Mesh::getFaceCenterUV(int faceIdx) const {
|
||||||
}
|
}
|
||||||
result /= 3.0f;
|
result /= 3.0f;
|
||||||
result = glm::clamp(result);
|
result = glm::clamp(result);
|
||||||
|
|
||||||
return move(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 &p1 = face.vertices[1];
|
||||||
const glm::vec3 &p2 = face.vertices[2];
|
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;
|
minDistance = localDistance;
|
||||||
material = static_cast<int>(face.material);
|
material = static_cast<int>(face.material);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,17 +74,11 @@ float SceneNode::getDistanceTo2(const glm::vec3 &point) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float SceneNode::getDistanceTo(const SceneNode &other) 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 {
|
float SceneNode::getDistanceTo2(const SceneNode &other) const {
|
||||||
if (!other.isVolumetric()) {
|
return glm::distance2(getOrigin(), other.getOrigin());
|
||||||
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) {
|
void SceneNode::setParent(const SceneNode *parent) {
|
||||||
|
|
Loading…
Reference in a new issue