template<UnsignedInt dimensions> Collision<dimensions> InvertedSphere<dimensions>::operator/(const Point<dimensions>& other) const { const typename DimensionTraits<dimensions, Float>::VectorType separating = other.position() - position(); const Float dot = separating.dot(); /* No collision occured */ if(dot < Math::pow<2>(radius())) return {}; /* Actual distance from the center */ const Float distance = Math::sqrt(dot); /* Separating normal */ const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = separating/distance; /* Collision position is on the point */ return Collision<dimensions>(other.position(), separatingNormal, distance - radius()); }
template<UnsignedInt dimensions> Collision<dimensions> InvertedSphere<dimensions>::operator/(const Sphere<dimensions>& other) const { const Float maxDistance = radius() - other.radius(); /** @todo How to handle inseparable shapes or shapes which can't be separated by movement only (i.e. two half-spaces)? */ CORRADE_INTERNAL_ASSERT(maxDistance > 0.0f); const typename DimensionTraits<dimensions, Float>::VectorType separating = other.position() - position(); const Float dot = separating.dot(); /* No collision occured */ if(dot < Math::pow<2>(maxDistance)) return {}; /* Actual distance */ const Float distance = Math::sqrt(dot); /* Separating normal */ const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = separating/distance; /* Contact position is on the surface of `other`, distance > maxDistance */ return Collision<dimensions>(other.position() + separatingNormal*other.radius(), separatingNormal, distance - maxDistance); }
template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::operator/(const Point<dimensions>& other) const { const typename DimensionTraits<dimensions, Float>::VectorType separating = _position - other.position(); const Float dot = separating.dot(); /* No collision occured */ if(dot > Math::pow<2>(_radius)) return {}; /* Actual distance from the center */ const Float distance = Math::sqrt(dot); /* Separating normal. If can't decide on direction, just move up. */ /** @todo How to handle this in a configurable way? */ const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = Math::TypeTraits<Float>::equals(dot, 0.0f) ? DimensionTraits<dimensions, Float>::VectorType::yAxis() : separating/distance; /* Collision position is on the point */ return Collision<dimensions>(other.position(), separatingNormal, _radius - distance); }
template<UnsignedInt dimensions> Collision<dimensions> Sphere<dimensions>::operator/(const Sphere<dimensions>& other) const { const Float minDistance = _radius + other._radius; const typename DimensionTraits<dimensions, Float>::VectorType separating = _position - other._position; const Float dot = separating.dot(); /* No collision occured */ if(dot > Math::pow<2>(minDistance)) return {}; /* Actual distance */ const Float distance = Math::sqrt(dot); /* Separating normal. If can't decide on direction, just move up. */ /** @todo How to handle this in a configurable way? */ const typename DimensionTraits<dimensions, Float>::VectorType separatingNormal = Math::TypeTraits<Float>::equals(dot, 0.0f) ? DimensionTraits<dimensions, Float>::VectorType::yAxis() : separating/distance; /* Contact position is on the surface of `other`, minDistace > distance */ return Collision<dimensions>(other._position + separatingNormal*other._radius, separatingNormal, minDistance - distance); }