00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <math.h>
00027 #include <assert.h>
00028
00029 #include "Box.h"
00030
00031
00033
00034
00035
00036
00037
00038
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
00065
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
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
00111
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
00127
00128 isOrthonormal = geXForm3d_IsOrthonormal(&(Box1->Transform));
00129 assert(isOrthonormal);
00130
00131 isOrthonormal = geXForm3d_IsOrthonormal(&(Box2->Transform));
00132 assert(isOrthonormal);
00133
00134
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
00151
00152
00153 for (i = 0; i < 3; i++)
00154 {
00155 geXForm3d_Rotate(&(BoxA->TransformInv), &(BoxB->GlobalFrameAxes[i]),
00156 &inverseXFormedGlobalFrameAxes[i]);
00157 }
00158
00159
00160
00161 geVec3d_Subtract(&(BoxB->Transform.Translation), &(BoxA->Transform.Translation),
00162 ¢erToCenterVector);
00163
00164
00165
00166
00167 geXForm3d_Rotate(&(BoxA->TransformInv), ¢erToCenterVector,
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
00175
00176
00177
00178
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
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
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 }
00206
00207 return GE_TRUE;
00208 }
00209