Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ois_update/src/libraries/util/Math.cc @ 7553

Last change on this file since 7553 was 7553, checked in by rgrieder, 14 years ago

Reverted intentional compiler errors generated in the last commit.
And commented erroneous line in Super.h for testing purposes.

  • Property svn:eol-style set to native
File size: 14.1 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:
25 *      ...
26 *
27 */
28
[1791]29/**
[2087]30    @file
[1791]31    @brief Implementation of several math-functions.
32*/
33
[2087]34#include "Math.h"
35
[1564]36#include <OgrePlane.h>
[3196]37
[2087]38#include "MathConvert.h"
39#include "SubString.h"
[3196]40// Do not remove this include, it avoids linker errors.
[2171]41#include "mbool.h"
[1505]42
[2171]43namespace orxonox
[1505]44{
[6417]45#if OGRE_VERSION < 0x010603
[2171]46    /**
47        @brief Function for writing a Radian to a stream.
48    */
49    std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian)
50    {
51        out << radian.valueRadians();
52        return out;
53    }
[1505]54
[2171]55    /**
[6417]56        @brief Function for writing a Degree to a stream.
57    */
58    std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree)
59    {
60        out << degree.valueDegrees();
61        return out;
62    }
63#endif
64
65    /**
[2171]66        @brief Function for reading a Radian from a stream.
67    */
68    std::istream& operator>>(std::istream& in, orxonox::Radian& radian)
69    {
70        float temp;
71        in >> temp;
72        radian = temp;
73        return in;
74    }
[1505]75
[2171]76    /**
77        @brief Function for reading a Degree from a stream.
78    */
79    std::istream& operator>>(std::istream& in, orxonox::Degree& degree)
80    {
81        float temp;
82        in >> temp;
83        degree = temp;
84        return in;
85    }
[1564]86
[1791]87
[2171]88    /**
89        @brief Gets the angle between my viewing direction and the direction to the position of the other object.
90        @param myposition My position
91        @param mydirection My viewing direction
92        @param otherposition The position of the other object
[7401]93        @return The angle in radian
[1564]94
[7401]95        Examples:
96         - If the other object is exactly in front of me, the function returns 0.
97         - If the other object is exactly behind me, the function returns pi.
98         - If the other object is exactly right/left to me (or above/below), the function returns pi/2.
[2171]99    */
100    float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition)
101    {
102        orxonox::Vector3 distance = otherposition - myposition;
103        float distancelength = distance.length();
104        if (distancelength == 0)
105            return 0;
106        else
107            return acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1));
108    }
[1791]109
[2171]110    /**
111        @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object.
112        @param myposition My position
113        @param mydirection My viewing direction
114        @param myorthonormal My orthonormalvector (pointing upwards through my head)
115        @param otherposition The position of the other object
116        @return The viewing direction
[1564]117
[7401]118        Examples:
119         - If the other object is exactly in front of me, the function returns <tt>Vector2(0, 0)</tt>.
120         - If the other object is exactly at my left, the function returns <tt>Vector2(-1, 0)</tt>.
121         - If the other object is exactly at my right, the function returns <tt>Vector2(1, 0)</tt>.
122         - If the other object is only a bit at my right, the function still returns <tt>Vector2(1, 0)</tt>.
123         - If the other object is exactly above me, the function returns <tt>Vector2(0, 1)</tt>.
[2171]124    */
125    orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
126    {
127        orxonox::Vector3 distance = otherposition - myposition;
[1564]128
[2171]129        // project difference vector on our plane
130        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
[1608]131
[2171]132        float projectionlength = projection.length();
[3049]133        if (projectionlength == 0)
134        {
135            if (myposition.dotProduct(otherposition) >= 0)
136                return orxonox::Vector2(0, 0);
137            else
138                return orxonox::Vector2(0, 1);
139        }
[6417]140
[3304]141        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
142        float sin_value = sqrt( 1 - cos_value*cos_value );
[6417]143
[2171]144        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
[3304]145            return orxonox::Vector2( sin_value, cos_value );
[2171]146        else
[3304]147            return orxonox::Vector2( -sin_value, cos_value );
[2171]148    }
[1791]149
[2171]150    /**
151        @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object, multiplied with the viewing distance to the object (0° = 0, 180° = 1).
152        @param myposition My position
153        @param mydirection My viewing direction
154        @param myorthonormal My orthonormalvector (pointing upwards through my head)
155        @param otherposition The position of the other object
156        @return The viewing direction
[1564]157
[7401]158        Examples:
159         - If the other object is exactly in front of me, the function returns <tt>Vector2(0, 0)</tt>.
160         - If the other object is exactly at my left, the function returns <tt>Vector2(-0.5, 0)</tt>.
161         - If the other object is exactly at my right, the function returns <tt>Vector2(0.5, 0)</tt>.
162         - If the other object is only a bit at my right, the function still returns <tt>Vector2(0.01, 0)</tt>.
163         - If the other object is exactly above me, the function returns <tt>Vector2(0, 0.5)</tt>.
[2171]164    */
165    orxonox::Vector2 get2DViewcoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
166    {
167        orxonox::Vector3 distance = otherposition - myposition;
[1564]168
[2171]169        // project difference vector on our plane
170        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
[1608]171
[2171]172        float projectionlength = projection.length();
[3049]173        if (projectionlength == 0)
174        {
175            if (myposition.dotProduct(otherposition) >= 0)
176                return orxonox::Vector2(0, 0);
177            else
178                return orxonox::Vector2(0, 1);
179        }
[3304]180        //float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
[6417]181
[3304]182        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
183        float sin_value = sqrt( 1 - cos_value*cos_value );
[1608]184
[2171]185        float distancelength = distance.length();
186        if (distancelength == 0) return orxonox::Vector2(0, 0);
[7184]187        float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / math::pi;
[1566]188
[2171]189        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
[3304]190            return orxonox::Vector2( sin_value * radius, cos_value * radius);
[2171]191        else
[3304]192            return orxonox::Vector2( -sin_value * radius, cos_value * radius);
[2171]193    }
[1791]194
[2171]195    /**
196        @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile.
197        @param myposition My position
198        @param projectilespeed The speed of my projectile
199        @param targetposition The position of my target
200        @param targetvelocity The velocity of my target
201        @return The predicted position
[1566]202
[2171]203        The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss.
204    */
205    orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity)
206    {
207        float squaredProjectilespeed = projectilespeed * projectilespeed;
208        orxonox::Vector3 distance = targetposition - myposition;
209        float a = distance.squaredLength();
210        float b = 2 * (distance.x + distance.y + distance.z) * (targetvelocity.x + targetvelocity.y + targetvelocity.z);
211        float c = targetvelocity.squaredLength();
[1566]212
[2171]213        float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c;
214        if (temp < 0)
215            return orxonox::Vector3::ZERO;
[1625]216
[2171]217        temp = sqrt(temp);
218        float time = (temp + a) / (2 * (squaredProjectilespeed - b));
219        return (targetposition + targetvelocity * time);
220    }
[1625]221
[7401]222    /**
223        @brief Returns a unique number. This function will never return the same value twice.
224    */
[2171]225    unsigned long getUniqueNumber()
226    {
227        static unsigned long aNumber = 135;
228        return aNumber++;
229    }
[2087]230
231
[2171]232    //////////////////////////
233    // Conversion functions //
234    //////////////////////////
[2087]235
[2171]236    // std::string to Vector2
237    bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
[2087]238    {
[7284]239        size_t opening_parenthesis, closing_parenthesis = input.find('}');
240        if ((opening_parenthesis = input.find('{')) == std::string::npos)
[2171]241            opening_parenthesis = 0;
242        else
243            opening_parenthesis++;
[2087]244
[2171]245        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
246                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
247        if (tokens.size() >= 2)
248        {
[3196]249            if (!convertValue(&(output->x), tokens[0]))
[2171]250                return false;
[3196]251            if (!convertValue(&(output->y), tokens[1]))
[2171]252                return false;
253
254            return true;
255        }
256        return false;
[2087]257    }
258
[2171]259    // std::string to Vector3
260    bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
[2087]261    {
[7284]262        size_t opening_parenthesis, closing_parenthesis = input.find('}');
263        if ((opening_parenthesis = input.find('{')) == std::string::npos)
[2171]264            opening_parenthesis = 0;
265        else
266            opening_parenthesis++;
[2087]267
[2171]268        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
269                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
270        if (tokens.size() >= 3)
271        {
[3196]272            if (!convertValue(&(output->x), tokens[0]))
[2171]273                return false;
[3196]274            if (!convertValue(&(output->y), tokens[1]))
[2171]275                return false;
[3196]276            if (!convertValue(&(output->z), tokens[2]))
[2171]277                return false;
278
279            return true;
280        }
281        return false;
[2087]282    }
283
[2171]284    // std::string to Vector4
285    bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
[2087]286    {
[7284]287        size_t opening_parenthesis, closing_parenthesis = input.find('}');
288        if ((opening_parenthesis = input.find('{')) == std::string::npos)
[2171]289            opening_parenthesis = 0;
290        else
291            opening_parenthesis++;
[2087]292
[2171]293        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
294                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
295        if (tokens.size() >= 4)
296        {
[3196]297            if (!convertValue(&(output->x), tokens[0]))
[2171]298                return false;
[3196]299            if (!convertValue(&(output->y), tokens[1]))
[2171]300                return false;
[3196]301            if (!convertValue(&(output->z), tokens[2]))
[2171]302                return false;
[3196]303            if (!convertValue(&(output->w), tokens[3]))
[2171]304                return false;
305
306            return true;
307        }
308        return false;
[2087]309    }
310
[2171]311    // std::string to Quaternion
312    bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
[2087]313    {
[7284]314        size_t opening_parenthesis, closing_parenthesis = input.find('}');
315        if ((opening_parenthesis = input.find('{')) == std::string::npos)
316            opening_parenthesis = 0;
317        else
318            opening_parenthesis++;
[2087]319
[2171]320        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
321        if (tokens.size() >= 4)
322        {
[3196]323            if (!convertValue(&(output->w), tokens[0]))
[2171]324                return false;
[3196]325            if (!convertValue(&(output->x), tokens[1]))
[2171]326                return false;
[3196]327            if (!convertValue(&(output->y), tokens[2]))
[2171]328                return false;
[3196]329            if (!convertValue(&(output->z), tokens[3]))
[2171]330                return false;
331
332            return true;
333        }
334        return false;
[2087]335    }
336
[2171]337    // std::string to ColourValue
338    bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
339    {
[7284]340        size_t opening_parenthesis, closing_parenthesis = input.find('}');
341        if ((opening_parenthesis = input.find('{')) == std::string::npos)
342            opening_parenthesis = 0;
343        else
344            opening_parenthesis++;
[2087]345
[2171]346        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
347        if (tokens.size() >= 3)
[2087]348        {
[3196]349            if (!convertValue(&(output->r), tokens[0]))
[2087]350                return false;
[3196]351            if (!convertValue(&(output->g), tokens[1]))
[2171]352                return false;
[3196]353            if (!convertValue(&(output->b), tokens[2]))
[2171]354                return false;
355            if (tokens.size() >= 4)
356            {
[3196]357                if (!convertValue(&(output->a), tokens[3]))
[2171]358                    return false;
359            }
360            else
361                output->a = 1.0;
362
363            return true;
[2087]364        }
[2171]365        return false;
[2087]366    }
367}
Note: See TracBrowser for help on using the repository browser.