Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pickups2/src/util/Math.cc @ 2706

Last change on this file since 2706 was 2087, checked in by landauf, 16 years ago

merged objecthierarchy branch back to trunk

  • 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
204
205//////////////////////////
206// Conversion functions //
207//////////////////////////
208
209// std::string to Vector2
210bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
211{
212    size_t opening_parenthesis, closing_parenthesis = input.find(')');
213    if ((opening_parenthesis = input.find('(')) == std::string::npos)
214        opening_parenthesis = 0;
215    else
216        opening_parenthesis++;
217
218    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
219                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
220    if (tokens.size() >= 2)
221    {
222        if (!ConvertValue(&(output->x), tokens[0]))
223            return false;
224        if (!ConvertValue(&(output->y), tokens[1]))
225            return false;
226
227        return true;
228    }
229    return false;
230}
231
232// std::string to Vector3
233bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
234{
235    size_t opening_parenthesis, closing_parenthesis = input.find(')');
236    if ((opening_parenthesis = input.find('(')) == std::string::npos)
237        opening_parenthesis = 0;
238    else
239        opening_parenthesis++;
240
241    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
242                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
243    if (tokens.size() >= 3)
244    {
245        if (!ConvertValue(&(output->x), tokens[0]))
246            return false;
247        if (!ConvertValue(&(output->y), tokens[1]))
248            return false;
249        if (!ConvertValue(&(output->z), tokens[2]))
250            return false;
251
252        return true;
253    }
254    return false;
255}
256
257// std::string to Vector4
258bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
259{
260    size_t opening_parenthesis, closing_parenthesis = input.find(')');
261    if ((opening_parenthesis = input.find('(')) == std::string::npos)
262        opening_parenthesis = 0;
263    else
264        opening_parenthesis++;
265
266    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
267                     ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
268    if (tokens.size() >= 4)
269    {
270        if (!ConvertValue(&(output->x), tokens[0]))
271            return false;
272        if (!ConvertValue(&(output->y), tokens[1]))
273            return false;
274        if (!ConvertValue(&(output->z), tokens[2]))
275            return false;
276        if (!ConvertValue(&(output->w), tokens[3]))
277            return false;
278
279        return true;
280    }
281    return false;
282}
283
284// std::string to Quaternion
285bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
286{
287    size_t opening_parenthesis, closing_parenthesis = input.find(')');
288    if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
289
290    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
291    if (tokens.size() >= 4)
292    {
293        if (!ConvertValue(&(output->w), tokens[0]))
294            return false;
295        if (!ConvertValue(&(output->x), tokens[1]))
296            return false;
297        if (!ConvertValue(&(output->y), tokens[2]))
298            return false;
299        if (!ConvertValue(&(output->z), tokens[3]))
300            return false;
301
302        return true;
303    }
304    return false;
305}
306
307// std::string to ColourValue
308bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
309{
310    size_t opening_parenthesis, closing_parenthesis = input.find(')');
311    if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
312
313    SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
314    if (tokens.size() >= 3)
315    {
316        if (!ConvertValue(&(output->r), tokens[0]))
317            return false;
318        if (!ConvertValue(&(output->g), tokens[1]))
319            return false;
320        if (!ConvertValue(&(output->b), tokens[2]))
321            return false;
322        if (tokens.size() >= 4)
323        {
324            if (!ConvertValue(&(output->a), tokens[3]))
325                return false;
326        }
327        else
328            output->a = 1.0;
329
330        return true;
331    }
332    return false;
333}
Note: See TracBrowser for help on using the repository browser.