Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

m_vector.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/07 19:02:06 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: m_vector.cpp,v 1.1.1.1 2002/12/07 19:02:06 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: m_vector.cpp,v $
00030   Revision 1.1.1.1  2002/12/07 19:02:06  kolrabi
00031   initial release
00032 
00033 
00034 */
00035 
00040 #include            "omicron/internal.h" 
00041 #include            <math.h>
00042 
00043 const vec3_t vec3_c::vec3x   = { 1, 0, 0 };
00044 const vec3_t vec3_c::vec3y   = { 0, 1, 0 };
00045 const vec3_t vec3_c::vec3z   = { 0, 0, 1 };
00046 const vec3_t vec3_c::vec30   = { 0, 0, 0 };
00047  
00048 /**************************************************************************** 
00049  **************************************************************************** 
00050  * VECTOR ROUTINES ********************************************************** 
00051  **************************************************************************** 
00052  ****************************************************************************/ 
00053 
00054  
00055 
00056 
00057 /****************************************************************************
00058  * vector_projectonplane                projects a vector on a given plane *
00059  ****************************************************************************/
00060 vec3_c vec3_c::project_on_plane
00061 ( 
00062     const vec3_t normal
00063 )
00064 {
00065     float   d;
00066     vec3_c  n;
00067     float   inv_denom;
00068 
00069     AssertReturnValue1(normal, vec3_c());
00070 
00071     inv_denom = 1.0f / vec3_c(normal).length_squared();
00072 
00073     d = dot(normal) * inv_denom;
00074     n = vec3_c(normal);
00075 
00076     return vec3_c(vec[0] - d * n[0], vec[1] - d * n[1], vec[2] - d * n[2]);
00077 }
00078 
00079 
00080 /****************************************************************************
00081  * vector_perpenticular                           get an orthogonal vector *
00082  ****************************************************************************/
00083 vec3_c vec3_c::perpendicular
00084 ( 
00085 )
00086 {
00087     ulong       pos;
00088     ulong       i;
00089     float       minelem = 1.0F;
00090     vec3_t      tempvec;
00091     vec3_c      res;
00092 
00093     // find the smallest magnitude axially aligned vector
00094     for ( pos = 0, i = 0; i < 3; i++ )
00095     {
00096         if ( fabs( vec[i] ) < minelem )
00097         {
00098             pos     = i;
00099             minelem = (float)fabs( vec[i] );
00100         }
00101     }
00102 
00103     tempvec[0]    = tempvec[1] = tempvec[2] = 0.0f;
00104     tempvec[pos]  = 1.0f;
00105 
00106     // project the point onto the plane defined by src
00107     res = vec3_c(tempvec).project_on_plane( vec );
00108 
00109     // normalize the result
00110     return res.normalize();
00111 }
00112 
00113 /****************************************************************************
00114  * vector_rotate_vec                           rotate vector around vector *
00115  ****************************************************************************/
00116 vec3_c vec3_c::rotate_vec
00117 ( 
00118     float           degrees, 
00119     const vec3_t    dir
00120 )
00121 {
00122     matrix3_t       m;
00123     matrix3_t       im;
00124     matrix3_t       zrot;
00125     matrix3_t       tmpmat;
00126     matrix3_t       rot;
00127     vec3_c          vr, vup;
00128     vec3_t          tmp;
00129 
00130     AssertReturnValue1(dir, vec3_c());
00131 
00132     vr = vec3_c(dir).perpendicular();
00133     vup = vr.cross(dir);
00134 
00135     m[0][0] = vr[0];    m[1][0] = vr[1];   m[2][0] = vr[2];
00136     m[0][1] = vup[0];   m[1][1] = vup[1];  m[2][1] = vup[2];
00137     m[0][2] = dir[0];   m[1][2] = dir[1];  m[2][2] = dir[2];
00138 
00139     memcpy( im, m, sizeof( im ) );
00140 
00141     im[0][1] = m[1][0]; im[0][2] = m[2][0];  im[1][0] = m[0][1];
00142     im[1][2] = m[2][1]; im[2][0] = m[0][2];  im[2][1] = m[1][2];
00143 
00144     memset( zrot, 0, sizeof( zrot ) );
00145     zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
00146 
00147     zrot[0][0] = fcos(DEG2RAD * degrees);
00148     zrot[0][1] = fsin(DEG2RAD * degrees);
00149     zrot[1][0] = -zrot[0][1];   // -sin
00150     zrot[1][1] =  zrot[0][0];   // cos
00151 
00152     matrix3_mult( m, zrot, tmpmat );
00153     matrix3_mult( tmpmat, im, rot );
00154 
00155     tmp[0] = rot[0][0] * vec[0] + rot[0][1] * vec[1] + rot[0][2] * vec[2];
00156     tmp[1] = rot[1][0] * vec[0] + rot[1][1] * vec[1] + rot[1][2] * vec[2];
00157     tmp[2] = rot[2][0] * vec[0] + rot[2][1] * vec[1] + rot[2][2] * vec[2];
00158 
00159     return vec3_c(tmp);
00160 }
00161 
00162 /****************************************************************************
00163  * vector_view_from_angles                      get view vectors by angles *
00164  ****************************************************************************/
00165 void vec3_c::get_view_from_angles
00166 (
00167     vec3_c &forward, 
00168     vec3_c &right, 
00169     vec3_c &up
00170 ) 
00171 {
00172     float   angle;
00173     static float    sr, sp, sy, cr, cp, cy;
00174     // static to help MS compiler fp bugs
00175 
00176     // assumes z is up
00177 
00178     angle = vec[ANGLE_YAW] * DEG2RAD;
00179     sy    = fsin(angle);
00180     cy    = fcos(angle);
00181     angle = vec[ANGLE_PITCH] * DEG2RAD;
00182     sp    = fsin(angle);
00183     cp    = fcos(angle);
00184     angle = vec[ANGLE_ROLL] * DEG2RAD;
00185     sr    = fsin(angle);
00186     cr    = fcos(angle);
00187 
00188     if (forward)
00189         forward.set(cp*cy, cp*sy, -sp);
00190 
00191     if (right)
00192         right.set( (-1*sr*sp*cy+-1*cr*-sy), (-1*sr*sp*sy+-1*cr*cy), -1*sr*cp);
00193     
00194     if (up)
00195         up.set( (cr*sp*cy+-sr*-sy), (cr*sp*sy+-sr*cy), cr*cp);
00196 }
00197 
00198 ushort vec3_c::pack_normal()
00199 {
00200     ulong nx, ny, nz = 0;
00201     nx = (ulong)((vec[0]*63)+63)&127;
00202     ny = (ulong)((vec[1]*63)+63)&127;
00203     
00204     if (vec[2]<0)
00205         nz = 0x8000;
00206 
00207     return (ushort)((nx << 7) | ny | nz);
00208 }
00209 
00210 vec3_c vec3_c::unpack_normal(ushort in)
00211 {
00212     ulong nx, ny, nz;
00213     vec3_c vec;
00214 
00215     nx = (in>>7) & 127;
00216     ny = (in) & 127;
00217     nz = in & 0x8000;
00218 
00219     vec.set( ((float)nx - 63)/64.0f, ((float)ny - 63)/64.0f, 0);
00220 
00221     if (!vec[0] && !vec[1])
00222         vec.set_component(2, 1);
00223     else
00224         vec.set_component(2, (float)sqrt(1-vec.length_squared()));
00225 
00226     if (nz)
00227       vec.set_component(2, -vec[2]);
00228 
00229     return vec.normalize();
00230 }
00231 /*
00232 float vector_intersect_bbox(const vec3_t v, const bbox_t *bbox, collision_t *out)
00233 {
00234     float       t1 = 0, t2 = 0, t = 0;
00235     float       tnear = 0, tfar = 0;
00236     vec3_t      ro, rd, v2;
00237     ulong       a,b;
00238     ulong       side = 0;
00239 
00240     AssertReturnValue3(v,bbox,out,0);
00241 
00242     out->t = 1;
00243   
00244     vector_copy(bbox->pos2, out->pos);
00245     vector_clear(out->normal);
00246     
00247     tnear   = -10000;
00248     tfar    =  10000;
00249 
00250     vector_subtract(bbox->pos1, bbox->pos2, rd);
00251     vector_add(v, rd, v2);
00252     vector_normalize(rd,rd);
00253     vector_subtract(v, bbox->pos1, ro);
00254 
00255     for (a=0; a<3; a++)
00256     {
00257         // not moving
00258         if (rd[a]==0)
00259         {
00260             // and outside of bbox
00261             if (ro[a]<bbox->size[0][a] || ro[a]<bbox->size[0][a])
00262             {
00263                 return 1;
00264             }
00265         }
00266         // moving
00267         else
00268         {
00269             t1 = (bbox->size[0][a]-ro[a])/rd[a];
00270             t2 = (bbox->size[1][a]-ro[a])/rd[a];
00271 
00272             if (t1>t2)
00273             {
00274                 t = t1; t1 = t2; t2 = t;
00275                 b = a+3;
00276             }
00277             else
00278                 b = a;
00279 
00280             if (t1>tnear)
00281             {
00282                 tnear   = t1;
00283                 side    = b;
00284             }
00285 
00286             if (t2<tfar)
00287                 tfar = t2;
00288 
00289             if (tnear>tfar || tfar==0)
00290             {
00291                 return 1;
00292             }
00293         }
00294     }
00295 
00296     if (tnear>tfar || tfar==0)
00297         return 1;
00298 
00299     out->t = 1;
00300     vector_linear(v, v2, out->t, out->pos);
00301 
00302     vector_clear(out->normal);
00303     out->normal[side%3] = side>2?-1.0f:1.0f;
00304 
00305     return t2;
00306 }
00307 */
00308 
00309 
00310 vec3_c vec3_c::bezier_spline
00311 (
00312     const   spline_t    sp,
00313     float   frac
00314 ) 
00315 { 
00316     float invfrac = 1-frac;
00317     float b0      = invfrac * invfrac;
00318     float b1      = 2.0f * frac * invfrac;
00319     float b2      = frac * frac;
00320 
00321     spline_t spline;
00322     
00323     spline[0] = sp[0];
00324     spline[1] = sp[1];
00325     spline[2] = sp[2];
00326 
00327     return spline[0] * b0 + spline[1] * b1 + spline[2] * b2;
00328 } 
00329 
00330 vec3_c vec3_c::bezier_patch
00331 (
00332     const   patch_t     patch,
00333     float   u,
00334     float   v
00335 ) 
00336 { 
00337     AssertReturnValue1(patch, vec3_c());
00338 
00339     spline_t spline;
00340 
00341     spline[0] = bezier_spline(patch[0], u);
00342     spline[1] = bezier_spline(patch[1], u);
00343     spline[2] = bezier_spline(patch[2], u);
00344 
00345     return bezier_spline(spline, v);
00346 } 
00347 
00349 
00350 vec3_c::vec3_c()
00351 {
00352     set(0,0,0);
00353 }
00354 
00355 vec3_c::vec3_c(const vec3_t v)
00356 {
00357     set(v[0], v[1], v[2]);
00358 }
00359 
00360 vec3_c::vec3_c(const vec3_c &v)
00361 {
00362     set(v.vec[0], v.vec[1], v.vec[2]);
00363 }
00364 
00365 vec3_c::vec3_c(float x, float y, float z)
00366 {
00367     set(x,y,z);
00368 }
00369 
00370 vec3_c::~vec3_c()
00371 {
00372 }
00373 
00374 vec3_c::operator const float*()
00375 {
00376     return vec;
00377 }
00378 
00379 // -- 
00380 
00381 void vec3_c::set(float x, float y, float z)
00382 {
00383     vec[0] = x;
00384     vec[1] = y;
00385     vec[2] = z;
00386 }
00387 
00388 void vec3_c::set_component(int n, float x)
00389 {
00390     vec[n] = x;
00391 }
00392 
00393 void vec3_c::clear()
00394 {
00395     set(0,0,0);
00396 }
00397 
00398 float vec3_c::length()
00399 {
00400     return (float)sqrt(
00401         vec[VECT_X]*vec[VECT_X] +
00402         vec[VECT_Y]*vec[VECT_Y] + 
00403         vec[VECT_Z]*vec[VECT_Z]);       // sqrts are slow :( 
00404 }
00405 
00406 float vec3_c::length_squared()
00407 {
00408     return 
00409         vec[VECT_X]*vec[VECT_X] +
00410         vec[VECT_Y]*vec[VECT_Y] + 
00411         vec[VECT_Z]*vec[VECT_Z];
00412 }
00413 
00414 bool vec3_c::operator ==(const vec3_t v)
00415 {
00416     ulong     i; 
00417 
00418     AssertReturnValue1(v, false);
00419 
00420     for (i=0 ; ++i<3;) 
00421         if (fabs(vec[i]-v[i]) > EQUAL_EPSILON) 
00422             return false; 
00423  
00424     return true; 
00425 }
00426 
00427 /*vec3_c vec3_c::operator +(const vec3_t v)
00428 {
00429     return vec3_c(v[0]+vec[0], v[1]+vec[1], v[2]+vec[2]);
00430 }*/
00431 
00432 vec3_c operator +(const vec3_t vec, vec3_c v)
00433 {
00434     return vec3_c(v[0]+vec[0], v[1]+vec[1], v[2]+vec[2]);
00435 }
00436 
00437 vec3_c vec3_c::operator -(const vec3_t v)
00438 {
00439     return vec3_c(vec[0]-v[0], vec[1]-v[1], vec[2]-v[2]);
00440 }
00441 
00442 vec3_c vec3_c::operator *(const float f)
00443 {
00444     return vec3_c(f*vec[0], f*vec[1], f*vec[2]);
00445 }
00446 
00447 vec3_c vec3_c::operator *(const vec3_t v)
00448 {
00449     return vec3_c(vec[0]*v[0], vec[1]*v[1], vec[2]*v[2]);
00450 }
00451 
00452 /**************************************************************************** 
00453  * vector_cross                                    calculate cross product * 
00454  ****************************************************************************/ 
00455 vec3_c vec3_c::cross 
00456 ( 
00457     const vec3_t v
00458 ) 
00459 { 
00460     AssertReturnValue1(v, vec3_c(0,0,0));
00461 
00462     return vec3_c(  vec[VECT_Y]*v[VECT_Z] - vec[VECT_Z]*v[VECT_Y],
00463                     vec[VECT_Z]*v[VECT_X] - vec[VECT_X]*v[VECT_Z],
00464                     vec[VECT_X]*v[VECT_Y] - vec[VECT_Y]*v[VECT_X]); 
00465 } // vector_cross 
00466  
00467 /**************************************************************************** 
00468  * vector_dot                                        calculate dot product * 
00469  ****************************************************************************/
00470 float vec3_c::dot
00471 ( 
00472     const vec3_t v
00473 ) 
00474 { 
00475     AssertReturnValue1(v, 0);
00476 
00477     return  v[VECT_X]*vec[VECT_X] + 
00478             v[VECT_Y]*vec[VECT_Y] + 
00479             v[VECT_Z]*vec[VECT_Z]; 
00480 } // vector_dot 
00481 
00482 vec3_c vec3_c::operator =(const vec3_t v)
00483 {
00484     vec[0] = v[0];
00485     vec[1] = v[1];
00486     vec[2] = v[2];
00487 
00488     return *this;
00489 }
00490 
00491 vec3_c vec3_c::normalize()
00492 {
00493     return *this * (1/length());
00494 }
00495 
00496 vec3_c vec3_c::project()
00497 {
00498     double    matModel[16], matProj[16]; 
00499     int       viewport[4]; 
00500     GLdouble  o[3]; 
00501 
00502     // slooooooooooow..
00503  
00504     glGetDoublev( GL_MODELVIEW_MATRIX, matModel ); 
00505     glGetDoublev( GL_PROJECTION_MATRIX, matProj ); 
00506     glGetIntegerv( GL_VIEWPORT, viewport); 
00507     gluProject( vec[0], vec[1], vec[2], matModel, matProj, viewport, &o[0], &o[1], &o[2] ); 
00508 
00509     return vec3_c((float)o[0],(float)o[1],(float)o[2]);
00510 }
00511 
00512 vec3_c vec3_c::project_ex 
00513 ( 
00514         ulong   w,                  // dimensions of the screen
00515         ulong   h 
00516 ) 
00517 { 
00518     double      matModel[16], matProj[16]; 
00519     int         viewport[4]; 
00520     GLdouble    o[3]; 
00521  
00522     glGetDoublev( GL_MODELVIEW_MATRIX, matModel ); 
00523     glGetDoublev( GL_PROJECTION_MATRIX, matProj ); 
00524     viewport[0] = viewport[1] = 0; 
00525     viewport[2] = (int)w; 
00526     viewport[3] = (int)h; 
00527     gluProject( vec[0], vec[1], vec[2], matModel, matProj, viewport, &o[0], &o[1], &o[2] ); 
00528  
00529     return vec3_c((float)o[0],(float)o[1],(float)o[2]);
00530 } 
00531 
00532 vec3_c vec3_c::unproject() 
00533 { 
00534     double  matModel[16], matProj[16]; 
00535     int     viewport[4]; 
00536     GLdouble o[3]; 
00537 
00538     glGetDoublev( GL_MODELVIEW_MATRIX, matModel ); 
00539     glGetDoublev( GL_PROJECTION_MATRIX, matProj ); 
00540     glGetIntegerv( GL_VIEWPORT, viewport); 
00541     gluUnProject( vec[0], vec[1], vec[2], matModel, matProj, viewport, &o[0], &o[1], &o[2] ); 
00542  
00543     return vec3_c((float)o[0],(float)o[1],(float)o[2]);
00544 } 
00545  
00546 
00547 /**************************************************************************** 
00548  * vector_unproject_ex                   unprojects screen to world coords *
00549  ****************************************************************************/ 
00550 vec3_c vec3_c::unproject_ex(ulong w, ulong h) 
00551 { 
00552     double  matModel[16], matProj[16]; 
00553     int     viewport[4]; 
00554     GLdouble o[3]; 
00555 
00556     glGetDoublev( GL_MODELVIEW_MATRIX, matModel ); 
00557     glGetDoublev( GL_PROJECTION_MATRIX, matProj ); 
00558     viewport[0] = viewport[1] = 0; 
00559     viewport[2] = (int)w; 
00560     viewport[3] = (int)h; 
00561     gluUnProject( vec[0], vec[1], vec[2], matModel, matProj, viewport, &o[0], &o[1], &o[2] ); 
00562  
00563     return vec3_c((float)o[0],(float)o[1],(float)o[2]);
00564 } 
00565 
00566 /****************************************************************************
00567  * vector_rotate                                    rotates a vector (ypr) *
00568  ****************************************************************************/
00569 vec3_c vec3_c::rotate
00570 ( 
00571     const vec3_t angles
00572 )
00573 { 
00574     float rad; 
00575     float radsin; 
00576     float radcos; 
00577  
00578     vec3_t tmp,tmp2; 
00579 
00580     AssertReturnValue1(angles, vec3_c());
00581  
00582     rad     = (float)(-angles[ANGLE_ROLL] * DEG2RAD); 
00583 
00584     radsin  = (float)(sin(rad)); radcos = (float)(cos(rad)); 
00585  
00586     tmp2[0] = vec[0]*radcos-vec[2]*radsin;
00587     tmp2[1] = vec[1];
00588     tmp2[2] = vec[0]*radsin+vec[2]*radcos;
00589  
00590     rad     = (float)(-angles[ANGLE_PITCH] * DEG2RAD); 
00591   
00592     radsin  = (float)(sin(rad)); radcos = (float)(cos(rad)); 
00593  
00594     tmp[0]  = tmp2[0]; 
00595     tmp[2]  = tmp2[2]*radcos-vec[1]*radsin; 
00596     tmp[1]  = tmp2[2]*radsin+vec[1]*radcos; 
00597  
00598     rad     = (float)(-angles[ANGLE_YAW] * DEG2RAD); 
00599   
00600     radsin  = (float)(sin(rad)); radcos = (float)(cos(rad)); 
00601  
00602     return vec3_c(  tmp[0]*radcos-tmp[1]*radsin,
00603                     tmp[0]*radsin+tmp[1]*radcos,
00604                     tmp[2] );
00605 } 
00606 
00607 /****************************************************************************
00608  * vector_linear                              interpolation of two vectors *
00609  ****************************************************************************/
00610 vec3_c vec3_c::linear
00611 (
00612     const vec3_t p1, 
00613     const vec3_t p2, 
00614     float frac
00615 ) 
00616 { 
00617     AssertReturnValue2(p1,p2, vec3_c());
00618 
00619     vec3_c vec;
00620 
00621     for (ulong i=0; i<3; i++) 
00622         vec.set_component(i, _interpolate_float_linear(p1[i], p2[i], frac));
00623 
00624     return vec;
00625 } 
00626 
00627 /****************************************************************************
00628  * vector_hermite                     hermite interpolation of two vectors *
00629  ****************************************************************************/
00630 vec3_c vec3_c::hermite
00631 (
00632     const vec3_t p1, 
00633     const vec3_t t1, 
00634     const vec3_t p2, 
00635     const vec3_t t2, 
00636     float   frac
00637 ) 
00638 { 
00639     AssertReturnValue4(p1,p2,t1,t2, vec3_c());
00640 
00641     vec3_c vec;
00642 
00643     float tsquared  = frac*frac; 
00644     float tsquared3 = tsquared*3; 
00645     float tcubed    = frac*tsquared; 
00646     float tcubed2   = tcubed*2; 
00647     float t         = frac; 
00648  
00649     float a = (tcubed2-tsquared3+1); 
00650     float b = (tcubed-(2*tsquared)+t); 
00651     float c = (tcubed-tsquared); 
00652     float d = (-tcubed2+tsquared3); 
00653  
00654     for (ulong i=0; i<3; i++) 
00655     { 
00656         float   pa = p1[i]; 
00657         float   pb = p2[i]; 
00658         float   ma = t1[i]; 
00659         float   mb = t2[i]; 
00660  
00661         vec.set_component(i, a*pa+b*ma+c*mb+d*pb);
00662     } 
00663 
00664     return vec;
00665 } 

Generated on Wed Dec 18 15:48:46 2002 for omicron engine by doxygen1.2.18