/* This file is part of Magnum. Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš 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 */ }}}