diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d417876..5bc282c11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ find_package(Corrade REQUIRED) set_parent_scope(MAGNUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") set_parent_scope(MAGNUM_LIBRARY Magnum) +set_parent_scope(MAGNUM_PHYSICS_LIBRARY MagnumPhysics) set_parent_scope(MAGNUM_PRIMITIVES_LIBRARY MagnumPrimitives) set_parent_scope(MAGNUM_MESHTOOLS_LIBRARY MagnumMeshTools) set_parent_scope(MAGNUM_SHADERS_LIBRARY MagnumShaders) diff --git a/doc/CollisionDetection.dox b/doc/CollisionDetection.dox new file mode 100644 index 000000000..e10528713 --- /dev/null +++ b/doc/CollisionDetection.dox @@ -0,0 +1,111 @@ +namespace Magnum { namespace Physics { +/** @page CollisionDetection Collision detection system + +The collision detection system consists of a low-level part, consisting of +shape collection providing collision detection and high-level part, +consisting of rigid bodies and their groups. + +@subpage CollisionDetectionShapes + +@page CollisionDetectionShapes Shapes providing collision detection features + +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 five different set operations. + +@tableofcontents + +@section CollisionDetectionShapeCollection Available shapes + +@subsection CollisionDetectionShapes1D One-dimensional shapes + +- Physics::Point - @copybrief Physics::Point +- Physics::Line - @copybrief Physics::Line +- Physics::LineSegment - @copybrief Physics::LineSegment + +One-dimensional shapes don't provide collision detection with each other +because of numerical instability. + +@subsection CollisionDetectionShapes2D Two-dimensional shapes + +- Physics::Plane - @copybrief Physics::Plane + +@subsection CollisionDetectionShapes3D Three-dimensional shapes + +- Physics::Sphere - @copybrief Physics::Sphere +- Physics::Capsule - @copybrief Physics::Capsule +- Physics::AxisAlignedBox - @copybrief Physics::AxisAlignedBox +- Physics::Box - @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 CollisionDetectionShapeGroups Creating hierarchic groups of shapes + +Shapes can be grouped together using one of five set operations: complement, +union, intersection, difference and XOR. These operations are mapped to +operator~(), operator|(), operator&(), operator-() and operator^(), so for +example creating complement of union of sphere and box is simple as this: +@code +Physics::Sphere sphere; +Physics::Box box; + +Physics::ShapeGroup group = ~(sphere|box); +@endcode + +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. intersection of line and three-dimensional object +can be a line segment) and stored inside ShapeGroup instead of two original +objects. + +@subsection CollisionDetectionShapeReference 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::Sphere sphere; +Physics::Box box; + +Physics::ShapeGroup group = ~(std::ref(sphere)|box); + +sphere.setRadius(2.0f); +@endcode + +Note that passing a reference implies that you must not destroy the original +instance (in this case the sphere). Also because the referenced instance could +change, there are no shape optimizations done, unlike above. + +@subsection CollisionDetectionShapeSimplification 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 intersection group - +the collision is initially detected on first (simplified) shape and then on +the other: +@code +Physics::AxisAlignedBox simplified; + +Physics::ShapeGroup object = simplified & (sphere|box); +@endcode + +@section CollisionDetectionShapeCollisions Detecting shape collisions + +Shape pairs which have collision detection implemented can be tested for +collision using operator%(), for example: +@code +Physics::Point point; +Physics::Sphere sphere; + +bool collide = point % sphere; +@endcode + +*/ +}}} diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 2c09beb5c..cd280e901 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -21,3 +21,10 @@ Basic primitives for testing purposes. Collection of shaders for testing purposes. */ + +/** @namespace Magnum::Physics +@brief %Physics library + +Collision detection system and rigid body objects. See @ref CollisionDetection +for introduction. +*/ diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 48fd4faf1..ff39e28a9 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -5,6 +5,7 @@ # MAGNUM_FOUND - True if Magnum library is found # MAGNUM_INCLUDE_DIR - Include dir for Magnum # MAGNUM_LIBRARY - Magnum library +# MAGNUM_PHYSICS_LIBRARY - Magnum physics library # MAGNUM_PRIMITIVES_LIBRARY - Library with primitives # # MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory @@ -16,7 +17,7 @@ find_package(Corrade REQUIRED) find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) -if (MAGNUM_INCLUDE_DIR AND MAGNUM_LIBRARY AND MAGNUM_PRIMITIVES_LIBRARY AND MAGNUM_MESHTOOLS_LIBRARY AND MAGNUM_SHADERS_LIBRARY) +if (MAGNUM_INCLUDE_DIR AND MAGNUM_LIBRARY AND MAGNUM_PHYSICS_LIBRARY AND MAGNUM_PRIMITIVES_LIBRARY AND MAGNUM_MESHTOOLS_LIBRARY AND MAGNUM_SHADERS_LIBRARY) # Already in cache set(MAGNUM_FOUND TRUE) @@ -24,6 +25,7 @@ if (MAGNUM_INCLUDE_DIR AND MAGNUM_LIBRARY AND MAGNUM_PRIMITIVES_LIBRARY AND MAGN else() # Libraries find_library(MAGNUM_LIBRARY Magnum) + find_library(MAGNUM_PHYSICS_LIBRARY MagnumPhysics) find_library(MAGNUM_PRIMITIVES_LIBRARY MagnumPrimitives) find_library(MAGNUM_MESHTOOLS_LIBRARY MagnumMeshTools) find_library(MAGNUM_SHADERS_LIBRARY MagnumShaders) @@ -38,6 +40,7 @@ else() find_package_handle_standard_args("Magnum" DEFAULT_MSG MAGNUM_INCLUDE_DIR MAGNUM_LIBRARY + MAGNUM_PHYSICS_LIBRARY MAGNUM_PRIMITIVES_LIBRARY MAGNUM_MESHTOOLS_LIBRARY MAGNUM_SHADERS_LIBRARY diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd69d4388..3883a5f9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CORRADE_INCLUDE_DIR}) add_subdirectory(Math) add_subdirectory(MeshTools) +add_subdirectory(Physics) add_subdirectory(Primitives) add_subdirectory(Shaders) diff --git a/src/Physics/AbstractShape.cpp b/src/Physics/AbstractShape.cpp new file mode 100644 index 000000000..da42b21b7 --- /dev/null +++ b/src/Physics/AbstractShape.cpp @@ -0,0 +1,28 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +bool AbstractShape::collides(const AbstractShape* other) const { + /* Operate only with simpler types than this */ + if(static_cast(other->type()) > static_cast(type())) + return other->collides(this); + + return false; +} + +}} diff --git a/src/Physics/AbstractShape.h b/src/Physics/AbstractShape.h new file mode 100644 index 000000000..21199173e --- /dev/null +++ b/src/Physics/AbstractShape.h @@ -0,0 +1,79 @@ +#ifndef Magnum_Physics_AbstractShape_h +#define Magnum_Physics_AbstractShape_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::AbstractShape + */ + +#include "Magnum.h" + +namespace Magnum { namespace Physics { + +/** +@brief Base class for shapes + +See @ref CollisionDetection for brief introduction. +*/ +class PHYSICS_EXPORT AbstractShape { + public: + /** + * @brief Shape type + * + * @internal Sorted by complexity, so the shape which is later in + * the list provides collision detection for previous shapes, not + * the other way around. + */ + enum class Type { + Point, + Line, + LineSegment, + Plane, + Sphere, + Capsule, + AxisAlignedBox, + Box, + ShapeGroup + }; + + /** @brief Destructor */ + virtual inline ~AbstractShape() {} + + /** @brief Shape type */ + virtual Type type() const = 0; + + /** + * @brief Apply transformation + * + * Applies transformation to user-defined shape properties and caches + * them for later usage in collision detection. + */ + virtual void applyTransformation(const Matrix4& transformation) = 0; + + /** + * @brief Detect collision with other shape + * + * Default implementation returns false. + * + * @internal If other shape is more complex than this, returns + * `other->collides(this)`. + */ + virtual bool collides(const AbstractShape* other) const; +}; + +}} + +#endif diff --git a/src/Physics/AxisAlignedBox.cpp b/src/Physics/AxisAlignedBox.cpp new file mode 100644 index 000000000..faa81e229 --- /dev/null +++ b/src/Physics/AxisAlignedBox.cpp @@ -0,0 +1,25 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AxisAlignedBox.h" + +namespace Magnum { namespace Physics { + +void AxisAlignedBox::applyTransformation(const Matrix4& transformation) { + _transformedPosition = (transformation*Vector4(_position)).xyz(); + _transformedSize = transformation.rotationScaling()*_size; +} + +}} diff --git a/src/Physics/AxisAlignedBox.h b/src/Physics/AxisAlignedBox.h new file mode 100644 index 000000000..4e9d848d3 --- /dev/null +++ b/src/Physics/AxisAlignedBox.h @@ -0,0 +1,70 @@ +#ifndef Magnum_Physics_AxisAlignedBox_h +#define Magnum_Physics_AxisAlignedBox_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::AxisAlignedBox + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** @brief Axis aligned box */ +class PHYSICS_EXPORT AxisAlignedBox: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr AxisAlignedBox(const Vector3& position, const Vector3& size): _position(position), _transformedPosition(position), _size(size), _transformedSize(size) {} + + void applyTransformation(const Matrix4& transformation); + + /** @brief Position */ + inline Vector3 position() const { return _position; } + + /** @brief Set position */ + inline void setPosition(const Vector3& position) { + _position = position; + } + + /** @brief Size */ + inline Vector3 size() const { return _size; } + + /** @brief Set size */ + inline void setSize(const Vector3& size) { + _size = size; + } + + /** @brief Transformed position */ + inline Vector3 transformedPosition() const { + return _transformedPosition; + } + + /** @brief Transformed size */ + inline Vector3 transformedSize() const { + return _transformedSize; + } + + protected: + inline Type type() const { return Type::AxisAlignedBox; } + + private: + Vector3 _position, _transformedPosition, + _size, _transformedSize; +}; + +}} + +#endif diff --git a/src/Physics/Box.h b/src/Physics/Box.h new file mode 100644 index 000000000..45420aef6 --- /dev/null +++ b/src/Physics/Box.h @@ -0,0 +1,58 @@ +#ifndef Magnum_Physics_Box_h +#define Magnum_Physics_Box_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Box + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** @brief Unit size box with assigned transformation matrix */ +class Box: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr Box(const Matrix4& transformation): _transformation(transformation), _transformedTransformation(transformation) {} + + inline void applyTransformation(const Matrix4& transformation) { + _transformedTransformation = transformation*_transformation; + } + + /** @brief Transformation */ + inline constexpr Matrix4 transformation() const { return _transformation; } + + /** @brief Set transformation */ + inline Vector3 setTransformation(const Matrix4& transformation) { + _transformation = transformation; + } + + /** @brief Transformed transformation */ + inline constexpr Vector3 transformedTransformation() const { + return _transformedTransformation; + } + + protected: + inline Type type() const { return Type::Box; } + + private: + Vector3 _transformation, _transformedTransformation; +}; + +}} + +#endif diff --git a/src/Physics/CMakeLists.txt b/src/Physics/CMakeLists.txt new file mode 100644 index 000000000..b9ec1a570 --- /dev/null +++ b/src/Physics/CMakeLists.txt @@ -0,0 +1,24 @@ +set(MagnumPhysics_SRCS + AbstractShape.cpp + AxisAlignedBox.cpp + Capsule.cpp + Line.cpp + Plane.cpp + ShapeGroup.cpp + Sphere.cpp +) + +add_library(MagnumPhysics SHARED ${MagnumPhysics_SRCS}) + +if(WIN32) + set_target_properties(MagnumPhysics PROPERTIES COMPILE_FLAGS -DPHYSICS_EXPORTING) +endif() + +target_link_libraries(MagnumPhysics Magnum) + +install(TARGETS MagnumPhysics DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + +if(BUILD_TESTS) + enable_testing() + add_subdirectory(Test) +endif() diff --git a/src/Physics/Capsule.cpp b/src/Physics/Capsule.cpp new file mode 100644 index 000000000..ab09f3bc3 --- /dev/null +++ b/src/Physics/Capsule.cpp @@ -0,0 +1,27 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Capsule.h" + +namespace Magnum { namespace Physics { + +void Capsule::applyTransformation(const Matrix4& transformation) { + _transformedA = (transformation*Vector4(_a)).xyz(); + _transformedB = (transformation*Vector4(_b)).xyz(); + float scaling = (transformation.rotationScaling()*Vector3(1/Math::Constants::Sqrt3)).length(); + _transformedRadius = scaling*_radius; +} + +}} diff --git a/src/Physics/Capsule.h b/src/Physics/Capsule.h new file mode 100644 index 000000000..9578edc65 --- /dev/null +++ b/src/Physics/Capsule.h @@ -0,0 +1,73 @@ +#ifndef Magnum_Physics_Capsule_h +#define Magnum_Physics_Capsule_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Capsule + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** +@brief %Capsule defined by cylinder start and end point and radius + +Unlike other elements the capsule doesn't support asymmetric scaling. When +applying transformation, the scale factor is averaged from all axes. +*/ +class PHYSICS_EXPORT Capsule: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr Capsule(const Vector3& a, const Vector3& b, float radius): _a(a), _transformedA(a), _b(b), _transformedB(b), _radius(radius), _transformedRadius(radius) {} + + void applyTransformation(const Matrix4& transformation); + + inline Vector3 a() const { return _a; } /**< @brief Start point */ + inline Vector3 b() const { return _a; } /**< @brief End point */ + + inline void setA(const Vector3& a) { _a = a; } /**< @brief Set start point */ + inline void setB(const Vector3& b) { _b = b; } /**< @brief Set end point */ + + /** @brief Radius */ + inline float radius() const { return _radius; } + + /** @brief Set radius */ + inline void setRadius(float radius) { _radius = radius; } + + /** @brief Transformed first point */ + inline Vector3 transformedA() const { return _transformedA; } + + /** @brief Transformed second point */ + inline Vector3 transformedB() const { return _transformedB; } + + /** @brief Transformed radius */ + inline float transformedRadius() const { + return _transformedRadius; + } + + protected: + inline Type type() const { return Type::Capsule; } + + private: + Vector3 _a, _transformedA, + _b, _transformedB; + float _radius, _transformedRadius; +}; + +}} + +#endif diff --git a/src/Physics/Line.cpp b/src/Physics/Line.cpp new file mode 100644 index 000000000..0cf2ecc15 --- /dev/null +++ b/src/Physics/Line.cpp @@ -0,0 +1,25 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Line.h" + +namespace Magnum { namespace Physics { + +void Line::applyTransformation(const Matrix4& transformation) { + _transformedA = (transformation*Vector4(_a)).xyz(); + _transformedB = (transformation*Vector4(_b)).xyz(); +} + +}} diff --git a/src/Physics/Line.h b/src/Physics/Line.h new file mode 100644 index 000000000..05b5c7f16 --- /dev/null +++ b/src/Physics/Line.h @@ -0,0 +1,56 @@ +#ifndef Magnum_Physics_Line_h +#define Magnum_Physics_Line_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Line + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** @brief Infinite line, defined by two points */ +class PHYSICS_EXPORT Line: public AbstractShape { + public: + /** @brief Constructor */ + inline Line(const Vector3& a, const Vector3& b): _a(a), _transformedA(a), _b(b), _transformedB(b) {} + + void applyTransformation(const Matrix4& transformation); + + inline Vector3 a() const { return _a; } /**< @brief First point */ + inline Vector3 b() const { return _a; } /**< @brief Second point */ + + inline void setA(const Vector3& a) { _a = a; } /**< @brief Set first point */ + inline void setB(const Vector3& b) { _b = b; } /**< @brief Set second point */ + + /** @brief Transformed first point */ + inline Vector3 transformedA() const { return _transformedA; } + + /** @brief Transformed second point */ + inline Vector3 transformedB() const { return _transformedB; } + + protected: + inline Type type() const { return Type::Line; } + + private: + Vector3 _a, _transformedA, + _b, _transformedB; +}; + +}} + +#endif diff --git a/src/Physics/LineSegment.h b/src/Physics/LineSegment.h new file mode 100644 index 000000000..b0149373c --- /dev/null +++ b/src/Physics/LineSegment.h @@ -0,0 +1,38 @@ +#ifndef Magnum_Physics_LineSegment_h +#define Magnum_Physics_LineSegment_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::LineSegment + */ + +#include "Line.h" + +namespace Magnum { namespace Physics { + +/** @brief %Line segment, defined by starting and ending point */ +class LineSegment: public Line { + public: + /** @brief Constructor */ + LineSegment(const Vector3& a, const Vector3& b): Line(a, b) {} + + protected: + inline Type type() const { return Type::LineSegment; } +}; + +}} + +#endif diff --git a/src/Physics/Plane.cpp b/src/Physics/Plane.cpp new file mode 100644 index 000000000..7301a79d3 --- /dev/null +++ b/src/Physics/Plane.cpp @@ -0,0 +1,25 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Plane.h" + +namespace Magnum { namespace Physics { + +void Plane::applyTransformation(const Matrix4& transformation) { + _transformedPosition = (transformation*Vector4(_position)).xyz(); + _transformedNormal = transformation.rotation()*_normal; +} + +}} diff --git a/src/Physics/Plane.h b/src/Physics/Plane.h new file mode 100644 index 000000000..e7daa7b93 --- /dev/null +++ b/src/Physics/Plane.h @@ -0,0 +1,70 @@ +#ifndef Magnum_Physics_Plane_h +#define Magnum_Physics_Plane_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Plane + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** @brief Infinite plane, defined by position and normal */ +class PHYSICS_EXPORT Plane: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr Plane(const Vector3& position, const Vector3& normal): _position(position), _transformedPosition(position), _normal(normal), _transformedNormal(normal) {} + + void applyTransformation(const Matrix4& transformation); + + /** @brief Position */ + inline Vector3 position() const { return _position; } + + /** @brief Set position */ + inline void setPosition(const Vector3& position) { + _position = position; + } + + /** @brief Normal */ + inline Vector3 normal() const { return _normal; } + + /** @brief Set normal */ + inline void setNormal(const Vector3& normal) { + _normal = normal; + } + + /** @brief Transformed position */ + inline Vector3 transformedPosition() const { + return _transformedPosition; + } + + /** @brief Transformed normal */ + inline Vector3 transformedNormal() const { + return _transformedNormal; + } + + protected: + inline Type type() const { return Type::Plane; } + + private: + Vector3 _position, _transformedPosition, + _normal, _transformedNormal; +}; + +}} + +#endif diff --git a/src/Physics/Point.h b/src/Physics/Point.h new file mode 100644 index 000000000..84218aece --- /dev/null +++ b/src/Physics/Point.h @@ -0,0 +1,58 @@ +#ifndef Magnum_Physics_Point_h +#define Magnum_Physics_Point_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Point + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** @brief %Point */ +class Point: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr Point(const Vector3& position): _position(position), _transformedPosition(position) {} + + inline void applyTransformation(const Matrix4& transformation) { + _transformedPosition = (transformation*Vector4(_position)).xyz(); + } + + /** @brief Position */ + inline Vector3 position() const { return _position; } + + /** @brief Set position */ + inline void setPosition(const Vector3& position) { + _position = position; + } + + /** @brief Transformed position */ + inline Vector3 transformedPosition() const { + return _transformedPosition; + } + + protected: + inline Type type() const { return Type::Point; } + + private: + Vector3 _position, _transformedPosition; +}; + +}} + +#endif diff --git a/src/Physics/ShapeGroup.cpp b/src/Physics/ShapeGroup.cpp new file mode 100644 index 000000000..32aaeaeb5 --- /dev/null +++ b/src/Physics/ShapeGroup.cpp @@ -0,0 +1,65 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "ShapeGroup.h" + +namespace Magnum { namespace Physics { + +ShapeGroup::ShapeGroup(ShapeGroup&& other): operation(other.operation), a(other.a), b(other.b) { + other.operation = AlwaysFalse; + other.a = nullptr; + other.b = nullptr; +} + +ShapeGroup::~ShapeGroup() { + if(!(operation & RefA)) delete a; + if(!(operation & RefB)) delete b; +} + +ShapeGroup& ShapeGroup::operator=(ShapeGroup&& other) { + if(!(operation & RefA)) delete a; + if(!(operation & RefB)) delete b; + + operation = other.operation; + a = other.a; + b = other.b; + + other.operation = AlwaysFalse; + other.a = nullptr; + other.b = nullptr; + + return *this; +} + +void ShapeGroup::applyTransformation(const Matrix4& transformation) { + if(a) a->applyTransformation(transformation); + if(b) b->applyTransformation(transformation); +} + +bool ShapeGroup::collides(const AbstractShape* other) const { + switch(operation & ~RefAB) { + case Complement: return !a->collides(other); + case Union: return a->collides(other) || b->collides(other); + case Intersection: return a->collides(other) && b->collides(other); + case Difference: return a->collides(other) && !b->collides(other); + case Xor: return a->collides(other) != b->collides(other); + case FirstObjectOnly: return a->collides(other); + + default: + return false; + } +} + +}} diff --git a/src/Physics/ShapeGroup.h b/src/Physics/ShapeGroup.h new file mode 100644 index 000000000..72c7e5a2a --- /dev/null +++ b/src/Physics/ShapeGroup.h @@ -0,0 +1,177 @@ +#ifndef Magnum_Physics_ShapeGroup_h +#define Magnum_Physics_ShapeGroup_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::ShapeGroup + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +#ifndef DOXYGEN_GENERATING_OUTPUT +#define enableIfIsBaseType typename std::enable_if::value, ShapeGroup>::type +#define enableIfAreBaseType typename std::enable_if::value && std::is_base_of::value, ShapeGroup>::type +#endif + +/** +@brief Collider group with defined set operation + +Result of union, intersection, substraction or XOR of two collider objects. +See @ref CollisionDetection for brief introduction. +*/ +class PHYSICS_EXPORT ShapeGroup: public AbstractShape { + #ifndef DOXYGEN_GENERATING_OUTPUT + template friend constexpr enableIfIsBaseType operator~(const T& a); + template friend constexpr enableIfIsBaseType operator~(T&& a); + template friend constexpr enableIfIsBaseType operator~(T& a); + + #define friendOp(char) \ + template friend constexpr enableIfAreBaseType operator char(const T& a, const U& b); \ + template friend constexpr enableIfAreBaseType operator char(const T& a, U&& b); \ + template friend constexpr enableIfAreBaseType operator char(T&& a, const U& b); \ + template friend constexpr enableIfAreBaseType operator char(T&& a, U&& b); \ + template friend constexpr enableIfAreBaseType operator char(const T& a, std::reference_wrapper b); \ + template friend constexpr enableIfAreBaseType operator char(T&& a, std::reference_wrapper b); \ + template friend constexpr enableIfAreBaseType operator char(std::reference_wrapper a, const U& b); \ + template friend constexpr enableIfAreBaseType operator char(std::reference_wrapper a, U&& b); \ + template friend constexpr enableIfAreBaseType operator char(std::reference_wrapper a, std::reference_wrapper b); + friendOp(|) + friendOp(&) + friendOp(-) + friendOp(^) + #undef friendOp + #endif + + ShapeGroup(const ShapeGroup& other) = delete; + ShapeGroup& operator=(const ShapeGroup& other) = delete; + + private: + enum Operation { + RefA = 0x01, + RefB = 0x02, + RefAB = 0x03, + Complement = 1 << 2, + Union = 2 << 2, + Intersection = 3 << 2, + Difference = 4 << 2, + Xor = 5 << 2, + FirstObjectOnly = 6 << 2, + AlwaysFalse = 7 << 2 + }; + + public: + /** @brief Default constructor */ + inline ShapeGroup(): operation(AlwaysFalse), a(nullptr), b(nullptr) {} + + /** @brief Move constructor */ + ShapeGroup(ShapeGroup&& other); + + /** @brief Destructor */ + ~ShapeGroup(); + + /** @brief Move assignment */ + ShapeGroup& operator=(ShapeGroup&& other); + + void applyTransformation(const Matrix4& transformation); + + bool collides(const AbstractShape* other) const; + + protected: + virtual Type type() const { return Type::ShapeGroup; } + + private: + inline constexpr ShapeGroup(int operation, AbstractShape* a, AbstractShape* b): operation(operation), a(a), b(b) {} + + int operation; + AbstractShape* a; + AbstractShape* b; +}; + +/** @brief Complement of shape */ +template inline constexpr enableIfIsBaseType operator~(const T& a) { + return ShapeGroup(ShapeGroup::Complement, new T(a), nullptr); +} +#ifndef DOXYGEN_GENERATING_OUTPUT +template inline constexpr enableIfIsBaseType operator~(T&& a) { + return ShapeGroup(ShapeGroup::Complement, new T(std::forward(a)), nullptr); +} +template inline constexpr enableIfIsBaseType operator~(T& a) { + return ShapeGroup(ShapeGroup::Complement|ShapeGroup::RefA, &a.get(), nullptr); +} +#endif + +#ifdef DOXYGEN_GENERATING_OUTPUT +/** @brief Union of two shapes */ +template inline constexpr ShapeGroup operator&(T a, U b); + +/** +@brief Intersection of two shapes + +Collision with @p a is computed first, so this operation can be also used for +providing simplified version for shape @p b. See @ref CollisionDetectionShapeGroups +for an example. +*/ +template inline constexpr ShapeGroup operator&(T a, U b); + +/** @brief Difference of two shapes */ +template inline constexpr ShapeGroup operator-(T a, U b); + +/** @brief XOR of two shapes */ +template inline constexpr ShapeGroup operator^(T a, U b); +#else +#define op(type, char) \ +template inline constexpr enableIfAreBaseType operator char(const T& a, const U& b) { \ + return ShapeGroup(ShapeGroup::type, new T(a), new U(b)); \ +} \ +template inline constexpr enableIfAreBaseType operator char(const T& a, U&& b) { \ + return ShapeGroup(ShapeGroup::type, new T(a), new U(std::forward(b))); \ +} \ +template inline constexpr enableIfAreBaseType operator char(T&& a, const U& b) { \ + return ShapeGroup(ShapeGroup::type, new T(std::forward(a)), new U(b)); \ +} \ +template inline constexpr enableIfAreBaseType operator char(T&& a, U&& b) { \ + return ShapeGroup(ShapeGroup::type, new T(std::forward(a)), new U(std::forward(b))); \ +} \ +template inline constexpr enableIfAreBaseType operator char(const T& a, std::reference_wrapper b) { \ + return ShapeGroup(ShapeGroup::type|ShapeGroup::RefB, new T(a), &b.get()); \ +} \ +template inline constexpr enableIfAreBaseType operator char(T&& a, std::reference_wrapper b) { \ + return ShapeGroup(ShapeGroup::type|ShapeGroup::RefB, new T(std::forward(a)), &b.get()); \ +} \ +template inline constexpr enableIfAreBaseType operator char(std::reference_wrapper a, const U& b) { \ + return ShapeGroup(ShapeGroup::type|ShapeGroup::RefA, &a.get(), new U(b)); \ +} \ +template inline constexpr enableIfAreBaseType operator char(std::reference_wrapper a, U&& b) { \ + return ShapeGroup(ShapeGroup::type|ShapeGroup::RefA, &a.get(), new U(std::forward(b))); \ +} \ +template inline constexpr enableIfAreBaseType operator char(std::reference_wrapper a, std::reference_wrapper b) { \ + return ShapeGroup(ShapeGroup::type|ShapeGroup::RefAB, &a.get(), &b.get()); \ +} +op(Union, |) +op(Intersection, &) +op(Difference, -) +op(Xor, ^) +#undef op +#endif + +#undef enableIfIsBaseType +#undef enableIfAreBaseType + +}} + +#endif diff --git a/src/Physics/Sphere.cpp b/src/Physics/Sphere.cpp new file mode 100644 index 000000000..8e01bd1f4 --- /dev/null +++ b/src/Physics/Sphere.cpp @@ -0,0 +1,26 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Sphere.h" + +namespace Magnum { namespace Physics { + +void Sphere::applyTransformation(const Matrix4& transformation) { + _transformedPosition = (transformation*Vector4(_position)).xyz(); + float scaling = (transformation.rotationScaling()*Vector3(1/Math::Constants::Sqrt3)).length(); + _transformedRadius = scaling*_radius; +} + +}} diff --git a/src/Physics/Sphere.h b/src/Physics/Sphere.h new file mode 100644 index 000000000..87eef0e91 --- /dev/null +++ b/src/Physics/Sphere.h @@ -0,0 +1,71 @@ +#ifndef Magnum_Physics_Sphere_h +#define Magnum_Physics_Sphere_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::Sphere + */ + +#include "AbstractShape.h" + +namespace Magnum { namespace Physics { + +/** +@brief %Sphere defined by position and radius + +Unlike other elements the sphere doesn't support asymmetric scaling. When +applying transformation, the scale factor is averaged from all axes. +*/ +class PHYSICS_EXPORT Sphere: public AbstractShape { + public: + /** @brief Constructor */ + inline constexpr Sphere(const Vector3& position, float radius): _position(position), _transformedPosition(position), _radius(radius), _transformedRadius(radius) {} + + void applyTransformation(const Matrix4& transformation); + + /** @brief Position */ + inline Vector3 position() const { return _position; } + + /** @brief Set position */ + inline void setPosition(const Vector3& position) { _position = position; } + + /** @brief Radius */ + inline float radius() const { return _radius; } + + /** @brief Set radius */ + inline void setRadius(float radius) { _radius = radius; } + + /** @brief Transformed position */ + inline Vector3 transformedPosition() const { + return _transformedPosition; + } + + /** @brief Transformed radius */ + inline float transformedRadius() const { + return _transformedRadius; + } + + protected: + inline Type type() const { return Type::Sphere; } + + private: + Vector3 _position, _transformedPosition; + float _radius, _transformedRadius; +}; + +}} + +#endif diff --git a/src/Physics/Test/AxisAlignedBoxTest.cpp b/src/Physics/Test/AxisAlignedBoxTest.cpp new file mode 100644 index 000000000..c90a549c4 --- /dev/null +++ b/src/Physics/Test/AxisAlignedBoxTest.cpp @@ -0,0 +1,38 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AxisAlignedBoxTest.h" + +#include + +#include "Physics/AxisAlignedBox.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::AxisAlignedBoxTest) + +namespace Magnum { namespace Physics { namespace Test { + +void AxisAlignedBoxTest::applyTransformation() { + Physics::AxisAlignedBox box({-1.0f, -2.0f, -3.0f}, {1.0f, 2.0f, 3.0f}); + + box.applyTransformation(Matrix4::scaling({2.0f, -1.0f, 1.5f})); + QVERIFY((box.transformedPosition() == Vector3(-2.0f, 2.0f, -4.5f))); + QVERIFY((box.transformedSize() == Vector3(2.0f, -2.0f, 4.5f))); + + box.applyTransformation(Matrix4::translation(Vector3(1.0f))*Matrix4::rotation(deg(90.0f), Vector3::xAxis())); + QVERIFY((box.transformedPosition() == Vector3(0.0f, 4.0f, -1.0f))); + QVERIFY((box.transformedSize() == Vector3(1.0f, -3.0f, 2.0f))); +} + +}}} diff --git a/src/Physics/Test/AxisAlignedBoxTest.h b/src/Physics/Test/AxisAlignedBoxTest.h new file mode 100644 index 000000000..fd734336b --- /dev/null +++ b/src/Physics/Test/AxisAlignedBoxTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_AxisAlignedBoxTest_h +#define Magnum_Physics_Test_AxisAlignedBoxTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class AxisAlignedBoxTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/CMakeLists.txt b/src/Physics/Test/CMakeLists.txt new file mode 100644 index 000000000..a95eb3d45 --- /dev/null +++ b/src/Physics/Test/CMakeLists.txt @@ -0,0 +1,7 @@ +corrade_add_test(PhysicsAxisAlignedBoxTest AxisAlignedBoxTest.h AxisAlignedBoxTest.cpp MagnumPhysics) +corrade_add_test(PhysicsCapsuleTest CapsuleTest.h CapsuleTest.cpp MagnumPhysics) +corrade_add_test(PhysicsLineTest LineTest.h LineTest.cpp MagnumPhysics) +corrade_add_test(PhysicsPlaneTest PlaneTest.h PlaneTest.cpp MagnumPhysics) +corrade_add_test(PhysicsPointTest PointTest.h PointTest.cpp MagnumPhysics) +corrade_add_test(PhysicsShapeGroupTest ShapeGroupTest.h ShapeGroupTest.cpp MagnumPhysics) +corrade_add_test(PhysicsSphereTest SphereTest.h SphereTest.cpp MagnumPhysics) diff --git a/src/Physics/Test/CapsuleTest.cpp b/src/Physics/Test/CapsuleTest.cpp new file mode 100644 index 000000000..6f15f3bd3 --- /dev/null +++ b/src/Physics/Test/CapsuleTest.cpp @@ -0,0 +1,39 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "CapsuleTest.h" + +#include + +#include "Physics/Capsule.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::CapsuleTest) + +namespace Magnum { namespace Physics { namespace Test { + +void CapsuleTest::applyTransformation() { + Physics::Capsule capsule({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}, 7.0f); + + capsule.applyTransformation(Matrix4::rotation(deg(90.0f), Vector3::zAxis())); + QVERIFY((capsule.transformedA() == Vector3(-2.0f, 1.0f, 3.0f))); + QVERIFY((capsule.transformedB() == Vector3(2.0f, -1.0f, -3.0f))); + QCOMPARE(capsule.radius(), 7.0f); + + /* Apply average scaling to radius */ + capsule.applyTransformation(Matrix4::scaling({Math::Constants::Sqrt3, -Math::Constants::Sqrt2, 2.0f})); + QCOMPARE(capsule.transformedRadius(), Math::Constants::Sqrt3*7.0f); +} + +}}} diff --git a/src/Physics/Test/CapsuleTest.h b/src/Physics/Test/CapsuleTest.h new file mode 100644 index 000000000..adbd04134 --- /dev/null +++ b/src/Physics/Test/CapsuleTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_CapsuleTest_h +#define Magnum_Physics_Test_CapsuleTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class CapsuleTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/LineTest.cpp b/src/Physics/Test/LineTest.cpp new file mode 100644 index 000000000..372a18820 --- /dev/null +++ b/src/Physics/Test/LineTest.cpp @@ -0,0 +1,33 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "LineTest.h" + +#include + +#include "Physics/Line.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::LineTest) + +namespace Magnum { namespace Physics { namespace Test { + +void LineTest::applyTransformation() { + Physics::Line line({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}); + line.applyTransformation(Matrix4::rotation(deg(90.0f), Vector3::zAxis())); + QVERIFY((line.transformedA() == Vector3(-2.0f, 1.0f, 3.0f))); + QVERIFY((line.transformedB() == Vector3(2.0f, -1.0f, -3.0f))); +} + +}}} diff --git a/src/Physics/Test/LineTest.h b/src/Physics/Test/LineTest.h new file mode 100644 index 000000000..a3a56f4a9 --- /dev/null +++ b/src/Physics/Test/LineTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_LineTest_h +#define Magnum_Physics_Test_LineTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class LineTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/PlaneTest.cpp b/src/Physics/Test/PlaneTest.cpp new file mode 100644 index 000000000..75907c2c1 --- /dev/null +++ b/src/Physics/Test/PlaneTest.cpp @@ -0,0 +1,39 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "PlaneTest.h" + +#include + +#include "Physics/Plane.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::PlaneTest) + +namespace Magnum { namespace Physics { namespace Test { + +void PlaneTest::applyTransformation() { + Physics::Plane plane({1.0f, 2.0f, 3.0f}, {Math::Constants::Sqrt2, -Math::Constants::Sqrt2, 0}); + + plane.applyTransformation(Matrix4::rotation(deg(90.0f), Vector3::xAxis())); + QVERIFY(plane.transformedPosition() == Vector3(1.0f, -3.0f, 2.0f)); + QVERIFY(plane.transformedNormal() == Vector3(Math::Constants::Sqrt2, 0, -Math::Constants::Sqrt2)); + + /* The normal should stay normalized */ + plane.applyTransformation(Matrix4::scaling({1.5f, 2.0f, 3.0f})); + QVERIFY(plane.transformedPosition() == Vector3(1.5f, 4.0f, 9.0f)); + QVERIFY(plane.transformedNormal() == Vector3(Math::Constants::Sqrt2, -Math::Constants::Sqrt2, 0)); +} + +}}} diff --git a/src/Physics/Test/PlaneTest.h b/src/Physics/Test/PlaneTest.h new file mode 100644 index 000000000..51d89b8d0 --- /dev/null +++ b/src/Physics/Test/PlaneTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_PlaneTest_h +#define Magnum_Physics_Test_PlaneTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class PlaneTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/PointTest.cpp b/src/Physics/Test/PointTest.cpp new file mode 100644 index 000000000..473025c92 --- /dev/null +++ b/src/Physics/Test/PointTest.cpp @@ -0,0 +1,32 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "PointTest.h" + +#include + +#include "Physics/Point.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::PointTest) + +namespace Magnum { namespace Physics { namespace Test { + +void PointTest::applyTransformation() { + Physics::Point point({1.0f, 2.0f, 3.0f}); + point.applyTransformation(Matrix4::translation({5.0f, 6.0f, 7.0f})); + QVERIFY((point.transformedPosition() == Vector3(6.0f, 8.0f, 10.0f))); +} + +}}} diff --git a/src/Physics/Test/PointTest.h b/src/Physics/Test/PointTest.h new file mode 100644 index 000000000..6db9f7afa --- /dev/null +++ b/src/Physics/Test/PointTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_PointTest_h +#define Magnum_Physics_Test_PointTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class PointTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/ShapeGroupTest.cpp b/src/Physics/Test/ShapeGroupTest.cpp new file mode 100644 index 000000000..dc222fe5e --- /dev/null +++ b/src/Physics/Test/ShapeGroupTest.cpp @@ -0,0 +1,55 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "ShapeGroupTest.h" + +#include + +#include "Physics/Point.h" +#include "Physics/Sphere.h" +#include "Physics/ShapeGroup.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::ShapeGroupTest) + +using namespace std; + +namespace Magnum { namespace Physics { namespace Test { + +void ShapeGroupTest::copy() { + ShapeGroup group; + { + Physics::Point point({1.0f, 2.0f, 3.0f}); + Physics::Sphere sphere({2.0f, 1.0f, 30.0f}, 1.0f); + + group = ~(point|sphere); + } + + /* Just to test that it doesn't crash */ + group.applyTransformation(Matrix4::translation(Vector3::xAxis(1.0f))); +} + +void ShapeGroupTest::reference() { + Physics::Point point({1.0f, 2.0f, 3.0f}); + Physics::Sphere sphere({2.0f, 1.0f, 30.0f}, 1.0f); + + ShapeGroup group = ~(ref(point)|ref(sphere)); + + group.applyTransformation(Matrix4::translation(Vector3(1.0f))); + + QVERIFY((point.transformedPosition() == Vector3(2.0f, 3.0f, 4.0f))); + QVERIFY((sphere.transformedPosition() == Vector3(3.0f, 2.0f, 31.0f))); +} + +}}} diff --git a/src/Physics/Test/ShapeGroupTest.h b/src/Physics/Test/ShapeGroupTest.h new file mode 100644 index 000000000..640e30d56 --- /dev/null +++ b/src/Physics/Test/ShapeGroupTest.h @@ -0,0 +1,32 @@ +#ifndef Magnum_Physics_Test_ShapeGroupTest_h +#define Magnum_Physics_Test_ShapeGroupTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class ShapeGroupTest: public QObject { + Q_OBJECT + + private slots: + void copy(); + void reference(); +}; + +}}} + +#endif diff --git a/src/Physics/Test/SphereTest.cpp b/src/Physics/Test/SphereTest.cpp new file mode 100644 index 000000000..6846616af --- /dev/null +++ b/src/Physics/Test/SphereTest.cpp @@ -0,0 +1,44 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "SphereTest.h" + +#include +#include "Utility/Debug.h" + +#include "Physics/Sphere.h" + +QTEST_APPLESS_MAIN(Magnum::Physics::Test::SphereTest) + +namespace Magnum { namespace Physics { namespace Test { + +void SphereTest::applyTransformation() { + Physics::Sphere sphere({1.0f, 2.0f, 3.0f}, 7.0f); + + sphere.applyTransformation(Matrix4::rotation(deg(90.0f), Vector3::yAxis())); + QVERIFY((sphere.transformedPosition() == Vector3(3.0f, 2.0f, -1.0f))); + QCOMPARE(sphere.transformedRadius(), 7.0f); + + /* Symmetric scaling */ + sphere.applyTransformation(Matrix4::scaling(Vector3(2.0f))); + QVERIFY((sphere.transformedPosition() == Vector3(2.0f, 4.0f, 6.0f))); + QCOMPARE(sphere.transformedRadius(), 14.0f); + + /* Apply average scaling to radius */ + sphere.applyTransformation(Matrix4::scaling({Math::Constants::Sqrt3, -Math::Constants::Sqrt2, 2.0f})); + QCOMPARE(sphere.transformedRadius(), Math::Constants::Sqrt3*7.0f); +} + +}}} diff --git a/src/Physics/Test/SphereTest.h b/src/Physics/Test/SphereTest.h new file mode 100644 index 000000000..370873e07 --- /dev/null +++ b/src/Physics/Test/SphereTest.h @@ -0,0 +1,31 @@ +#ifndef Magnum_Physics_Test_SphereTest_h +#define Magnum_Physics_Test_SphereTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Physics { namespace Test { + +class SphereTest: public QObject { + Q_OBJECT + + private slots: + void applyTransformation(); +}; + +}}} + +#endif diff --git a/src/utilities.h b/src/utilities.h index ab79e63c2..41955cf98 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -32,9 +32,15 @@ namespace Magnum { #else #define MESHTOOLS_EXPORT __declspec(dllimport) #endif +#ifdef PHYSICS_EXPORTING + #define PHYSICS_EXPORT __declspec(dllexport) +#else + #define PHYSICS_EXPORT __declspec(dllimport) +#endif #else #define MAGNUM_EXPORT #define MESHTOOLS_EXPORT + #define PHYSICS_EXPORT #endif }