|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
to deal in the Software without restriction, including without limitation
|
|
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace Physics {
|
|
|
|
|
/** @page collision-detection Collision detection
|
|
|
|
|
@brief Collection of simple shapes for high performance collision detection.
|
|
|
|
|
|
|
|
|
|
The essential thing in collision detection is to define a complex object with
|
|
|
|
|
collection of simple shapes, for which it is easy to detect collisions. These
|
|
|
|
|
shapes can be either one-, two- or three-dimensional and they can be grouped
|
|
|
|
|
together using various operations.
|
|
|
|
|
|
|
|
|
|
@tableofcontents
|
|
|
|
|
|
|
|
|
|
@section collision-detection-shape-collection Available shapes
|
|
|
|
|
|
|
|
|
|
@subsection collision-detection-shapes1D One-dimensional shapes
|
|
|
|
|
|
|
|
|
|
- @ref Physics::Point "Physics::Point*D" - @copybrief Physics::Point
|
|
|
|
|
- @ref Physics::Line "Physics::Line*D" - @copybrief Physics::Line
|
|
|
|
|
- @ref Physics::LineSegment "Physics::LineSegment*D" - @copybrief Physics::LineSegment
|
|
|
|
|
|
|
|
|
|
Because of numerical instability it's not possible to detect collisions of
|
|
|
|
|
line and point. Collision of two lines can be detected only in 2D.
|
|
|
|
|
|
|
|
|
|
@subsection collision-detection-shapes2D Two-dimensional shapes
|
|
|
|
|
|
|
|
|
|
- Physics::Plane - @copybrief Physics::Plane
|
|
|
|
|
|
|
|
|
|
@subsection collision-detection-shapes3D Three-dimensional shapes
|
|
|
|
|
|
|
|
|
|
- @ref Physics::Sphere "Physics::Sphere*D" - @copybrief Physics::Sphere
|
|
|
|
|
- @ref Physics::Capsule "Physics::Capsule*D" - @copybrief Physics::Capsule
|
|
|
|
|
- @ref Physics::AxisAlignedBox "Physics::AxisAlignedBox*D" - @copybrief Physics::AxisAlignedBox
|
|
|
|
|
- @ref Physics::Box "Physics::Box*D" - @copybrief Physics::Box
|
|
|
|
|
|
|
|
|
|
The easiest (and most efficient) shape combination for detecting collisions
|
|
|
|
|
is point and sphere, followed by two spheres. Computing collision of two boxes
|
|
|
|
|
is least efficient.
|
|
|
|
|
|
|
|
|
|
@section collision-detection-shape-groups Creating hierarchic groups of shapes
|
|
|
|
|
|
|
|
|
|
Shapes can be grouped together using one of three available logical
|
|
|
|
|
operations: AND, OR and NOT. These operations are mapped to operator&&(),
|
|
|
|
|
operator||() and operator!(), so for example creating negation of logical OR
|
|
|
|
|
of line segment and point is simple as this:
|
|
|
|
|
@code
|
|
|
|
|
Physics::LineSegment3D segment;
|
|
|
|
|
Physics::Point3D point;
|
|
|
|
|
|
|
|
|
|
Physics::ShapeGroup3D group = !(segment || point);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@note Logical operations are not the same as set operations -- intersection of
|
|
|
|
|
two spheres will not generate any collision if they are disjoint, but
|
|
|
|
|
logical AND will if the object collides with both of them.
|
|
|
|
|
|
|
|
|
|
The resulting object internally stores copies of both shapes, so the original
|
|
|
|
|
instances can be destroyed. For simple combinations appropriate resulting
|
|
|
|
|
shape is generated (e.g. logical OR of point and sphere can be only the sphere,
|
|
|
|
|
if the point lies inside) and stored inside ShapeGroup instead of two original
|
|
|
|
|
objects.
|
|
|
|
|
|
|
|
|
|
@subsection collision-detection-shape-reference Referencing the shapes for later changes
|
|
|
|
|
|
|
|
|
|
Sometimes you may want to modify the shape based on changes of the object
|
|
|
|
|
itself. In previous example all the shapes were copied into ShapeGroup, so it
|
|
|
|
|
was not possible to change their properties such as sphere radius without
|
|
|
|
|
recreating the group again. You can, however, explicitly pass a reference to
|
|
|
|
|
original object, so you can change it later:
|
|
|
|
|
@code
|
|
|
|
|
Physics::LineSegment3D segment;
|
|
|
|
|
Physics::Point3D point;
|
|
|
|
|
|
|
|
|
|
Physics::ShapeGroup3D group = !(segment || std::ref(point));
|
|
|
|
|
|
|
|
|
|
point.setPosition({1.0f, -6.0f, 0.5f});
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Note that passing a reference implies that you must not destroy the original
|
|
|
|
|
instance (in this case the point). Also because the referenced instance could
|
|
|
|
|
change, there are no shape optimizations done, unlike above.
|
|
|
|
|
|
|
|
|
|
@subsection collision-detection-shape-simplification Providing simplified version of shape for better performance
|
|
|
|
|
|
|
|
|
|
If there are many shapes grouped together, it might hurt performance of
|
|
|
|
|
collision detection, because it might be testing collision with more shapes
|
|
|
|
|
than necessary. It's then good to specify simplified version of such shape,
|
|
|
|
|
so the collision detection is done on the original if and only if collision
|
|
|
|
|
was detected with the simplified shape. It is in fact logical AND using
|
|
|
|
|
operator&&() - the collision is initially detected on first (simplified) shape
|
|
|
|
|
and then on the other:
|
|
|
|
|
@code
|
|
|
|
|
Physics::Sphere3D sphere;
|
|
|
|
|
Physics::Box3D box;
|
|
|
|
|
Physics::AxisAlignedBox3D simplified;
|
|
|
|
|
|
|
|
|
|
Physics::ShapeGroup3D object = simplified && (sphere || box);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section collision-detection-shape-collisions Detecting shape collisions
|
|
|
|
|
|
|
|
|
|
Shape pairs which have collision detection implemented can be tested for
|
|
|
|
|
collision using operator%(), for example:
|
|
|
|
|
@code
|
|
|
|
|
Physics::Point3D point;
|
|
|
|
|
Physics::Sphere3D sphere;
|
|
|
|
|
|
|
|
|
|
bool collide = point % sphere;
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
}}}
|