Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/util/Math.cc @ 2896

Last change on this file since 2896 was 2171, checked in by landauf, 16 years ago

merged revisions 2111-2170 from objecthierarchy branch back to trunk.

  • Property svn:eol-style set to native
File size: 13.3 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// Do not remove this include to avoid linker errors.
41#include "mbool.h"
42
43namespace orxonox
44{
45    /**
46        @brief Function for writing a Radian to a stream.
47    */
48    std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian)
49    {
50        out << radian.valueRadians();
51        return out;
52    }
53
54    /**
55        @brief Function for reading a Radian from a stream.
56    */
57    std::istream& operator>>(std::istream& in, orxonox::Radian& radian)
58    {
59        float temp;
60        in >> temp;
61        radian = temp;
62        return in;
63    }
64
65    /**
66        @brief Function for writing a Degree to a stream.
67    */
68    std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree)
69    {
70        out << degree.valueDegrees();
71        return out;
72    }
73
74    /**
75        @brief Function for reading a Degree from a stream.
76    */
77    std::istream& operator>>(std::istream& in, orxonox::Degree& degree)
78    {
79        float temp;
80        in >> temp;
81        degree = temp;
82        return in;
83    }
84
85
86    /**
87        @brief Gets the angle between my viewing direction and the direction to the position of the other object.
88        @param myposition My position
89        @param mydirection My viewing direction
90        @param otherposition The position of the other object
91        @return The angle
92
93        @example
94        If the other object is exactly in front of me, the function returns 0.
95        If the other object is exactly behind me, the function returns pi.
96        If the other object is exactly right/left to me (or above/below), the function returns pi/2.
97    */
98    float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition)
99    {
100        orxonox::Vector3 distance = otherposition - myposition;
101        float distancelength = distance.length();
102        if (distancelength == 0)
103            return 0;
104        else
105            return acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1));
106    }
107
108    /**
109        @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object.
110        @param myposition My position
111        @param mydirection My viewing direction
112        @param myorthonormal My orthonormalvector (pointing upwards through my head)
113        @param otherposition The position of the other object
114        @return The viewing direction
115
116        @example
117        If the other object is exactly in front of me, the function returns Vector2(0, 0).
118        If the other object is exactly at my left, the function returns Vector2(-1, 0).
119        If the other object is exactly at my right, the function returns Vector2(1, 0).
120        If the other object is only a bit at my right, the function still returns Vector2(1, 0).
121        If the other object is exactly above me, the function returns Vector2(0, 1).
122    */
123    orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
124    {
125        orxonox::Vector3 distance = otherposition - myposition;
126
127        // project difference vector on our plane
128        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
129
130        float projectionlength = projection.length();
131        if (projectionlength == 0) return orxonox::Vector2(0, 0);
132        float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
133
134        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
135            return orxonox::Vector2(sin(angle), cos(angle));
136        else
137            return orxonox::Vector2(-sin(angle), cos(angle));
138    }
139
140    /**
141        @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).
142        @param myposition My position
143        @param mydirection My viewing direction
144        @param myorthonormal My orthonormalvector (pointing upwards through my head)
145        @param otherposition The position of the other object
146        @return The viewing direction
147
148        @example
149        If the other object is exactly in front of me, the function returns Vector2(0, 0).
150        If the other object is exactly at my left, the function returns Vector2(-0.5, 0).
151        If the other object is exactly at my right, the function returns Vector2(0.5, 0).
152        If the other object is only a bit at my right, the function still returns Vector2(0.01, 0).
153        If the other object is exactly above me, the function returns Vector2(0, 0.5).
154    */
155    orxonox::Vector2 get2DViewcoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
156    {
157        orxonox::Vector3 distance = otherposition - myposition;
158
159        // project difference vector on our plane
160        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
161
162        float projectionlength = projection.length();
163        if (projectionlength == 0) return orxonox::Vector2(0, 0);
164        float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
165
166        float distancelength = distance.length();
167        if (distancelength == 0) return orxonox::Vector2(0, 0);
168        float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / Ogre::Math::PI;
169
170        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
171            return orxonox::Vector2(sin(angle) * radius, cos(angle) * radius);
172        else
173            return orxonox::Vector2(-sin(angle) * radius, cos(angle) * radius);
174    }
175
176    /**
177        @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile.
178        @param myposition My position
179        @param projectilespeed The speed of my projectile
180        @param targetposition The position of my target
181        @param targetvelocity The velocity of my target
182        @return The predicted position
183
184        The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss.
185    */
186    orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity)
187    {
188        float squaredProjectilespeed = projectilespeed * projectilespeed;
189        orxonox::Vector3 distance = targetposition - myposition;
190        float a = distance.squaredLength();
191        float b = 2 * (distance.x + distance.y + distance.z) * (targetvelocity.x + targetvelocity.y + targetvelocity.z);
192        float c = targetvelocity.squaredLength();
193
194        float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c;
195        if (temp < 0)
196            return orxonox::Vector3::ZERO;
197
198        temp = sqrt(temp);
199        float time = (temp + a) / (2 * (squaredProjectilespeed - b));
200        return (targetposition + targetvelocity * time);
201    }
202
203    unsigned long getUniqueNumber()
204    {
205        static unsigned long aNumber = 135;
206        return aNumber++;
207    }
208
209
210    //////////////////////////
211    // Conversion functions //
212    //////////////////////////
213
214    // std::string to Vector2
215    bool 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
238    bool 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
263    bool 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
290    bool 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
313    bool 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    }
339}
Note: See TracBrowser for help on using the repository browser.