Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy/src/util/Math.cc @ 2155

Last change on this file since 2155 was 2111, checked in by rgrieder, 16 years ago

Moved all util classes and functions to orxonox namespace.
Converted all code to 4 spaces/tab in util.

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