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

Box.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  BOX.C                                                                               */
00003 /*                                                                                      */
00004 /*  Author: Jason Wood                                                                  */
00005 /*  Description: Non-axial aligned box support                                          */
00006 /*               This implementation may have a inaccuracy which allows the test to     */
00007 /*               return that boxes overlap, when they are actually separated by a       */
00008 /*               small distance.                                                        */
00009 /*                                                                                      */
00010 /*  The contents of this file are subject to the Genesis3D Public License               */
00011 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00012 /*  compliance with the License. You may obtain a copy of the License at                */
00013 /*  http://www.genesis3d.com                                                            */
00014 /*                                                                                      */
00015 /*  Software distributed under the License is distributed on an "AS IS"                 */
00016 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00017 /*  the License for the specific language governing rights and limitations              */
00018 /*  under the License.                                                                  */
00019 /*                                                                                      */
00020 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00021 /*Genesis3D Version 1.1 released November 15, 1999                            */
00022 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00023 /*                                                                                      */
00024 /****************************************************************************************/
00025 #include <stdio.h>
00026 #include <math.h>
00027 #include <assert.h>
00028 
00029 #include "Box.h"
00030 
00031 
00033 // geBox_ functions
00034 
00035 
00036 // Box needs to know what its axes are like in world space
00037 // this involves a simplified rotation of the Box's local
00038 // frame axes into global coord system
00039 
00040 static void geBox_ComputeGlobalFrameAxes(geBox* Box)
00041 {
00042         geBoolean isOrthonormal;
00043 
00044         assert(Box != NULL);
00045 
00046         isOrthonormal = geXForm3d_IsOrthonormal(&(Box->Transform));
00047         assert(isOrthonormal);
00048 
00049         Box->GlobalFrameAxes[0].X = Box->Transform.AX * Box->xScale;
00050         Box->GlobalFrameAxes[0].Y = Box->Transform.BX * Box->xScale;
00051         Box->GlobalFrameAxes[0].Z = Box->Transform.CX * Box->xScale;
00052 
00053         Box->GlobalFrameAxes[1].X = Box->Transform.AY * Box->yScale;
00054         Box->GlobalFrameAxes[1].Y = Box->Transform.BY * Box->yScale;
00055         Box->GlobalFrameAxes[1].Z = Box->Transform.CY * Box->yScale;
00056 
00057         Box->GlobalFrameAxes[2].X = Box->Transform.AZ * Box->zScale;
00058         Box->GlobalFrameAxes[2].Y = Box->Transform.BZ * Box->zScale;
00059         Box->GlobalFrameAxes[2].Z = Box->Transform.CZ * Box->zScale;
00060 
00061 }
00062 
00063 
00064 // set up a Box; call when initializing an Box or when
00065 // the Box's scale(s) change
00066 
00067 void geBox_Set(geBox* Box, geFloat xScale, geFloat yScale, geFloat zScale, const geXForm3d* Transform)
00068 {
00069         geBoolean isOrthonormal;
00070 
00071         assert(Box != NULL);
00072         assert(Transform != NULL);
00073 
00074         isOrthonormal = geXForm3d_IsOrthonormal(&(Box->Transform));
00075         assert(isOrthonormal);
00076 
00077         Box->xScale = xScale;
00078         Box->yScale = yScale;
00079         Box->zScale = zScale;
00080 
00081         geBox_SetXForm(Box, Transform); 
00082 }
00083 
00084 // set a Box's Transform
00085 
00086 void geBox_SetXForm(geBox* Box, const geXForm3d* Transform)
00087 {
00088         geBoolean isOrthonormal;
00089 
00090         assert(Box != NULL);
00091         assert(Transform != NULL);
00092 
00093         isOrthonormal = geXForm3d_IsOrthonormal(Transform);
00094         assert(isOrthonormal);
00095 
00096         geXForm3d_Copy(Transform, &(Box->Transform));
00097 
00098         isOrthonormal = geXForm3d_IsOrthonormal(&(Box->Transform));
00099         assert(isOrthonormal);
00100 
00101         geXForm3d_GetTranspose(Transform, &(Box->TransformInv));
00102 
00103         isOrthonormal = geXForm3d_IsOrthonormal(&(Box->TransformInv));
00104         assert(isOrthonormal);
00105 
00106         geBox_ComputeGlobalFrameAxes(Box);
00107 }
00108 
00109 
00110 // test for Box overlap between 2 Boxs
00111 // tests for overlap between B against A and then A against B
00112 
00113 geBoolean geBox_DetectCollisionBetween(const geBox* Box1, const geBox* Box2)
00114 {
00115         int i, c;
00116         geFloat radius;
00117         const geBox* BoxA;
00118         const geBox* BoxB;
00119         static geVec3d centerToCenterVector, xformedCenterToCenterVector;
00120         static geVec3d inverseXFormedGlobalFrameAxes[3];
00121         geBoolean isOrthonormal;
00122 
00123         assert(Box1 != NULL);
00124         assert(Box2 != NULL);
00125 
00126         // assert orthonormality
00127 
00128         isOrthonormal = geXForm3d_IsOrthonormal(&(Box1->Transform));
00129         assert(isOrthonormal);
00130 
00131         isOrthonormal = geXForm3d_IsOrthonormal(&(Box2->Transform));
00132         assert(isOrthonormal);
00133 
00134         // test B against A and if necessary A against B
00135 
00136         for (c = 0; c < 2; c ++)
00137         {
00138                 if (c == 0)
00139                 {
00140                         BoxA = Box1;
00141                         BoxB = Box2;
00142                 }
00143 
00144                 else
00145                 {
00146                         BoxA = Box2;
00147                         BoxB = Box1;
00148                 }
00149 
00150                 // rotate B's global frame axes by the amount A was rotated to bring it
00151                 // back into its local coord system
00152 
00153                 for (i = 0; i < 3; i++)
00154                 {
00155                         geXForm3d_Rotate(&(BoxA->TransformInv), &(BoxB->GlobalFrameAxes[i]),
00156                                 &inverseXFormedGlobalFrameAxes[i]);
00157                 }
00158 
00159                 // get B's translation offset from A in global coord system
00160 
00161                 geVec3d_Subtract(&(BoxB->Transform.Translation), &(BoxA->Transform.Translation),
00162                         &centerToCenterVector);
00163 
00164                 // rotate offset by the amount A was rotated to bring it
00165                 // back into its local coord system
00166                 
00167                 geXForm3d_Rotate(&(BoxA->TransformInv), &centerToCenterVector,
00168                         &xformedCenterToCenterVector);
00169 
00170                 xformedCenterToCenterVector.X = (geFloat)fabs(xformedCenterToCenterVector.X);
00171                 xformedCenterToCenterVector.Y = (geFloat)fabs(xformedCenterToCenterVector.Y);
00172                 xformedCenterToCenterVector.Z = (geFloat)fabs(xformedCenterToCenterVector.Z);
00173 
00174                 // test every radius of BoxB
00175                 // for every global frame-axis-aligned axis of BoxA
00176                 // to see if overlap occurred
00177 
00178                 // test overlap in X axis
00179 
00180                 radius = (geFloat)(fabs(inverseXFormedGlobalFrameAxes[0].X) +
00181                         fabs(inverseXFormedGlobalFrameAxes[1].X) +
00182                         fabs(inverseXFormedGlobalFrameAxes[2].X));
00183 
00184                 if ((radius + BoxA->xScale) < xformedCenterToCenterVector.X)
00185                         return GE_FALSE;
00186 
00187                 // test overlap in Y axis
00188 
00189                 radius = (geFloat)(fabs(inverseXFormedGlobalFrameAxes[0].Y) +
00190                         fabs(inverseXFormedGlobalFrameAxes[1].Y) +
00191                         fabs(inverseXFormedGlobalFrameAxes[2].Y));
00192 
00193                 if ((radius + BoxA->yScale) < xformedCenterToCenterVector.Y)
00194                         return GE_FALSE;
00195 
00196                 // test overlap in Z axis
00197 
00198                 radius = (geFloat)(fabs(inverseXFormedGlobalFrameAxes[0].Z) +
00199                         fabs(inverseXFormedGlobalFrameAxes[1].Z) +
00200                         fabs(inverseXFormedGlobalFrameAxes[2].Z));
00201 
00202                 if ((radius + BoxA->zScale) < xformedCenterToCenterVector.Z)
00203                         return GE_FALSE;
00204 
00205         } // c
00206 
00207         return GE_TRUE; // all tests checked out, overlap occurred
00208 }
00209 

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