Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3814 was 3814, checked in by patrick, 19 years ago

orxonox/trunk: working on vector class, making it more performant by reducing nr of objects created in operators and inlining them

File size: 18.3 KB
Line 
1
2
3/*
4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Christian Meyer
15   co-programmer: Patrick Boenzli : Vector::scale()
16                                    Vector::abs()
17   
18   Quaternion code borrowed from an Gamasutra article by Nick Bobick and Ken Shoemake
19*/
20
21#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_MATH
22
23#include "vector.h"
24#include "debug.h"
25#include "stdincl.h"
26
27using namespace std;
28
29/**
30   \brief add two vectors
31   \param v: the other vector
32   \return the sum of both vectors
33*/
34/*
35Vector Vector::operator+ (const Vector& v) const
36{
37  return Vector(x + v.x, y + v.y, z + v.z);
38}
39*/
40
41/**
42   \brief subtract a vector from another
43   \param v: the other vector
44   \return the difference between the vectors
45*/
46Vector Vector::operator- (const Vector& v) const
47{
48  return Vector(x - v.x, y - v.y, z - v.z);
49}
50
51/**
52   \brief calculate the dot product of two vectors
53   \param v: the other vector
54   \return the dot product of the vectors
55*/
56float Vector::operator* (const Vector& v) const
57{
58  return x * v.x + y * v.y+ z * v.z;
59}
60
61/**
62   \brief multiply a vector with a float
63   \param f: the factor
64   \return the vector multipied by f
65*/
66Vector Vector::operator* (float f) const
67{ 
68  return Vector(x * f, y * f, z * f);
69}
70
71/**
72   \brief divide a vector with a float
73   \param f: the divisor
74   \return the vector divided by f   
75*/
76Vector Vector::operator/ (float f) const
77{
78  __UNLIKELY_IF( f == 0.0)
79  {
80    // Prevent divide by zero
81    return Vector (0,0,0);
82  }
83  return Vector(x / f, y / f, z / f);
84}
85
86/**
87   \brief calculate the dot product of two vectors
88   \param v: the other vector
89   \return the dot product of the vectors
90*/
91float Vector::dot (const Vector& v) const
92{
93  return x*v.x+y*v.y+z*v.z;
94}
95
96/**
97  \brief calculate the cross product of two vectors
98  \param v: the other vector
99        \return the cross product of the vectors
100*/
101Vector Vector::cross (const Vector& v) const
102{
103  return Vector(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x );
104}
105 
106/**
107   \brief normalizes the vector to lenght 1.0
108*/
109void Vector::normalize ()
110{
111  float l = len();
112 
113  __UNLIKELY_IF( l == 0.0)
114  {
115    // Prevent divide by zero
116    return;
117  }
118 
119  x = x / l;
120  y = y / l;
121  z = z / l;
122}
123
124
125/**
126   \brief returns the voctor normalized to length 1.0
127*/
128
129Vector* Vector::getNormalized()
130{
131  float l = len();
132  __UNLIKELY_IF(l != 1.0)
133    {
134      return this;
135    }
136  else __UNLIKELY_IF(l == 0.0)
137    {
138      return 0;
139    }
140
141  return new Vector(x / l, y /l, z / l);
142}
143
144/**
145   \brief scales this Vector with Vector v.
146   \param v the vector to scale this vector with
147*/
148void Vector::scale(const Vector& v)
149{
150  x *= v.x;
151  y *= v.y;
152  z *= v.z;
153}
154
155 
156/**
157   \brief calculates the lenght of the vector
158   \return the lenght of the vector
159*/
160float Vector::len () const
161{
162  return sqrt (x*x+y*y+z*z);
163}
164
165
166/**
167   \brief Vector is looking in the positive direction on all axes after this
168*/
169Vector Vector::abs() 
170{
171  Vector v(fabs(x), fabs(y), fabs(z));
172  return v;
173}
174
175/**
176   \brief calculate the angle between two vectors in radiances
177   \param v1: a vector
178   \param v2: another vector
179   \return the angle between the vectors in radians
180*/
181float angleRad (const Vector& v1, const Vector& v2)
182{
183  return acos( v1 * v2 / (v1.len() * v2.len()));
184}
185
186
187/**
188   \brief calculate the angle between two vectors in degrees
189   \param v1: a vector
190   \param v2: another vector
191   \return the angle between the vectors in degrees
192*/
193float angleDeg (const Vector& v1, const Vector& v2)
194{
195  float f;
196  f = acos( v1 * v2 / (v1.len() * v2.len()));
197  return f * 180 / PI;
198}
199
200
201/**
202   \brief Outputs the values of the Vector
203*/
204void Vector::debug(void)
205{
206  PRINT(0)("Vector Debug information\n");
207  PRINT(0)("x: %f; y: %f; z: %f", x, y, z);
208  PRINT(3)(" lenght: %f", len());
209  PRINT(0)("\n");
210}
211
212/**
213        \brief creates a multiplicational identity Quaternion
214*/
215Quaternion::Quaternion ()
216{
217        w = 1;
218        v = Vector(0,0,0);
219}
220
221/**
222        \brief turns a rotation along an axis into a Quaternion
223        \param angle: the amount of radians to rotate
224        \param axis: the axis to rotate around
225*/
226Quaternion::Quaternion (float angle, const Vector& axis)
227{
228        w = cos(angle/2);
229        v = axis * sin(angle/2);
230}
231
232/**
233   \brief calculates a lookAt rotation
234   \param dir: the direction you want to look
235   \param up: specify what direction up should be
236   
237   Mathematically this determines the rotation a (0,0,1)-Vector has to undergo to point
238   the same way as dir. If you want to use this with cameras, you'll have to reverse the
239   dir Vector (Vector(0,0,0) - your viewing direction) or you'll point the wrong way. You
240   can use this for meshes as well (then you do not have to reverse the vector), but keep
241   in mind that if you do that, the model's front has to point in +z direction, and left
242   and right should be -x or +x respectively or the mesh wont rotate correctly.
243*/
244Quaternion::Quaternion (const Vector& dir, const Vector& up)
245{
246  Vector z = dir;
247  z.normalize(); 
248  Vector x = up.cross(z);
249  x.normalize(); 
250  Vector y = z.cross(x);
251 
252  float m[4][4];
253  m[0][0] = x.x;
254  m[0][1] = x.y;
255  m[0][2] = x.z;
256  m[0][3] = 0;
257  m[1][0] = y.x;
258  m[1][1] = y.y;
259  m[1][2] = y.z;
260  m[1][3] = 0;
261  m[2][0] = z.x;
262  m[2][1] = z.y;
263  m[2][2] = z.z;
264  m[2][3] = 0;
265  m[3][0] = 0;
266  m[3][1] = 0;
267  m[3][2] = 0;
268  m[3][3] = 1;
269 
270  *this = Quaternion (m);
271}
272
273/**
274        \brief calculates a rotation from euler angles
275        \param roll: the roll in radians
276        \param pitch: the pitch in radians
277        \param yaw: the yaw in radians
278       
279        I DO HONESTLY NOT EXACTLY KNOW WHICH ANGLE REPRESENTS WHICH ROTATION. And I do not know
280        in what order they are applied, I just copy-pasted the code.
281*/
282Quaternion::Quaternion (float roll, float pitch, float yaw)
283{
284        float cr, cp, cy, sr, sp, sy, cpcy, spsy;
285       
286        // calculate trig identities
287        cr = cos(roll/2);
288        cp = cos(pitch/2);
289        cy = cos(yaw/2);
290       
291        sr = sin(roll/2);
292        sp = sin(pitch/2);
293        sy = sin(yaw/2);
294       
295        cpcy = cp * cy;
296        spsy = sp * sy;
297       
298        w = cr * cpcy + sr * spsy;
299        v.x = sr * cpcy - cr * spsy;
300        v.y = cr * sp * cy + sr * cp * sy;
301        v.z = cr * cp * sy - sr * sp * cy;
302}
303
304/**
305        \brief rotates one Quaternion by another
306        \param q: another Quaternion to rotate this by
307        \return a quaternion that represents the first one rotated by the second one (WARUNING: this operation is not commutative! e.g. (A*B) != (B*A))
308*/
309Quaternion Quaternion::operator*(const Quaternion& q) const
310{
311        float A, B, C, D, E, F, G, H;
312        Quaternion r;
313       
314        A = (w   + v.x)*(q.w   + q.v.x);
315        B = (v.z - v.y)*(q.v.y - q.v.z);
316        C = (w   - v.x)*(q.v.y + q.v.z); 
317        D = (v.y + v.z)*(q.w   - q.v.x);
318        E = (v.x + v.z)*(q.v.x + q.v.y);
319        F = (v.x - v.z)*(q.v.x - q.v.y);
320        G = (w   + v.y)*(q.w   - q.v.z);
321        H = (w   - v.y)*(q.w   + q.v.z);
322       
323        r.w = B +  (-E - F + G + H)/2;
324        r.v.x = A - (E + F + G + H)/2; 
325        r.v.y = C + (E - F + G - H)/2; 
326        r.v.z = D + (E - F - G + H)/2;
327       
328        return r;
329}
330
331/**
332        \brief add two Quaternions
333        \param q: another Quaternion
334        \return the sum of both Quaternions
335*/
336Quaternion Quaternion::operator+(const Quaternion& q) const
337{
338  Quaternion r(*this);
339  r.w = r.w + q.w;
340  r.v = r.v + q.v;
341  return r;
342}
343
344/**
345   \brief subtract two Quaternions
346   \param q: another Quaternion
347   \return the difference of both Quaternions
348*/
349Quaternion Quaternion::operator- (const Quaternion& q) const
350{
351  Quaternion r(*this);
352  r.w = r.w - q.w;
353  r.v = r.v - q.v;
354  return r;
355}
356
357/**
358   \brief rotate a Vector by a Quaternion
359   \param v: the Vector
360   \return a new Vector representing v rotated by the Quaternion
361*/
362Vector Quaternion::apply (Vector& v) const
363{
364  Quaternion q;
365  q.v = v;
366  q.w = 0;
367  q = *this * q * conjugate();
368  return q.v;
369}
370
371/**
372   \brief multiply a Quaternion with a real value
373   \param f: a real value
374   \return a new Quaternion containing the product
375*/
376Quaternion Quaternion::operator*(const float& f) const
377{
378  Quaternion r(*this);
379  r.w = r.w*f;
380  r.v = r.v*f;
381  return r;
382}
383
384/**
385   \brief divide a Quaternion by a real value
386   \param f: a real value
387   \return a new Quaternion containing the quotient
388*/
389Quaternion Quaternion::operator/(const float& f) const
390{
391  if( f == 0) return Quaternion();
392  Quaternion r(*this);
393  r.w = r.w/f;
394  r.v = r.v/f;
395  return r;
396}
397
398/**
399   \brief calculate the conjugate value of the Quaternion
400   \return the conjugate Quaternion
401*/
402Quaternion Quaternion::conjugate() const
403{
404  Quaternion r(*this);
405  r.v = Vector() - r.v;
406  return r;
407}
408
409/**
410   \brief calculate the norm of the Quaternion
411   \return the norm of The Quaternion
412*/
413float Quaternion::norm() const
414{
415  return w*w + v.x*v.x + v.y*v.y + v.z*v.z;
416}
417
418/**
419   \brief calculate the inverse value of the Quaternion
420   \return the inverse Quaternion
421   
422        Note that this is equal to conjugate() if the Quaternion's norm is 1
423*/
424Quaternion Quaternion::inverse() const
425{
426  float n = norm();
427  if (n != 0)
428    {
429      return conjugate() / norm();
430    }
431  else return Quaternion();
432}
433
434/**
435   \brief convert the Quaternion to a 4x4 rotational glMatrix
436   \param m: a buffer to store the Matrix in
437*/
438void Quaternion::matrix (float m[4][4]) const
439{
440  float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; 
441 
442  // calculate coefficients
443  x2 = v.x + v.x;
444  y2 = v.y + v.y; 
445  z2 = v.z + v.z;
446  xx = v.x * x2; xy = v.x * y2; xz = v.x * z2;
447  yy = v.y * y2; yz = v.y * z2; zz = v.z * z2;
448  wx = w * x2; wy = w * y2; wz = w * z2;
449 
450  m[0][0] = 1.0 - (yy + zz); m[1][0] = xy - wz;
451  m[2][0] = xz + wy; m[3][0] = 0.0;
452       
453  m[0][1] = xy + wz; m[1][1] = 1.0 - (xx + zz);
454  m[2][1] = yz - wx; m[3][1] = 0.0;
455 
456  m[0][2] = xz - wy; m[1][2] = yz + wx;
457  m[2][2] = 1.0 - (xx + yy); m[3][2] = 0.0;
458 
459  m[0][3] = 0; m[1][3] = 0;
460  m[2][3] = 0; m[3][3] = 1;
461}
462
463/**
464   \brief performs a smooth move.
465   \param from from where
466   \param to to where
467   \param t the time this transformation should take
468   \param res The approximation-density
469*/
470void Quaternion::quatSlerp(const Quaternion* from, const Quaternion* to, float t, Quaternion* res)
471{
472  float tol[4];
473  double omega, cosom, sinom, scale0, scale1;
474  DELTA = 0.2;
475
476  cosom = from->v.x * to->v.x + from->v.y * to->v.y + from->v.z * to->v.z + from->w * to->w;
477
478  if( cosom < 0.0 ) 
479    { 
480      cosom = -cosom; 
481      tol[0] = -to->v.x;
482      tol[1] = -to->v.y;
483      tol[2] = -to->v.z;
484      tol[3] = -to->w;
485    }
486  else
487    {
488      tol[0] = to->v.x;
489      tol[1] = to->v.y;
490      tol[2] = to->v.z;
491      tol[3] = to->w;
492    }
493 
494  //if( (1.0 - cosom) > DELTA )
495  //{
496      omega = acos(cosom);
497      sinom = sin(omega);
498      scale0 = sin((1.0 - t) * omega) / sinom;
499      scale1 = sin(t * omega) / sinom;
500      //}
501      /*
502  else
503    {
504      scale0 = 1.0 - t;
505      scale1 = t;
506    }
507      */
508  res->v.x = scale0 * from->v.x + scale1 * tol[0];
509  res->v.y = scale0 * from->v.y + scale1 * tol[1];
510  res->v.z = scale0 * from->v.z + scale1 * tol[2];
511  res->w = scale0 * from->w + scale1 * tol[3];
512}
513
514
515/**
516   \brief convert a rotational 4x4 glMatrix into a Quaternion
517   \param m: a 4x4 matrix in glMatrix order
518*/
519Quaternion::Quaternion (float m[4][4])
520{
521       
522  float  tr, s, q[4];
523  int    i, j, k;
524
525  int nxt[3] = {1, 2, 0};
526
527  tr = m[0][0] + m[1][1] + m[2][2];
528
529        // check the diagonal
530  if (tr > 0.0) 
531  {
532    s = sqrt (tr + 1.0);
533    w = s / 2.0;
534    s = 0.5 / s;
535    v.x = (m[1][2] - m[2][1]) * s;
536    v.y = (m[2][0] - m[0][2]) * s;
537    v.z = (m[0][1] - m[1][0]) * s;
538        } 
539        else 
540        {
541                // diagonal is negative
542        i = 0;
543        if (m[1][1] > m[0][0]) i = 1;
544    if (m[2][2] > m[i][i]) i = 2;
545    j = nxt[i];
546    k = nxt[j];
547
548    s = sqrt ((m[i][i] - (m[j][j] + m[k][k])) + 1.0);
549     
550    q[i] = s * 0.5;
551           
552    if (s != 0.0) s = 0.5 / s;
553       
554          q[3] = (m[j][k] - m[k][j]) * s;
555    q[j] = (m[i][j] + m[j][i]) * s;
556    q[k] = (m[i][k] + m[k][i]) * s;
557
558        v.x = q[0];
559        v.y = q[1];
560        v.z = q[2];
561        w = q[3];
562  }
563}
564
565/**
566   \brief outputs some nice formated debug information about this quaternion
567*/
568void Quaternion::debug(void)
569{
570  PRINT(0)("Quaternion Debug Information\n");
571  PRINT(0)("real a=%f; imag: x=%f y=%f z=%f\n", w, v.x, v.y, v.z);
572}
573
574/**
575   \brief create a rotation from a vector
576   \param v: a vector
577*/
578Rotation::Rotation (const Vector& v)
579{
580  Vector x = Vector( 1, 0, 0);
581  Vector axis = x.cross( v);
582  axis.normalize();
583  float angle = angleRad( x, v);
584  float ca = cos(angle);
585  float sa = sin(angle);
586  m[0] = 1.0f+(1.0f-ca)*(axis.x*axis.x-1.0f);
587  m[1] = -axis.z*sa+(1.0f-ca)*axis.x*axis.y;
588  m[2] = axis.y*sa+(1.0f-ca)*axis.x*axis.z;
589  m[3] = axis.z*sa+(1.0f-ca)*axis.x*axis.y;
590  m[4] = 1.0f+(1.0f-ca)*(axis.y*axis.y-1.0f);
591  m[5] = -axis.x*sa+(1.0f-ca)*axis.y*axis.z;
592  m[6] = -axis.y*sa+(1.0f-ca)*axis.x*axis.z;
593  m[7] = axis.x*sa+(1.0f-ca)*axis.y*axis.z;
594  m[8] = 1.0f+(1.0f-ca)*(axis.z*axis.z-1.0f);
595}
596
597/**
598   \brief creates a rotation from an axis and an angle (radians!)
599   \param axis: the rotational axis
600   \param angle: the angle in radians
601*/
602Rotation::Rotation (const Vector& axis, float angle)
603{
604  float ca, sa;
605  ca = cos(angle);
606  sa = sin(angle);
607  m[0] = 1.0f+(1.0f-ca)*(axis.x*axis.x-1.0f);
608  m[1] = -axis.z*sa+(1.0f-ca)*axis.x*axis.y;
609  m[2] = axis.y*sa+(1.0f-ca)*axis.x*axis.z;
610  m[3] = axis.z*sa+(1.0f-ca)*axis.x*axis.y;
611  m[4] = 1.0f+(1.0f-ca)*(axis.y*axis.y-1.0f);
612  m[5] = -axis.x*sa+(1.0f-ca)*axis.y*axis.z;
613  m[6] = -axis.y*sa+(1.0f-ca)*axis.x*axis.z;
614  m[7] = axis.x*sa+(1.0f-ca)*axis.y*axis.z;
615  m[8] = 1.0f+(1.0f-ca)*(axis.z*axis.z-1.0f);
616}
617
618/**
619   \brief creates a rotation from euler angles (pitch/yaw/roll)
620   \param pitch: rotation around z (in radians)
621   \param yaw: rotation around y (in radians)
622   \param roll: rotation around x (in radians)
623*/
624Rotation::Rotation ( float pitch, float yaw, float roll)
625{
626  float cy, sy, cr, sr, cp, sp;
627  cy = cos(yaw);
628  sy = sin(yaw);
629  cr = cos(roll);
630  sr = sin(roll);
631  cp = cos(pitch);
632  sp = sin(pitch);
633  m[0] = cy*cr;
634  m[1] = -cy*sr;
635  m[2] = sy;
636  m[3] = cp*sr+sp*sy*cr;
637  m[4] = cp*cr-sp*sr*sy;
638  m[5] = -sp*cy;
639  m[6] = sp*sr-cp*sy*cr;
640  m[7] = sp*cr+cp*sy*sr;
641  m[8] = cp*cy;
642}
643
644/**
645   \brief creates a nullrotation (an identity rotation)
646*/
647Rotation::Rotation ()
648{
649  m[0] = 1.0f;
650  m[1] = 0.0f;
651  m[2] = 0.0f;
652  m[3] = 0.0f;
653  m[4] = 1.0f;
654  m[5] = 0.0f;
655  m[6] = 0.0f;
656  m[7] = 0.0f;
657  m[8] = 1.0f;
658}
659
660/**
661   \brief fills the specified buffer with a 4x4 glmatrix
662   \param buffer: Pointer to an array of 16 floats
663   
664   Use this to get the rotation in a gl-compatible format
665*/
666void Rotation::glmatrix (float* buffer)
667{
668        buffer[0] = m[0];
669        buffer[1] = m[3];
670        buffer[2] = m[6];
671        buffer[3] = m[0];
672        buffer[4] = m[1];
673        buffer[5] = m[4];
674        buffer[6] = m[7];
675        buffer[7] = m[0];
676        buffer[8] = m[2];
677        buffer[9] = m[5];
678        buffer[10] = m[8];
679        buffer[11] = m[0];
680        buffer[12] = m[0];
681        buffer[13] = m[0];
682        buffer[14] = m[0];
683        buffer[15] = m[1];
684}
685
686/**
687   \brief multiplies two rotational matrices
688   \param r: another Rotation
689   \return the matrix product of the Rotations
690   
691   Use this to rotate one rotation by another
692*/
693Rotation Rotation::operator* (const Rotation& r)
694{
695        Rotation p;
696       
697        p.m[0] = m[0]*r.m[0] + m[1]*r.m[3] + m[2]*r.m[6];
698        p.m[1] = m[0]*r.m[1] + m[1]*r.m[4] + m[2]*r.m[7];
699        p.m[2] = m[0]*r.m[2] + m[1]*r.m[5] + m[2]*r.m[8];
700       
701        p.m[3] = m[3]*r.m[0] + m[4]*r.m[3] + m[5]*r.m[6];
702        p.m[4] = m[3]*r.m[1] + m[4]*r.m[4] + m[5]*r.m[7];
703        p.m[5] = m[3]*r.m[2] + m[4]*r.m[5] + m[5]*r.m[8];
704
705        p.m[6] = m[6]*r.m[0] + m[7]*r.m[3] + m[8]*r.m[6];
706        p.m[7] = m[6]*r.m[1] + m[7]*r.m[4] + m[8]*r.m[7];
707        p.m[8] = m[6]*r.m[2] + m[7]*r.m[5] + m[8]*r.m[8];
708       
709        return p;
710}
711
712
713/**
714   \brief rotates the vector by the given rotation
715   \param v: a vector
716   \param r: a rotation
717   \return the rotated vector
718*/
719Vector rotateVector( const Vector& v, const Rotation& r)
720{
721  Vector t;
722 
723  t.x = v.x * r.m[0] + v.y * r.m[1] + v.z * r.m[2];
724  t.y = v.x * r.m[3] + v.y * r.m[4] + v.z * r.m[5];
725  t.z = v.x * r.m[6] + v.y * r.m[7] + v.z * r.m[8];
726
727  return t;
728}
729
730/**
731   \brief calculate the distance between two lines
732   \param l: the other line
733   \return the distance between the lines
734*/
735float Line::distance (const Line& l) const
736{
737  float q, d;
738  Vector n = a.cross(l.a);
739  q = n.dot(r-l.r);
740  d = n.len();
741  if( d == 0.0) return 0.0;
742  return q/d;
743}
744
745/**
746   \brief calculate the distance between a line and a point
747   \param v: the point
748   \return the distance between the Line and the point
749*/
750float Line::distancePoint (const Vector& v) const
751{
752  Vector d = v-r;
753  Vector u = a * d.dot( a);
754  return (d - u).len();
755}
756
757/**
758   \brief calculate the two points of minimal distance of two lines
759   \param l: the other line
760   \return a Vector[2] (!has to be deleted after use!) containing the two points of minimal distance
761*/
762Vector* Line::footpoints (const Line& l) const
763{
764  Vector* fp = new Vector[2];
765  Plane p = Plane (r + a.cross(l.a), r, r + a);
766  fp[1] = p.intersectLine (l);
767  p = Plane (fp[1], l.a);
768  fp[0] = p.intersectLine (*this);
769  return fp;
770}
771
772/**
773  \brief calculate the length of a line
774  \return the lenght of the line
775*/
776float Line::len() const
777{
778  return a.len();
779}
780
781/**
782   \brief rotate the line by given rotation
783   \param rot: a rotation
784*/
785void Line::rotate (const Rotation& rot)
786{
787  Vector t = a + r;
788  t = rotateVector( t, rot);
789  r = rotateVector( r, rot),
790  a = t - r;
791}
792
793/**
794   \brief create a plane from three points
795   \param a: first point
796   \param b: second point
797   \param c: third point
798*/
799Plane::Plane (Vector a, Vector b, Vector c)
800{
801  n = (a-b).cross(c-b);
802  k = -(n.x*b.x+n.y*b.y+n.z*b.z);
803}
804
805/**
806   \brief create a plane from anchor point and normal
807   \param norm: normal vector
808   \param p: anchor point
809*/
810Plane::Plane (Vector norm, Vector p)
811{
812  n = norm;
813  k = -(n.x*p.x+n.y*p.y+n.z*p.z);
814}
815
816/**
817   \brief returns the intersection point between the plane and a line
818   \param l: a line
819*/
820Vector Plane::intersectLine (const Line& l) const
821{
822  if (n.x*l.a.x+n.y*l.a.y+n.z*l.a.z == 0.0) return Vector(0,0,0);
823  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);
824  return l.r + (l.a * t);
825}
826
827/**
828   \brief returns the distance between the plane and a point
829   \param p: a Point
830   \return the distance between the plane and the point (can be negative)
831*/
832float Plane::distancePoint (const Vector& p) const
833{
834  float l = n.len();
835  if( l == 0.0) return 0.0;
836  return (n.dot(p) + k) / n.len();
837}
838
839/**
840   \brief returns the side a point is located relative to a Plane
841   \param p: a Point
842   \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
843*/
844float Plane::locatePoint (const Vector& p) const
845{
846  return (n.dot(p) + k);
847}
848
Note: See TracBrowser for help on using the repository browser.