Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

ExtBox.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  EXTBOX.C                                                                            */
00003 /*                                                                                      */
00004 /*  Author:                                                                             */
00005 /*  Description: Axial aligned bounding box support                                     */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #include "ExtBox.h"
00023 #include <assert.h>
00024 
00025 #define MAX(aa,bb)   ( ((aa)>(bb))?(aa):(bb) )
00026 #define MIN(aa,bb)   ( ((aa)<(bb))?(aa):(bb) )
00027 
00028 geBoolean GENESISCC geExtBox_IsValid(  const geExtBox *B )
00029 {
00030         if (B == NULL) return GE_FALSE;
00031         
00032         if (geVec3d_IsValid(&(B->Min)) == GE_FALSE)
00033                 return GE_FALSE;
00034         if (geVec3d_IsValid(&(B->Max)) == GE_FALSE)
00035                 return GE_FALSE;
00036 
00037 
00038         if (    (B->Min.X <= B->Max.X) &&
00039                         (B->Min.Y <= B->Max.Y) &&
00040                         (B->Min.Z <= B->Max.Z)          )
00041                 return GE_TRUE;
00042         else
00043                 return GE_FALSE;
00044 }
00045 
00046 void GENESISCC geExtBox_Set(  geExtBox *B,
00047                                         geFloat X1,geFloat Y1,geFloat Z1,
00048                                         geFloat X2,geFloat Y2,geFloat Z2)
00049 {
00050         assert (B != NULL);
00051 
00052         //geVec3d_Set   (&B->Min, MIN (x1, x2), MIN (y1, y2),MIN (z1, z2));
00053         //geVec3d_Set (&B->Max, MAX (x1, x2),   MAX (y1, y2),MAX (z1, z2));
00054 
00055         if ( X1 > X2 )
00056                 {       B->Max.X = X1;  B->Min.X = X2;  }
00057         else
00058                 {       B->Max.X = X2;  B->Min.X = X1;  }
00059         
00060         if ( Y1 > Y2 )
00061                 {       B->Max.Y = Y1;  B->Min.Y = Y2;  }
00062         else
00063                 {       B->Max.Y = Y2;  B->Min.Y = Y1;  }
00064         
00065         if ( Z1 > Z2 )
00066                 {       B->Max.Z = Z1;  B->Min.Z = Z2;  }
00067         else
00068                 {       B->Max.Z = Z2;  B->Min.Z = Z1;  }
00069 
00070         assert( geVec3d_IsValid(&(B->Min)) != GE_FALSE );
00071         assert( geVec3d_IsValid(&(B->Max)) != GE_FALSE );
00072 
00073 }
00074 
00075 // Set box Min and Max to the passed point
00076 void GENESISCC geExtBox_SetToPoint ( geExtBox *B, const geVec3d *Point )
00077 {
00078         assert( B     != NULL );
00079         assert( Point != NULL );
00080         assert( geVec3d_IsValid(Point) != GE_FALSE );
00081 
00082         
00083         B->Max = *Point;
00084         B->Min = *Point;
00085 }
00086 
00087 // Extend a box to encompass the passed point
00088 void GENESISCC geExtBox_ExtendToEnclose( geExtBox *B, const geVec3d *Point )
00089 {
00090         assert ( geExtBox_IsValid(B) != GE_FALSE );
00091         assert( Point != NULL );
00092         assert( geVec3d_IsValid(Point) != GE_FALSE );
00093 
00094         if (Point->X > B->Max.X ) B->Max.X = Point->X;
00095         if (Point->Y > B->Max.Y ) B->Max.Y = Point->Y;
00096         if (Point->Z > B->Max.Z ) B->Max.Z = Point->Z;
00097 
00098         if (Point->X < B->Min.X ) B->Min.X = Point->X;
00099         if (Point->Y < B->Min.Y ) B->Min.Y = Point->Y;
00100         if (Point->Z < B->Min.Z ) B->Min.Z = Point->Z;
00101 
00102 }
00103 
00104 static geBoolean GENESISCC geExtBox_Intersects(  const geExtBox *B1,  const geExtBox *B2 )
00105 {
00106         assert ( geExtBox_IsValid (B1) != GE_FALSE );
00107         assert ( geExtBox_IsValid (B2) != GE_FALSE );
00108 
00109         if ((B1->Min.X > B2->Max.X) || (B1->Max.X < B2->Min.X)) return GE_FALSE;
00110         if ((B1->Min.Y > B2->Max.Y) || (B1->Max.Y < B2->Min.Y)) return GE_FALSE;
00111         if ((B1->Min.Z > B2->Max.Z) || (B1->Max.Z < B2->Min.Z)) return GE_FALSE;
00112         return GE_TRUE;
00113 }
00114 
00115 
00116         
00117 geBoolean GENESISCC geExtBox_Intersection( const geExtBox *B1, const geExtBox *B2, geExtBox *Result )
00118 {
00119         geBoolean rslt;
00120 
00121         assert ( geExtBox_IsValid (B1) != GE_FALSE );
00122         assert ( geExtBox_IsValid (B2) != GE_FALSE );
00123 
00124         rslt = geExtBox_Intersects (B1, B2);
00125         if ( (rslt != GE_FALSE) && (Result != NULL))
00126                 {
00127                         geExtBox_Set ( Result,
00128                                                 MAX (B1->Min.X, B2->Min.X),
00129                                                 MAX (B1->Min.Y, B2->Min.Y),
00130                                                 MAX (B1->Min.Z, B2->Min.Z),
00131                                                 MIN (B1->Max.X, B2->Max.X),
00132                                                 MIN (B1->Max.Y, B2->Max.Y),
00133                                                 MIN (B1->Max.Z, B2->Max.Z) );
00134                 }
00135         return rslt;
00136 }
00137 
00138 void GENESISCC geExtBox_Union( const geExtBox *B1, const geExtBox *B2, geExtBox *Result )
00139 {
00140         assert ( geExtBox_IsValid (B1) != GE_FALSE );
00141         assert ( geExtBox_IsValid (B2) != GE_FALSE );
00142         assert (Result != NULL);
00143 
00144         geExtBox_Set (  Result,
00145                                 MIN (B1->Min.X, B2->Min.X),
00146                                 MIN (B1->Min.Y, B2->Min.Y),
00147                                 MIN (B1->Min.Z, B2->Min.Z),
00148                                 MAX (B1->Max.X, B2->Max.X),
00149                                 MAX (B1->Max.Y, B2->Max.Y),
00150                                 MAX (B1->Max.Z, B2->Max.Z) );
00151 }
00152 
00153 geBoolean GENESISCC geExtBox_ContainsPoint(  const geExtBox *B,  const geVec3d *Point )
00154 {
00155         assert (geExtBox_IsValid (B) != GE_FALSE);
00156         assert( geVec3d_IsValid(Point) != GE_FALSE );
00157 
00158         if (    (Point->X >= B->Min.X) && (Point->X <= B->Max.X) &&
00159                         (Point->Y >= B->Min.Y) && (Point->Y <= B->Max.Y) &&
00160                         (Point->Z >= B->Min.Z) && (Point->Z <= B->Max.Z)     )
00161                 {
00162                         return GE_TRUE;
00163                 }
00164         else
00165                 {
00166                         return GE_FALSE;
00167                 }
00168 }
00169 
00170 
00171 void GENESISCC geExtBox_GetTranslation( const geExtBox *B, geVec3d *pCenter )
00172 {
00173         assert (geExtBox_IsValid (B) != GE_FALSE);
00174         assert (pCenter != NULL);
00175 
00176         geVec3d_Set( pCenter,
00177                                 (B->Min.X + B->Max.X)/2.0f,
00178                                 (B->Min.Y + B->Max.Y)/2.0f,
00179                                 (B->Min.Z + B->Max.Z)/2.0f );
00180 }
00181 
00182 void GENESISCC geExtBox_Translate(  geExtBox *B,  geFloat DX,  geFloat DY,  geFloat DZ  )
00183 {
00184         geVec3d VecDelta;
00185 
00186         assert (geExtBox_IsValid (B) != GE_FALSE);
00187 
00188         geVec3d_Set (&VecDelta, DX, DY, DZ);
00189                 assert( geVec3d_IsValid(&VecDelta) != GE_FALSE );
00190         geVec3d_Add (&B->Min, &VecDelta, &B->Min);
00191         geVec3d_Add (&B->Max, &VecDelta, &B->Max);
00192 }
00193 
00194 void GENESISCC geExtBox_SetTranslation( geExtBox *B, const geVec3d *pCenter )
00195 {
00196         geVec3d Center,Translation;
00197 
00198         assert (geExtBox_IsValid (B) != GE_FALSE);
00199         assert (pCenter != NULL);
00200         assert( geVec3d_IsValid(pCenter) != GE_FALSE );
00201 
00202         geExtBox_GetTranslation( B, &Center );
00203         geVec3d_Subtract( pCenter, &Center, &Translation);
00204 
00205         geExtBox_Translate( B, Translation.X, Translation.Y, Translation.Z );
00206 }
00207 
00208 void GENESISCC geExtBox_GetScaling( const geExtBox *B, geVec3d *pScale )
00209 {
00210         assert (geExtBox_IsValid (B) != GE_FALSE );
00211         assert (pScale != NULL);
00212 
00213         geVec3d_Subtract( &(B->Max), &(B->Min), pScale );
00214 }
00215 
00216 void GENESISCC geExtBox_Scale( geExtBox *B, geFloat ScaleX, geFloat ScaleY, geFloat ScaleZ )
00217 {
00218         geVec3d Center;
00219         geVec3d Scale;
00220         geFloat DX,DY,DZ;
00221 
00222         assert (geExtBox_IsValid (B) != GE_FALSE );
00223         assert (ScaleX >= 0.0f );
00224         assert (ScaleY >= 0.0f );
00225         assert (ScaleZ >= 0.0f );
00226         assert (ScaleX * ScaleX >= 0.0f );              // check for NANS
00227         assert (ScaleY * ScaleY >= 0.0f );
00228         assert (ScaleZ * ScaleZ >= 0.0f );
00229 
00230         geExtBox_GetTranslation( B, &Center );
00231         geExtBox_GetScaling    ( B, &Scale  );
00232         
00233         DX = ScaleX * Scale.X * 0.5f;
00234         DY = ScaleY * Scale.Y * 0.5f;
00235         DZ = ScaleZ * Scale.Z * 0.5f;
00236 
00237         B->Min.X = Center.X - DX;
00238         B->Min.Y = Center.Y - DY;
00239         B->Min.Z = Center.Z - DZ;
00240         
00241         B->Max.X = Center.X + DX;
00242         B->Max.Y = Center.Y + DY;
00243         B->Max.Z = Center.Z + DZ;
00244         
00245         assert (geExtBox_IsValid (B) != GE_FALSE);
00246 }
00247 
00248 void GENESISCC geExtBox_SetScaling( geExtBox *B, const geVec3d *pScale )
00249 {
00250         geVec3d Center;
00251         geFloat DX,DY,DZ;
00252 
00253         assert (geExtBox_IsValid (B) != GE_FALSE );
00254         assert (pScale != NULL );
00255         assert (geVec3d_IsValid( pScale )!= GE_FALSE);
00256         assert (pScale->X >= 0.0f );
00257         assert (pScale->Y >= 0.0f );
00258         assert (pScale->Z >= 0.0f );
00259 
00260         geExtBox_GetTranslation( B, &Center );
00261 
00262         DX = pScale->X / 2.0f;
00263         DY = pScale->Y / 2.0f;
00264         DZ = pScale->Z / 2.0f;
00265 
00266         B->Min.X = Center.X - DX;
00267         B->Min.Y = Center.Y - DY;
00268         B->Min.Z = Center.Z - DZ;
00269         
00270         B->Max.X = Center.X + DX;
00271         B->Max.Y = Center.Y + DY;
00272         B->Max.Z = Center.Z + DZ;
00273 }
00274 
00275 void GENESISCC geExtBox_LinearSweep(    const geExtBox *BoxToSweep, 
00276                                                 const geVec3d *StartPoint, 
00277                                                 const geVec3d *EndPoint, 
00278                                                 geExtBox *EnclosingBox )
00279 {
00280 
00281         assert (geExtBox_IsValid (BoxToSweep) != GE_FALSE );
00282         assert (StartPoint   != NULL );
00283         assert (EndPoint     != NULL );
00284         assert (geVec3d_IsValid( StartPoint )!= GE_FALSE);
00285         assert (geVec3d_IsValid( EndPoint   )!= GE_FALSE);
00286         assert (EnclosingBox != NULL );
00287 
00288         *EnclosingBox = *BoxToSweep;
00289 
00290         if (EndPoint->X > StartPoint->X)
00291                 {
00292                         EnclosingBox->Min.X += StartPoint->X; 
00293                         EnclosingBox->Max.X += EndPoint->X; 
00294                 }
00295         else
00296                 {
00297                         EnclosingBox->Min.X += EndPoint->X; 
00298                         EnclosingBox->Max.X += StartPoint->X; 
00299                 }
00300 
00301         if (EndPoint->Y > StartPoint->Y)
00302                 {
00303                         EnclosingBox->Min.Y += StartPoint->Y; 
00304                         EnclosingBox->Max.Y += EndPoint->Y; 
00305                 }
00306         else
00307                 {
00308                         EnclosingBox->Min.Y += EndPoint->Y; 
00309                         EnclosingBox->Max.Y += StartPoint->Y; 
00310                 }
00311 
00312         if (EndPoint->Z > StartPoint->Z)
00313                 {
00314                         EnclosingBox->Min.Z += StartPoint->Z; 
00315                         EnclosingBox->Max.Z += EndPoint->Z; 
00316                 }
00317         else
00318                 {
00319                         EnclosingBox->Min.Z += EndPoint->Z; 
00320                         EnclosingBox->Max.Z += StartPoint->Z; 
00321                 }
00322         assert (geExtBox_IsValid (EnclosingBox) != GE_FALSE );
00323 }
00324 
00325 static geBoolean GENESISCC geExtBox_XFaceDist(  const geVec3d *Start, 
00326                                                                                                 const geVec3d *Delta, const geExtBox *B, geFloat *T, geFloat X)
00327 {
00328         geFloat t;
00329         geFloat Y,Z;
00330         assert( Start != NULL );
00331         assert( Delta != NULL );
00332         assert( B     != NULL );
00333         assert( T     != NULL );
00334 
00335         //if ( (Start->X <= X) && (X <= Delta->X + Start->X) )
00336                 {
00337                         t = (X - Start->X)/Delta->X;
00338                         Y  = Start->Y + Delta->Y * t;
00339                         if ( ( B->Min.Y <= Y) && (Y <= B->Max.Y) )
00340                                 {
00341                                         Z = Start->Z + Delta->Z * t;
00342                                         if ( ( B->Min.Z <= Z) && (Z <= B->Max.Z) )
00343                                                 {
00344                                                         *T = t;
00345                                                         return GE_TRUE;
00346                                                 }
00347                                 }
00348                 }
00349         return GE_FALSE;
00350 }
00351 
00352 static geBoolean GENESISCC geExtBox_YFaceDist(  const geVec3d *Start, const geVec3d *Delta, const geExtBox *B, geFloat *T, geFloat Y)
00353 {
00354         geFloat t;
00355         geFloat X,Z;
00356         assert( Start != NULL );
00357         assert( Delta != NULL );
00358         assert( B     != NULL );
00359         assert( T     != NULL );
00360 
00361         //if ( (Start->Y <= Y) && (Y <= Delta->Y + Start->Y) )
00362                 {
00363                         t = (Y - Start->Y)/Delta->Y;
00364                         Z  = Start->Z + Delta->Z * t;
00365                         if ( ( B->Min.Z <= Z) && (Z <= B->Max.Z) )
00366                                 {
00367                                         X = Start->X + Delta->X * t;
00368                                         if ( ( B->Min.X <= X) && (X <= B->Max.X) )
00369                                                 {
00370                                                         *T = t;
00371                                                         return GE_TRUE;
00372                                                 }
00373                                 }
00374                 }
00375         return GE_FALSE;
00376 }
00377 
00378 
00379 static geBoolean GENESISCC geExtBox_ZFaceDist(  const geVec3d *Start, const geVec3d *Delta, const geExtBox *B, geFloat *T, geFloat Z)
00380 {
00381         geFloat t;
00382         geFloat X,Y;
00383         assert( Start != NULL );
00384         assert( Delta != NULL );
00385         assert( B     != NULL );
00386         assert( T     != NULL );
00387 
00388         //if ( (Start->Z <= Z) && (Z <= Delta->Z + Start->Z) )
00389                 {
00390                         t = (Z - Start->Z)/Delta->Z;
00391                         X  = Start->X + Delta->X * t;
00392                         if ( ( B->Min.X <= X) && (X <= B->Max.X) )
00393                                 {
00394                                         Y = Start->Y + Delta->Y * t;
00395                                         if ( ( B->Min.Y <= Y) && (Y <= B->Max.Y) )
00396                                                 {
00397                                                         *T = t;
00398                                                         return GE_TRUE;
00399                                                 }
00400                                 }
00401                 }
00402         return GE_FALSE;
00403 }
00404 
00405 
00406 
00407 geBoolean GENESISCC geExtBox_RayCollision( const geExtBox *B, const geVec3d *Start, const geVec3d *End, 
00408                                                                 geFloat *T, geVec3d *Normal )
00409 {
00410         // only detects rays going 'in' to the box
00411         geFloat t;
00412         geVec3d Delta;
00413         geVec3d LocalNormal;
00414         geFloat LocalT;
00415 
00416         assert( B != NULL );
00417         assert( Start != NULL );
00418         assert( End != NULL );
00419         assert (geVec3d_IsValid( Start )!= GE_FALSE);
00420         assert (geVec3d_IsValid( End   )!= GE_FALSE);
00421         assert (geExtBox_IsValid( B )!= GE_FALSE );
00422 
00423         geVec3d_Subtract(End,Start,&Delta);
00424         
00425         if (Normal == NULL)
00426                 Normal = &LocalNormal;
00427         if (T == NULL)
00428                 T = &LocalT;
00429         
00430         // test x end of box, facing away from ray direction.
00431         if (Delta.X > 0.0f)
00432                 {
00433                         if ( (Start->X <= B->Min.X) && (B->Min.X <= End->X) &&
00434                                  (geExtBox_XFaceDist(  Start ,&Delta, B, &t, B->Min.X ) != GE_FALSE) )
00435                                         {
00436                                                 geVec3d_Set( Normal,  -1.0f, 0.0f, 0.0f );
00437                                                 *T = t;
00438                                                 return GE_TRUE;
00439                                         }
00440                 }
00441         else if (Delta.X < 0.0f)
00442                 {
00443                         if ( (End->X <= B->Max.X) && (B->Max.X <= Start->X) &&
00444                                  (geExtBox_XFaceDist(  Start ,&Delta, B, &t, B->Max.X ) != GE_FALSE) )
00445                                         {
00446                                                 geVec3d_Set( Normal,  1.0f, 0.0f, 0.0f );
00447                                                 *T = t;
00448                                                 return GE_TRUE;
00449                                         }
00450                 }
00451         
00452         // test y end of box, facing away from ray direction.
00453         if (Delta.Y > 0.0f)
00454                 {       
00455                         if ( (Start->Y <= B->Min.Y) && (B->Min.Y <= End->Y) &&
00456                                  (geExtBox_YFaceDist(  Start ,&Delta, B, &t, B->Min.Y ) != GE_FALSE) )
00457                                 {
00458                                         geVec3d_Set( Normal,  0.0f, -1.0f, 0.0f );
00459                                         *T = t;
00460                                         return GE_TRUE;
00461                                 }
00462                 }
00463         else if (Delta.Y < 0.0f)
00464                 {
00465                         if ( (End->Y <= B->Max.Y) && (B->Max.Y <= Start->Y) &&
00466                                  (geExtBox_YFaceDist(  Start ,&Delta, B, &t, B->Max.Y ) != GE_FALSE) )
00467                                 {
00468                                         geVec3d_Set( Normal,  0.0f, 1.0f, 0.0f );
00469                                         *T = t;
00470                                         return GE_TRUE;
00471                                 }
00472                 }
00473         
00474         // test z end of box, facing away from ray direction.
00475         if (Delta.Z > 0.0f)
00476                 {       
00477                         if ( (Start->Z <= B->Min.Z) && (B->Min.Z <= End->Z) &&
00478                              (geExtBox_ZFaceDist(  Start ,&Delta, B, &t, B->Min.Z ) != GE_FALSE) )
00479                                 {
00480                                         geVec3d_Set( Normal,  0.0f, 0.0f, -1.0f );
00481                                         *T = t;
00482                                         return GE_TRUE;
00483                                 }
00484                 }
00485         else if (Delta.Z < 0.0f)
00486                 {                       
00487                         if ( (End->Z <= B->Max.Z) && (B->Max.Z <= Start->Z) &&
00488                                  (geExtBox_ZFaceDist(  Start ,&Delta, B, &t, B->Max.Z ) != GE_FALSE) )
00489                                 {
00490                                         geVec3d_Set( Normal,  0.0f, 0.0f, 1.0f );
00491                                         *T = t;
00492                                         return GE_TRUE;
00493                                 }
00494                 }
00495         return GE_FALSE;        
00496 }

Generated on Tue Sep 30 12:35:42 2003 for GTestAndEngine by doxygen 1.3.2