Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/environment/src/libraries/util/Math.cc @ 8416

Last change on this file since 8416 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
Line 
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
29/**
30    @file
31    @brief Implementation of several math-functions.
32*/
33
34#include "Math.h"
35
36#include <OgrePlane.h>
37
38#include "MathConvert.h"
39#include "SubString.h"
40// Do not remove this include, it avoids linker errors.
41#include "mbool.h"
42
43namespace orxonox
44{
45#if OGRE_VERSION < 0x010603
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    }
54
55    /**
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    /**
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    }
75
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    }
86
87
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
93        @return The angle in radian
94
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.
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    }
109
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
117
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>.
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;
128
129        // project difference vector on our plane
130        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
131
132        float projectionlength = projection.length();
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        }
140
141        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
142        float sin_value = sqrt( 1 - cos_value*cos_value );
143
144        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
145            return orxonox::Vector2( sin_value, cos_value );
146        else
147            return orxonox::Vector2( -sin_value, cos_value );
148    }
149
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
157
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>.
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;
168
169        // project difference vector on our plane
170        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
171
172        float projectionlength = projection.length();
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        }
180        //float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
181
182        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
183        float sin_value = sqrt( 1 - cos_value*cos_value );
184
185        float distancelength = distance.length();
186        if (distancelength == 0) return orxonox::Vector2(0, 0);
187        float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / math::pi;
188
189        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
190            return orxonox::Vector2( sin_value * radius, cos_value * radius);
191        else
192            return orxonox::Vector2( -sin_value * radius, cos_value * radius);
193    }
194
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
202
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();
212
213        float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c;
214        if (temp < 0)
215            return orxonox::Vector3::ZERO;
216
217        temp = sqrt(temp);
218        float time = (temp + a) / (2 * (squaredProjectilespeed - b));
219        return (targetposition + targetvelocity * time);
220    }
221
222    /**
223        @brief Returns a unique number. This function will never return the same value twice.
224    */
225    unsigned long getUniqueNumber()
226    {
227        static unsigned long aNumber = 135;
228        return aNumber++;
229    }
230
231
232    //////////////////////////
233    // Conversion functions //
234    //////////////////////////
235
236    // std::string to Vector2
237    bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
238    {
239        size_t opening_parenthesis, closing_parenthesis = input.find('}');
240        if ((opening_parenthesis = input.find('{')) == std::string::npos)
241            opening_parenthesis = 0;
242        else
243            opening_parenthesis++;
244
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        {
249            if (!convertValue(&(output->x), tokens[0]))
250                return false;
251            if (!convertValue(&(output->y), tokens[1]))
252                return false;
253
254            return true;
255        }
256        return false;
257    }
258
259    // std::string to Vector3
260    bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
261    {
262        size_t opening_parenthesis, closing_parenthesis = input.find('}');
263        if ((opening_parenthesis = input.find('{')) == std::string::npos)
264            opening_parenthesis = 0;
265        else
266            opening_parenthesis++;
267
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        {
272            if (!convertValue(&(output->x), tokens[0]))
273                return false;
274            if (!convertValue(&(output->y), tokens[1]))
275                return false;
276            if (!convertValue(&(output->z), tokens[2]))
277                return false;
278
279            return true;
280        }
281        return false;
282    }
283
284    // std::string to Vector4
285    bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
286    {
287        size_t opening_parenthesis, closing_parenthesis = input.find('}');
288        if ((opening_parenthesis = input.find('{')) == std::string::npos)
289            opening_parenthesis = 0;
290        else
291            opening_parenthesis++;
292
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        {
297            if (!convertValue(&(output->x), tokens[0]))
298                return false;
299            if (!convertValue(&(output->y), tokens[1]))
300                return false;
301            if (!convertValue(&(output->z), tokens[2]))
302                return false;
303            if (!convertValue(&(output->w), tokens[3]))
304                return false;
305
306            return true;
307        }
308        return false;
309    }
310
311    // std::string to Quaternion
312    bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
313    {
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++;
319
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        {
323            if (!convertValue(&(output->w), tokens[0]))
324                return false;
325            if (!convertValue(&(output->x), tokens[1]))
326                return false;
327            if (!convertValue(&(output->y), tokens[2]))
328                return false;
329            if (!convertValue(&(output->z), tokens[3]))
330                return false;
331
332            return true;
333        }
334        return false;
335    }
336
337    // std::string to ColourValue
338    bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
339    {
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++;
345
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)
348        {
349            if (!convertValue(&(output->r), tokens[0]))
350                return false;
351            if (!convertValue(&(output->g), tokens[1]))
352                return false;
353            if (!convertValue(&(output->b), tokens[2]))
354                return false;
355            if (tokens.size() >= 4)
356            {
357                if (!convertValue(&(output->a), tokens[3]))
358                    return false;
359            }
360            else
361                output->a = 1.0;
362
363            return true;
364        }
365        return false;
366    }
367}
Note: See TracBrowser for help on using the repository browser.