00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00053
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
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
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 );
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
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
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
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
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
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
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
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 }