00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "MgcIntrLin3Box3.h"
00014
00015
00016 bool MgcTestIntersection (const MgcSegment3& rkSegment, const MgcBox3& rkBox)
00017 {
00018 double fAWdU[3], fADdU[3], fAWxDdU[3], fRhs;
00019 MgcVector3 kSDir = 0.5*rkSegment.Direction();
00020 MgcVector3 kSCen = rkSegment.Origin() + kSDir;
00021
00022 MgcVector3 kDiff = kSCen - rkBox.Center();
00023
00024 fAWdU[0] = MgcMath::Abs(kSDir.Dot(rkBox.Axis(0)));
00025 fADdU[0] = MgcMath::Abs(kDiff.Dot(rkBox.Axis(0)));
00026 fRhs = rkBox.Extent(0) + fAWdU[0];
00027 if ( fADdU[0] > fRhs )
00028 return false;
00029
00030 fAWdU[1] = MgcMath::Abs(kSDir.Dot(rkBox.Axis(1)));
00031 fADdU[1] = MgcMath::Abs(kDiff.Dot(rkBox.Axis(1)));
00032 fRhs = rkBox.Extent(1) + fAWdU[1];
00033 if ( fADdU[1] > fRhs )
00034 return false;
00035
00036 fAWdU[2] = MgcMath::Abs(kSDir.Dot(rkBox.Axis(2)));
00037 fADdU[2] = MgcMath::Abs(kDiff.Dot(rkBox.Axis(2)));
00038 fRhs = rkBox.Extent(2) + fAWdU[2];
00039 if ( fADdU[2] > fRhs )
00040 return false;
00041
00042 MgcVector3 kWxD = kSDir.Cross(kDiff);
00043
00044 fAWxDdU[0] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(0)));
00045 fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1];
00046 if ( fAWxDdU[0] > fRhs )
00047 return false;
00048
00049 fAWxDdU[1] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(1)));
00050 fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0];
00051 if ( fAWxDdU[1] > fRhs )
00052 return false;
00053
00054 fAWxDdU[2] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(2)));
00055 fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0];
00056 if ( fAWxDdU[2] > fRhs )
00057 return false;
00058
00059 return true;
00060 }
00061
00062 bool MgcTestIntersection (const MgcRay3& rkRay, const MgcBox3& rkBox)
00063 {
00064 double fWdU[3], fAWdU[3], fDdU[3], fADdU[3], fAWxDdU[3], fRhs;
00065
00066 MgcVector3 kDiff = rkRay.Origin() - rkBox.Center();
00067
00068 fWdU[0] = rkRay.Direction().Dot(rkBox.Axis(0));
00069 fAWdU[0] = MgcMath::Abs(fWdU[0]);
00070 fDdU[0] = kDiff.Dot(rkBox.Axis(0));
00071 fADdU[0] = MgcMath::Abs(fDdU[0]);
00072 if ( fADdU[0] > rkBox.Extent(0) && fDdU[0]*fWdU[0] >= 0.0f )
00073 return false;
00074
00075 fWdU[1] = rkRay.Direction().Dot(rkBox.Axis(1));
00076 fAWdU[1] = MgcMath::Abs(fWdU[1]);
00077 fDdU[1] = kDiff.Dot(rkBox.Axis(1));
00078 fADdU[1] = MgcMath::Abs(fDdU[1]);
00079 if ( fADdU[1] > rkBox.Extent(1) && fDdU[1]*fWdU[1] >= 0.0f )
00080 return false;
00081
00082 fWdU[2] = rkRay.Direction().Dot(rkBox.Axis(2));
00083 fAWdU[2] = MgcMath::Abs(fWdU[2]);
00084 fDdU[2] = kDiff.Dot(rkBox.Axis(2));
00085 fADdU[2] = MgcMath::Abs(fDdU[2]);
00086 if ( fADdU[2] > rkBox.Extent(2) && fDdU[2]*fWdU[2] >= 0.0f )
00087 return false;
00088
00089 MgcVector3 kWxD = rkRay.Direction().Cross(kDiff);
00090
00091 fAWxDdU[0] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(0)));
00092 fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1];
00093 if ( fAWxDdU[0] > fRhs )
00094 return false;
00095
00096 fAWxDdU[1] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(1)));
00097 fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0];
00098 if ( fAWxDdU[1] > fRhs )
00099 return false;
00100
00101 fAWxDdU[2] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(2)));
00102 fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0];
00103 if ( fAWxDdU[2] > fRhs )
00104 return false;
00105
00106 return true;
00107 }
00108
00109 bool MgcTestIntersection (const MgcLine3& rkLine, const MgcBox3& rkBox)
00110 {
00111 double fAWdU[3], fAWxDdU[3], fRhs;
00112
00113 MgcVector3 kDiff = rkLine.Origin() - rkBox.Center();
00114 MgcVector3 kWxD = rkLine.Direction().Cross(kDiff);
00115
00116 fAWdU[1] = MgcMath::Abs(rkLine.Direction().Dot(rkBox.Axis(1)));
00117 fAWdU[2] = MgcMath::Abs(rkLine.Direction().Dot(rkBox.Axis(2)));
00118 fAWxDdU[0] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(0)));
00119 fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1];
00120 if ( fAWxDdU[0] > fRhs )
00121 return false;
00122
00123 fAWdU[0] = MgcMath::Abs(rkLine.Direction().Dot(rkBox.Axis(0)));
00124 fAWxDdU[1] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(1)));
00125 fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0];
00126 if ( fAWxDdU[1] > fRhs )
00127 return false;
00128
00129 fAWxDdU[2] = MgcMath::Abs(kWxD.Dot(rkBox.Axis(2)));
00130 fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0];
00131 if ( fAWxDdU[2] > fRhs )
00132 return false;
00133
00134 return true;
00135 }
00136
00137 static bool Clip (MgcReal fDenom, MgcReal fNumer, MgcReal& rfT0,
00138 MgcReal& rfT1)
00139 {
00140
00141
00142
00143
00144 if ( fDenom > 0.0 )
00145 {
00146 if ( fNumer > fDenom*rfT1 )
00147 return false;
00148 if ( fNumer > fDenom*rfT0 )
00149 rfT0 = fNumer/fDenom;
00150 return true;
00151 }
00152 else if ( fDenom < 0.0 )
00153 {
00154 if ( fNumer > fDenom*rfT0 )
00155 return false;
00156 if ( fNumer > fDenom*rfT1 )
00157 rfT1 = fNumer/fDenom;
00158 return true;
00159 }
00160 else
00161 {
00162 return fNumer <= 0.0;
00163 }
00164 }
00165
00166 bool MgcFindIntersection (const MgcVector3& rkOrigin,
00167 const MgcVector3& rkDirection, const MgcReal afExtent[3], MgcReal& rfT0,
00168 MgcReal& rfT1)
00169 {
00170 MgcReal fSaveT0 = rfT0, fSaveT1 = rfT1;
00171
00172 bool bNotEntirelyClipped =
00173 Clip(+rkDirection.x,-rkOrigin.x-afExtent[0],rfT0,rfT1) &&
00174 Clip(-rkDirection.x,+rkOrigin.x-afExtent[0],rfT0,rfT1) &&
00175 Clip(+rkDirection.y,-rkOrigin.y-afExtent[1],rfT0,rfT1) &&
00176 Clip(-rkDirection.y,+rkOrigin.y-afExtent[1],rfT0,rfT1) &&
00177 Clip(+rkDirection.z,-rkOrigin.z-afExtent[2],rfT0,rfT1) &&
00178 Clip(-rkDirection.z,+rkOrigin.z-afExtent[2],rfT0,rfT1);
00179
00180 return bNotEntirelyClipped && ( rfT0 != fSaveT0 || rfT1 != fSaveT1 );
00181 }
00182
00183 bool MgcFindIntersection (const MgcSegment3& rkSegment, const MgcBox3& rkBox,
00184 int& riQuantity, MgcVector3 akPoint[2])
00185 {
00186
00187 MgcVector3 kDiff = rkSegment.Origin() - rkBox.Center();
00188 MgcVector3 kOrigin(
00189 kDiff.Dot(rkBox.Axis(0)),
00190 kDiff.Dot(rkBox.Axis(1)),
00191 kDiff.Dot(rkBox.Axis(2))
00192 );
00193 MgcVector3 kDirection(
00194 rkSegment.Direction().Dot(rkBox.Axis(0)),
00195 rkSegment.Direction().Dot(rkBox.Axis(1)),
00196 rkSegment.Direction().Dot(rkBox.Axis(2))
00197 );
00198
00199 MgcReal fT0 = 0.0, fT1 = 1.0;
00200 bool bIntersects = MgcFindIntersection(kOrigin,kDirection,rkBox.Extents(),
00201 fT0,fT1);
00202
00203 if ( bIntersects )
00204 {
00205 if ( fT0 > 0.0 )
00206 {
00207 if ( fT1 < 1.0 )
00208 {
00209 riQuantity = 2;
00210 akPoint[0] = rkSegment.Origin() + fT0*rkSegment.Direction();
00211 akPoint[1] = rkSegment.Origin() + fT1*rkSegment.Direction();
00212 }
00213 else
00214 {
00215 riQuantity = 1;
00216 akPoint[0] = rkSegment.Origin() + fT0*rkSegment.Direction();
00217 }
00218 }
00219 else
00220 {
00221 if ( fT1 < 1.0 )
00222 {
00223 riQuantity = 1;
00224 akPoint[0] = rkSegment.Origin() + fT1*rkSegment.Direction();
00225 }
00226 else
00227 {
00228
00229 riQuantity = 0;
00230 }
00231 }
00232 }
00233 else
00234 {
00235 riQuantity = 0;
00236 }
00237
00238 return bIntersects;
00239 }
00240
00241 bool MgcFindIntersection (const MgcRay3& rkRay, const MgcBox3& rkBox,double &t)
00242 {
00243
00244
00245
00246 MgcVector3 kDiff = rkRay.Origin() - rkBox.Center();
00247 MgcVector3 kOrigin(
00248 kDiff.Dot(rkBox.Axis(0)),
00249 kDiff.Dot(rkBox.Axis(1)),
00250 kDiff.Dot(rkBox.Axis(2))
00251 );
00252 MgcVector3 kDirection(
00253 rkRay.Direction().Dot(rkBox.Axis(0)),
00254 rkRay.Direction().Dot(rkBox.Axis(1)),
00255 rkRay.Direction().Dot(rkBox.Axis(2))
00256 );
00257
00258 MgcReal fT0 = 0.0, fT1 = MgcMath::INFINITY;
00259 bool bIntersects = MgcFindIntersection(kOrigin,kDirection,rkBox.Extents(),
00260 fT0,fT1);
00261
00262 if (( fT0 > 0.0 ) && ( fT0 < fT1 ))
00263 {
00264 t = fT0;
00265 } else if ( fT1 > 0.0 )
00266 {
00267 t = fT1;
00268 }
00269
00270 return bIntersects;
00271 }
00272
00273 bool MgcFindIntersection (const MgcLine3& rkLine, const MgcBox3& rkBox,
00274 int& riQuantity, MgcVector3 akPoint[2])
00275 {
00276
00277 MgcVector3 kDiff = rkLine.Origin() - rkBox.Center();
00278 MgcVector3 kOrigin(
00279 kDiff.Dot(rkBox.Axis(0)),
00280 kDiff.Dot(rkBox.Axis(1)),
00281 kDiff.Dot(rkBox.Axis(2))
00282 );
00283 MgcVector3 kDirection(
00284 rkLine.Direction().Dot(rkBox.Axis(0)),
00285 rkLine.Direction().Dot(rkBox.Axis(1)),
00286 rkLine.Direction().Dot(rkBox.Axis(2))
00287 );
00288
00289 MgcReal fT0 = -MgcMath::INFINITY, fT1 = MgcMath::INFINITY;
00290 bool bIntersects = MgcFindIntersection(kOrigin,kDirection,rkBox.Extents(),
00291 fT0,fT1);
00292
00293 if ( bIntersects )
00294 {
00295 if ( fT0 != fT1 )
00296 {
00297 riQuantity = 2;
00298 akPoint[0] = rkLine.Origin() + fT0*rkLine.Direction();
00299 akPoint[1] = rkLine.Origin() + fT1*rkLine.Direction();
00300 }
00301 else
00302 {
00303 riQuantity = 1;
00304 akPoint[0] = rkLine.Origin() + fT0*rkLine.Direction();
00305 }
00306 }
00307 else
00308 {
00309 riQuantity = 0;
00310 }
00311
00312 return bIntersects;
00313 }
00314