Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp6/src/util/Math.cc @ 3258

Last change on this file since 3258 was 3258, checked in by scheusso, 15 years ago

see ticket #329

  • Property svn:eol-style set to native
File size: 13.6 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    /**
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)
132        {
133            if (myposition.dotProduct(otherposition) >= 0)
134                return orxonox::Vector2(0, 0);
135            else
136                return orxonox::Vector2(0, 1);
137        }
138     
139        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
140        float sin_value = sqrt( 1 - cos_value*cos_value );
141     
142        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
143            return orxonox::Vector2( sin_value, cos_value );
144        else
145            return orxonox::Vector2( -sin_value, cos_value );
146    }
147
148    /**
149        @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).
150        @param myposition My position
151        @param mydirection My viewing direction
152        @param myorthonormal My orthonormalvector (pointing upwards through my head)
153        @param otherposition The position of the other object
154        @return The viewing direction
155
156        @example
157        If the other object is exactly in front of me, the function returns Vector2(0, 0).
158        If the other object is exactly at my left, the function returns Vector2(-0.5, 0).
159        If the other object is exactly at my right, the function returns Vector2(0.5, 0).
160        If the other object is only a bit at my right, the function still returns Vector2(0.01, 0).
161        If the other object is exactly above me, the function returns Vector2(0, 0.5).
162    */
163    orxonox::Vector2 get2DViewcoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
164    {
165        orxonox::Vector3 distance = otherposition - myposition;
166
167        // project difference vector on our plane
168        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
169
170        float projectionlength = projection.length();
171        if (projectionlength == 0)
172        {
173            if (myposition.dotProduct(otherposition) >= 0)
174                return orxonox::Vector2(0, 0);
175            else
176                return orxonox::Vector2(0, 1);
177        }
178        float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
179
180        float distancelength = distance.length();
181        if (distancelength == 0) return orxonox::Vector2(0, 0);
182        float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / Ogre::Math::PI;
183
184        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
185            return orxonox::Vector2(sin(angle) * radius, cos(angle) * radius);
186        else
187            return orxonox::Vector2(-sin(angle) * radius, cos(angle) * radius);
188    }
189
190    /**
191        @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile.
192        @param myposition My position
193        @param projectilespeed The speed of my projectile
194        @param targetposition The position of my target
195        @param targetvelocity The velocity of my target
196        @return The predicted position
197
198        The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss.
199    */
200    orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity)
201    {
202        float squaredProjectilespeed = projectilespeed * projectilespeed;
203        orxonox::Vector3 distance = targetposition - myposition;
204        float a = distance.squaredLength();
205        float b = 2 * (distance.x + distance.y + distance.z) * (targetvelocity.x + targetvelocity.y + targetvelocity.z);
206        float c = targetvelocity.squaredLength();
207
208        float temp = 4*squaredProjectilespeed*c + a*a - 4*b*c;
209        if (temp < 0)
210            return orxonox::Vector3::ZERO;
211
212        temp = sqrt(temp);
213        float time = (temp + a) / (2 * (squaredProjectilespeed - b));
214        return (targetposition + targetvelocity * time);
215    }
216
217    unsigned long getUniqueNumber()
218    {
219        static unsigned long aNumber = 135;
220        return aNumber++;
221    }
222
223
224    //////////////////////////
225    // Conversion functions //
226    //////////////////////////
227
228    // std::string to Vector2
229    bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
230    {
231        size_t opening_parenthesis, closing_parenthesis = input.find(')');
232        if ((opening_parenthesis = input.find('(')) == std::string::npos)
233            opening_parenthesis = 0;
234        else
235            opening_parenthesis++;
236
237        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
238                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
239        if (tokens.size() >= 2)
240        {
241            if (!convertValue(&(output->x), tokens[0]))
242                return false;
243            if (!convertValue(&(output->y), tokens[1]))
244                return false;
245
246            return true;
247        }
248        return false;
249    }
250
251    // std::string to Vector3
252    bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
253    {
254        size_t opening_parenthesis, closing_parenthesis = input.find(')');
255        if ((opening_parenthesis = input.find('(')) == std::string::npos)
256            opening_parenthesis = 0;
257        else
258            opening_parenthesis++;
259
260        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
261                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
262        if (tokens.size() >= 3)
263        {
264            if (!convertValue(&(output->x), tokens[0]))
265                return false;
266            if (!convertValue(&(output->y), tokens[1]))
267                return false;
268            if (!convertValue(&(output->z), tokens[2]))
269                return false;
270
271            return true;
272        }
273        return false;
274    }
275
276    // std::string to Vector4
277    bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
278    {
279        size_t opening_parenthesis, closing_parenthesis = input.find(')');
280        if ((opening_parenthesis = input.find('(')) == std::string::npos)
281            opening_parenthesis = 0;
282        else
283            opening_parenthesis++;
284
285        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
286                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
287        if (tokens.size() >= 4)
288        {
289            if (!convertValue(&(output->x), tokens[0]))
290                return false;
291            if (!convertValue(&(output->y), tokens[1]))
292                return false;
293            if (!convertValue(&(output->z), tokens[2]))
294                return false;
295            if (!convertValue(&(output->w), tokens[3]))
296                return false;
297
298            return true;
299        }
300        return false;
301    }
302
303    // std::string to Quaternion
304    bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
305    {
306        size_t opening_parenthesis, closing_parenthesis = input.find(')');
307        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
308
309        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
310        if (tokens.size() >= 4)
311        {
312            if (!convertValue(&(output->w), tokens[0]))
313                return false;
314            if (!convertValue(&(output->x), tokens[1]))
315                return false;
316            if (!convertValue(&(output->y), tokens[2]))
317                return false;
318            if (!convertValue(&(output->z), tokens[3]))
319                return false;
320
321            return true;
322        }
323        return false;
324    }
325
326    // std::string to ColourValue
327    bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
328    {
329        size_t opening_parenthesis, closing_parenthesis = input.find(')');
330        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
331
332        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
333        if (tokens.size() >= 3)
334        {
335            if (!convertValue(&(output->r), tokens[0]))
336                return false;
337            if (!convertValue(&(output->g), tokens[1]))
338                return false;
339            if (!convertValue(&(output->b), tokens[2]))
340                return false;
341            if (tokens.size() >= 4)
342            {
343                if (!convertValue(&(output->a), tokens[3]))
344                    return false;
345            }
346            else
347                output->a = 1.0;
348
349            return true;
350        }
351        return false;
352    }
353}
Note: See TracBrowser for help on using the repository browser.