Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2016 was 2016, checked in by rgrieder, 17 years ago

Merged the changes in Convert.h from core3 branch back.
If it doesn't work, feel free to revert. I have however more or less checked every possible conversion on gcc (tardis) and msvc with a script.

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