Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/math/vector.cc @ 6616

Last change on this file since 6616 was 6616, checked in by bensch, 18 years ago

orxonox/trunk: taken the quaternion outside of Vector.cc to quaternion.cc/h

File size: 8.9 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Christian Meyer
13   co-programmer: Patrick Boenzli : Vector::scale()
14                                    Vector::abs()
15
16   Quaternion code borrowed from an Gamasutra article by Nick Bobick and Ken Shoemake
17
18   2005-06-02: Benjamin Grauer: speed up, and new Functionality to Vector (mostly inline now)
19*/
20
21#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_MATH
22
23#include "vector.h"
24#ifdef DEBUG
25  #include "debug.h"
26#else
27  #include <stdio.h>
28  #define PRINT(x) printf
29#endif
30
31using namespace std;
32
33/////////////
34/* VECTORS */
35/////////////
36/**
37 *  returns the this-vector normalized to length 1.0
38 * @todo there is some error in this function, that i could not resolve. it just does not, what it is supposed to do.
39 */
40Vector Vector::getNormalized() const
41{
42  float l = this->len();
43  if(unlikely(l == 1.0 || l == 0.0))
44    return *this;
45  else
46    return (*this / l);
47}
48
49/**
50 *  Vector is looking in the positive direction on all axes after this
51*/
52Vector Vector::abs()
53{
54  Vector v(fabs(x), fabs(y), fabs(z));
55  return v;
56}
57
58
59
60/**
61 *  Outputs the values of the Vector
62 */
63void Vector::debug() const
64{
65  PRINT(0)("x: %f; y: %f; z: %f", x, y, z);
66  PRINT(0)(" lenght: %f", len());
67  PRINT(0)("\n");
68}
69
70/**
71 *  create a rotation from a vector
72 * @param v: a vector
73*/
74Rotation::Rotation (const Vector& v)
75{
76  Vector x = Vector( 1, 0, 0);
77  Vector axis = x.cross( v);
78  axis.normalize();
79  float angle = angleRad( x, v);
80  float ca = cos(angle);
81  float sa = sin(angle);
82  m[0] = 1.0f+(1.0f-ca)*(axis.x*axis.x-1.0f);
83  m[1] = -axis.z*sa+(1.0f-ca)*axis.x*axis.y;
84  m[2] = axis.y*sa+(1.0f-ca)*axis.x*axis.z;
85  m[3] = axis.z*sa+(1.0f-ca)*axis.x*axis.y;
86  m[4] = 1.0f+(1.0f-ca)*(axis.y*axis.y-1.0f);
87  m[5] = -axis.x*sa+(1.0f-ca)*axis.y*axis.z;
88  m[6] = -axis.y*sa+(1.0f-ca)*axis.x*axis.z;
89  m[7] = axis.x*sa+(1.0f-ca)*axis.y*axis.z;
90  m[8] = 1.0f+(1.0f-ca)*(axis.z*axis.z-1.0f);
91}
92
93/**
94 *  creates a rotation from an axis and an angle (radians!)
95 * @param axis: the rotational axis
96 * @param angle: the angle in radians
97*/
98Rotation::Rotation (const Vector& axis, float angle)
99{
100  float ca, sa;
101  ca = cos(angle);
102  sa = sin(angle);
103  m[0] = 1.0f+(1.0f-ca)*(axis.x*axis.x-1.0f);
104  m[1] = -axis.z*sa+(1.0f-ca)*axis.x*axis.y;
105  m[2] = axis.y*sa+(1.0f-ca)*axis.x*axis.z;
106  m[3] = axis.z*sa+(1.0f-ca)*axis.x*axis.y;
107  m[4] = 1.0f+(1.0f-ca)*(axis.y*axis.y-1.0f);
108  m[5] = -axis.x*sa+(1.0f-ca)*axis.y*axis.z;
109  m[6] = -axis.y*sa+(1.0f-ca)*axis.x*axis.z;
110  m[7] = axis.x*sa+(1.0f-ca)*axis.y*axis.z;
111  m[8] = 1.0f+(1.0f-ca)*(axis.z*axis.z-1.0f);
112}
113
114/**
115 *  creates a rotation from euler angles (pitch/yaw/roll)
116 * @param pitch: rotation around z (in radians)
117 * @param yaw: rotation around y (in radians)
118 * @param roll: rotation around x (in radians)
119*/
120Rotation::Rotation ( float pitch, float yaw, float roll)
121{
122  float cy, sy, cr, sr, cp, sp;
123  cy = cos(yaw);
124  sy = sin(yaw);
125  cr = cos(roll);
126  sr = sin(roll);
127  cp = cos(pitch);
128  sp = sin(pitch);
129  m[0] = cy*cr;
130  m[1] = -cy*sr;
131  m[2] = sy;
132  m[3] = cp*sr+sp*sy*cr;
133  m[4] = cp*cr-sp*sr*sy;
134  m[5] = -sp*cy;
135  m[6] = sp*sr-cp*sy*cr;
136  m[7] = sp*cr+cp*sy*sr;
137  m[8] = cp*cy;
138}
139
140/**
141 *  creates a nullrotation (an identity rotation)
142*/
143Rotation::Rotation ()
144{
145  m[0] = 1.0f;
146  m[1] = 0.0f;
147  m[2] = 0.0f;
148  m[3] = 0.0f;
149  m[4] = 1.0f;
150  m[5] = 0.0f;
151  m[6] = 0.0f;
152  m[7] = 0.0f;
153  m[8] = 1.0f;
154}
155
156/**
157 *  fills the specified buffer with a 4x4 glmatrix
158 * @param buffer: Pointer to an array of 16 floats
159
160   Use this to get the rotation in a gl-compatible format
161*/
162void Rotation::glmatrix (float* buffer)
163{
164        buffer[0] = m[0];
165        buffer[1] = m[3];
166        buffer[2] = m[6];
167        buffer[3] = m[0];
168        buffer[4] = m[1];
169        buffer[5] = m[4];
170        buffer[6] = m[7];
171        buffer[7] = m[0];
172        buffer[8] = m[2];
173        buffer[9] = m[5];
174        buffer[10] = m[8];
175        buffer[11] = m[0];
176        buffer[12] = m[0];
177        buffer[13] = m[0];
178        buffer[14] = m[0];
179        buffer[15] = m[1];
180}
181
182/**
183 *  multiplies two rotational matrices
184 * @param r: another Rotation
185 * @return the matrix product of the Rotations
186
187   Use this to rotate one rotation by another
188*/
189Rotation Rotation::operator* (const Rotation& r)
190{
191        Rotation p;
192
193        p.m[0] = m[0]*r.m[0] + m[1]*r.m[3] + m[2]*r.m[6];
194        p.m[1] = m[0]*r.m[1] + m[1]*r.m[4] + m[2]*r.m[7];
195        p.m[2] = m[0]*r.m[2] + m[1]*r.m[5] + m[2]*r.m[8];
196
197        p.m[3] = m[3]*r.m[0] + m[4]*r.m[3] + m[5]*r.m[6];
198        p.m[4] = m[3]*r.m[1] + m[4]*r.m[4] + m[5]*r.m[7];
199        p.m[5] = m[3]*r.m[2] + m[4]*r.m[5] + m[5]*r.m[8];
200
201        p.m[6] = m[6]*r.m[0] + m[7]*r.m[3] + m[8]*r.m[6];
202        p.m[7] = m[6]*r.m[1] + m[7]*r.m[4] + m[8]*r.m[7];
203        p.m[8] = m[6]*r.m[2] + m[7]*r.m[5] + m[8]*r.m[8];
204
205        return p;
206}
207
208
209/**
210 *  rotates the vector by the given rotation
211 * @param v: a vector
212 * @param r: a rotation
213 * @return the rotated vector
214*/
215Vector rotateVector( const Vector& v, const Rotation& r)
216{
217  Vector t;
218
219  t.x = v.x * r.m[0] + v.y * r.m[1] + v.z * r.m[2];
220  t.y = v.x * r.m[3] + v.y * r.m[4] + v.z * r.m[5];
221  t.z = v.x * r.m[6] + v.y * r.m[7] + v.z * r.m[8];
222
223  return t;
224}
225
226/**
227 *  calculate the distance between two lines
228 * @param l: the other line
229 * @return the distance between the lines
230*/
231float Line::distance (const Line& l) const
232{
233  float q, d;
234  Vector n = a.cross(l.a);
235  q = n.dot(r-l.r);
236  d = n.len();
237  if( d == 0.0) return 0.0;
238  return q/d;
239}
240
241/**
242 *  calculate the distance between a line and a point
243 * @param v: the point
244 * @return the distance between the Line and the point
245*/
246float Line::distancePoint (const Vector& v) const
247{
248  Vector d = v-r;
249  Vector u = a * d.dot( a);
250  return (d - u).len();
251}
252
253/**
254 *  calculate the distance between a line and a point
255 * @param v: the point
256 * @return the distance between the Line and the point
257 */
258float Line::distancePoint (const sVec3D& v) const
259{
260  Vector s(v[0], v[1], v[2]);
261  Vector d = s - r;
262  Vector u = a * d.dot( a);
263  return (d - u).len();
264}
265
266/**
267 *  calculate the two points of minimal distance of two lines
268 * @param l: the other line
269 * @return a Vector[2] (!has to be deleted after use!) containing the two points of minimal distance
270*/
271Vector* Line::footpoints (const Line& l) const
272{
273  Vector* fp = new Vector[2];
274  Plane p = Plane (r + a.cross(l.a), r, r + a);
275  fp[1] = p.intersectLine (l);
276  p = Plane (fp[1], l.a);
277  fp[0] = p.intersectLine (*this);
278  return fp;
279}
280
281/**
282  \brief calculate the length of a line
283  \return the lenght of the line
284*/
285float Line::len() const
286{
287  return a.len();
288}
289
290/**
291 *  rotate the line by given rotation
292 * @param rot: a rotation
293*/
294void Line::rotate (const Rotation& rot)
295{
296  Vector t = a + r;
297  t = rotateVector( t, rot);
298  r = rotateVector( r, rot),
299  a = t - r;
300}
301
302/**
303 *  create a plane from three points
304 * @param a: first point
305 * @param b: second point
306 * @param c: third point
307*/
308Plane::Plane (const Vector& a, const Vector& b, const Vector& c)
309{
310  n = (a-b).cross(c-b);
311  k = -(n.x*b.x+n.y*b.y+n.z*b.z);
312}
313
314/**
315 *  create a plane from anchor point and normal
316 * @param norm: normal vector
317 * @param p: anchor point
318*/
319Plane::Plane (const Vector& norm, const Vector& p)
320{
321  n = norm;
322  k = -(n.x*p.x+n.y*p.y+n.z*p.z);
323}
324
325
326/**
327  *  create a plane from anchor point and normal
328  * @param norm: normal vector
329  * @param p: anchor point
330*/
331Plane::Plane (const Vector& norm, const sVec3D& g)
332{
333  Vector p(g[0], g[1], g[2]);
334  n = norm;
335  k = -(n.x*p.x+n.y*p.y+n.z*p.z);
336}
337
338
339/**
340 *  returns the intersection point between the plane and a line
341 * @param l: a line
342*/
343Vector Plane::intersectLine (const Line& l) const
344{
345  if (n.x*l.a.x+n.y*l.a.y+n.z*l.a.z == 0.0) return Vector(0,0,0);
346  float t = (n.x*l.r.x+n.y*l.r.y+n.z*l.r.z+k) / (n.x*l.a.x+n.y*l.a.y+n.z*l.a.z);
347  return l.r + (l.a * t);
348}
349
350/**
351 *  returns the distance between the plane and a point
352 * @param p: a Point
353 * @return the distance between the plane and the point (can be negative)
354*/
355float Plane::distancePoint (const Vector& p) const
356{
357  float l = n.len();
358  if( l == 0.0) return 0.0;
359  return (n.dot(p) + k) / n.len();
360}
361
362
363/**
364 *  returns the distance between the plane and a point
365 * @param p: a Point
366 * @return the distance between the plane and the point (can be negative)
367 */
368float Plane::distancePoint (const sVec3D& p) const
369{
370  Vector s(p[0], p[1], p[2]);
371  float l = n.len();
372  if( l == 0.0) return 0.0;
373  return (n.dot(s) + k) / n.len();
374}
375
376
377/**
378 *  returns the side a point is located relative to a Plane
379 * @param p: a Point
380 * @return 0 if the point is contained within the Plane, positive(negative) if the point is in the positive(negative) semi-space of the Plane
381*/
382float Plane::locatePoint (const Vector& p) const
383{
384  return (n.dot(p) + k);
385}
386
Note: See TracBrowser for help on using the repository browser.