Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/Math.h @ 11751

Last change on this file since 11751 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 12.4 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
[9939]25 *      Wolfgang Roenninger
[1505]26 *
27 */
28
[1791]29/**
[7401]30    @defgroup Math Mathematical functions
31    @ingroup Util
32*/
33
34/**
[2171]35    @file
[7401]36    @ingroup Math
[1791]37    @brief Declaration and implementation of several math-functions, typedefs of some Ogre::Math classes to the orxonox namespace.
38*/
39
[1505]40#ifndef _Util_Math_H__
41#define _Util_Math_H__
42
43#include "UtilPrereqs.h"
44
[1625]45#include <string>
[2171]46#include <cmath>
[7427]47#include <cstdlib>
[11071]48#include <random>
49#include <type_traits>
[1505]50
51#include <OgreMath.h>
52#include <OgreVector2.h>
53#include <OgreVector3.h>
54#include <OgreVector4.h>
55#include <OgreQuaternion.h>
56#include <OgreColourValue.h>
57
[3214]58// Certain headers might define unwanted macros...
59#undef max
60#undef min
61#undef sgn
62#undef clamp
63#undef sqrt
64#undef square
65#undef mod
66#undef rnd
[1781]67
[2171]68namespace orxonox
[1505]69{
[8351]70    /** Often used numerical constants because C++ doesn't define any.
71    @note
72        The values here are decimal representations of the approximate floating
73        point value as it is stored according to the IEEE 754 standard.
74    */
[7184]75    namespace math
76    {
[11071]77        constexpr float twoPi   = 6.283185482025146484375f;     ///< PI * 2
78        constexpr float pi      = 3.1415927410125732421875f;    ///< PI
79        constexpr float pi_2    = 1.57079637050628662109375f;   ///< PI / 2
80        constexpr float pi_4    = 0.785398185253143310546875f;  ///< PI / 4
81        constexpr float e       = 2.718281269073486328125f;     ///< e
82        constexpr float sqrt2   = 1.41421353816986083984375f;   ///< sqrt(2)
83        constexpr float sqrt2_2 = 0.707106769084930419921875f;  ///< sqrt(2) / 2
[7184]84    }
85
[6417]86#if OGRE_VERSION < 0x010603
[2171]87    _UtilExport std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian);
[6417]88    _UtilExport std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree);
89#endif
[2171]90    _UtilExport std::istream& operator>>(std::istream& in, orxonox::Radian& radian);
91    _UtilExport std::istream& operator>>(std::istream& in, orxonox::Degree& degree);
[1505]92
[2171]93    _UtilExport float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition);
94    _UtilExport orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition);
[11052]95    _UtilExport orxonox::Vector2 get2DViewCoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition);
[9939]96    _UtilExport orxonox::Vector2 get3DProjection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle, const float detectionlimit);
97    _UtilExport bool isObjectHigherThanShipOnMap(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle);
98    _UtilExport int determineMap3DZOrder(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float detectionlimit);
99    _UtilExport orxonox::Vector3 getTransformedVector(const orxonox::Vector3& distance, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& myside);
[2171]100    _UtilExport orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity);
[1505]101
[2171]102    /**
103        @brief Returns the sign of the given value.
104        @param x The value
105        @return 1 if the value is positive or zero, -1 if the value is negative
106    */
107    template <typename T>
[11071]108    constexpr inline T sgn(T x)
[2171]109    {
[6502]110        return (x >= 0) ? (T)1 : (T)-1;
[2171]111    }
[1505]112
[2171]113    /**
[7401]114        @brief Keeps a value between a lower and an upper limit. Values beyond these limits are limited to either @a min or @a max.
[2171]115        @param x The value
116        @param min The lower limit
117        @param max The upper limit
118    */
119    template <typename T>
[11071]120    constexpr inline T clamp(T x, T min, T max)
[2171]121    {
[11071]122        return x < min ? min : (x > max ? max : x);
[2171]123    }
[1505]124
[2171]125    /**
[7401]126        @brief Returns the squared value (x^2).
[2171]127    */
128    template <typename T>
[11071]129    constexpr inline T square(T x)
[2171]130    {
131        return x*x;
132    }
[1505]133
[2171]134    /**
[7401]135        @brief Returns the cubed value (x^3).
[2171]136    */
137    template <typename T>
[11071]138    constexpr inline T cube(T x)
[2171]139    {
140        return x*x*x;
141    }
[1505]142
[2171]143    /**
144        @brief The modulo operation, enhanced to work properly with negative values.
145        @param x The value
146        @param max The operand
[7401]147
148        The built in modulo operator % yields a strange behavior with negative values.
149        This function corrects this - the result is guaranteed to lie always between
150        zero and (max-1).
151
152        Example:
153        @code
154        int var = 11 % 10;      //  1
155        int var = -1 % 10;      // -1
156
157        int var = mod(11, 10);  //  1
158        int var = mod(-1, 10);  //  9
159        @endcode
[2171]160    */
161    template <typename T>
162    inline int mod(T x, int max)
163    {
164        if (x >= 0)
165            return (x % max);
166        else
[8706]167        {
168            T temp = x % max;
169            return (temp < 0) ? (temp + max) : temp;
170        }
[2171]171    }
[2087]172
[7401]173    /**
174        @brief Returns a "zero" value for the given type.
175        @note This is the default template of the zeroise() function. The template is spezialized for each supported type.
176
177        The exact return value of the function depends on the type. For @c int this is 0,
178        for @c float it's 0.0f. For a @c std::string the function returns "" and for
179        @c Vector3 you get <tt>Vector3(0, 0, 0)</tt>.
180    */
[11071]181    template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, T>::type
182    inline /*T*/ zeroise()
[2171]183    {
[11071]184        // If you reach this code, you abused zeroise()!
185        static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
[2171]186    }
[11071]187    /// Implementation for enum classes: uses the underlying type to create a zero value.
188    template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, T>::type
189    inline /*T*/ zeroise()
190    {
191        return static_cast<T>(zeroise<typename std::underlying_type<T>::type>());
192    }
[2087]193
[2171]194    template <> inline char                 zeroise<char>()                 { return 0; }
195    template <> inline unsigned char        zeroise<unsigned char>()        { return 0; }
196    template <> inline short                zeroise<short>()                { return 0; }
197    template <> inline unsigned short       zeroise<unsigned short>()       { return 0; }
198    template <> inline int                  zeroise<int>()                  { return 0; }
199    template <> inline unsigned int         zeroise<unsigned int>()         { return 0; }
200    template <> inline long                 zeroise<long>()                 { return 0; }
201    template <> inline unsigned long        zeroise<unsigned long>()        { return 0; }
202    template <> inline long long            zeroise<long long>()            { return 0; }
203    template <> inline unsigned long long   zeroise<unsigned long long>()   { return 0; }
204    template <> inline float                zeroise<float>()                { return 0; }
205    template <> inline double               zeroise<double>()               { return 0; }
206    template <> inline long double          zeroise<long double>()          { return 0; }
207    template <> inline bool                 zeroise<bool>()                 { return 0; }
[11071]208    template <> inline void*                zeroise<void*>()                { return nullptr; }
[6417]209    template <> inline std::string          zeroise<std::string>()          { return std::string(); }
[2171]210    template <> inline orxonox::Radian      zeroise<orxonox::Radian>()      { return orxonox::Radian(0.0f); }
211    template <> inline orxonox::Degree      zeroise<orxonox::Degree>()      { return orxonox::Degree(0.0f); }
212    template <> inline orxonox::Vector2     zeroise<orxonox::Vector2>()     { return orxonox::Vector2    (0, 0)      ; }
213    template <> inline orxonox::Vector3     zeroise<orxonox::Vector3>()     { return orxonox::Vector3    (0, 0, 0)   ; }
214    template <> inline orxonox::Vector4     zeroise<orxonox::Vector4>()     { return orxonox::Vector4    (0, 0, 0, 0); }
215    template <> inline orxonox::ColourValue zeroise<orxonox::ColourValue>() { return orxonox::ColourValue(0, 0, 0, 0); }
216    template <> inline orxonox::Quaternion  zeroise<orxonox::Quaternion>()  { return orxonox::Quaternion (0, 0, 0, 0); }
[1505]217
[7401]218    /**
219        @brief Provides zero value symbols that can be returned as reference
220        @see zeroise()
221    */
[3196]222    template <typename T>
223    struct NilValue
224    {
225        inline operator const T&() const
226        {
227            return value;
228        }
229        static T value;
230    };
231    template <typename T>
232    T NilValue<T>::value = zeroise<T>();
233
[2171]234    /**
235        @brief Interpolates between two values for a time between 0 and 1.
[7401]236        @param time The time is a value between 0 and 1 - the function returns @a start if @a time is 0, @a end if @a time is 1, and interpolates if @a time is between 0 and 1.
237        @param start The value at @a time = 0
238        @param end The value at @a time = 1
239        @return The interpolated value at a given time
[2171]240    */
241    template <typename T>
[3196]242    inline T interpolate(float time, const T& start, const T& end)
[2171]243    {
[9550]244        return static_cast<T>(time * (end - start) + start);
[2171]245    }
[1505]246
[2171]247    /**
248        @brief Interpolates smoothly between two values for a time between 0 and 1. The function starts slowly, increases faster and stops slowly again.
[7401]249        @param time The time is a value between 0 and 1 - the function returns @a start if @a time is 0, @a end if @a time is 1, and interpolates if @a time is between 0 and 1.
250        @param start The value at @a time = 0
251        @param end The value at @a time = 1
252        @return The interpolated value at a given time
[2171]253    */
254    template <typename T>
[3196]255    inline T interpolateSmooth(float time, const T& start, const T& end)
[2171]256    {
[9550]257        return static_cast<T>((-2 * (end - start) * cube(time)) + (3 * (end - start) * square(time)) + start);
[2171]258    }
[1505]259
[11071]260    namespace detail
261    {
262        /**
263        Random number generator used for the functions below. Marked extern to only have one global instance.
264        */
265        _UtilExport extern std::mt19937 rngen;
266    }
267
[2171]268    /**
[11071]269    @brief Seeds the random number generator used for the functions below.
[2171]270    */
[11071]271    inline void rndseed(unsigned int seed)
[2171]272    {
[11071]273        detail::rngen.seed(seed);
[2171]274    }
[1505]275
[2171]276    /**
[11071]277    @brief Returns a random number between @a min and almost @a max: <tt>min <= rnd < max</tt>.
278    @param min The minimum
279    @param max The maximum
[2171]280    */
[11071]281    inline float rnd(float min, float max)
[2171]282    {
[11071]283        std::uniform_real_distribution<float> dist(min, max);
284        return dist(detail::rngen);
[2171]285    }
[1505]286
[2171]287    /**
[11071]288        @brief Returns a random number between 0 and almost 1: <tt>0 <= rnd < 1</tt>.
289    */
290    inline float rnd()
291    {
292        return rnd(0, 1);
293    }
294
295    /**
296        @brief Returns a random number between 0 and almost @a max: <tt>0 <= rnd < max</tt>.
[2171]297        @param max The maximum
298    */
[11071]299    inline float rnd(float max)
[2171]300    {
[11071]301        return rnd(0, max);
[2171]302    }
[1625]303
[2872]304    /**
305        @brief Returns randomly 1 or -1 with equal probability.
306    */
307    inline float rndsgn()
308    {
[11071]309        std::uniform_int_distribution<> dist;
310        return static_cast<float>((dist(detail::rngen) & 0x2) - 1); // dist(...) & 0x2 is either 2 or 0
[2872]311    }
312
[2171]313    _UtilExport unsigned long getUniqueNumber();
314}
315
[1505]316#endif /* _Util_Math_H__ */
Note: See TracBrowser for help on using the repository browser.