bool Wml::FindIntersection (const Ray3<Real>& rkRay, const Cylinder3<Real>& rkCylinder, int& riQuantity, Vector3<Real> akPoint[2]) { Real afT[2]; if ( rkCylinder.Capped() ) { riQuantity = Find(rkRay.Origin(),rkRay.Direction(),rkCylinder,afT); } else { riQuantity = FindHollow(rkRay.Origin(),rkRay.Direction(), rkCylinder,afT); } int iClipQuantity = 0; for (int i = 0; i < riQuantity; i++) { if ( afT[i] >= (Real)0.0 ) { akPoint[iClipQuantity++] = rkRay.Origin() + afT[i]*rkRay.Direction(); } } riQuantity = iClipQuantity; return riQuantity > 0; }
//---------------------------------------------------------------------------- bool Mgc::TestIntersection (const Ray3& rkRay, const Box3& rkBox) { Real fWdU[3], fAWdU[3], fDdU[3], fADdU[3], fAWxDdU[3], fRhs; Vector3 kDiff = rkRay.Origin() - rkBox.Center(); fWdU[0] = rkRay.Direction().Dot(rkBox.Axis(0)); fAWdU[0] = Math::FAbs(fWdU[0]); fDdU[0] = kDiff.Dot(rkBox.Axis(0)); fADdU[0] = Math::FAbs(fDdU[0]); if ( fADdU[0] > rkBox.Extent(0) && fDdU[0]*fWdU[0] >= 0.0f ) return false; fWdU[1] = rkRay.Direction().Dot(rkBox.Axis(1)); fAWdU[1] = Math::FAbs(fWdU[1]); fDdU[1] = kDiff.Dot(rkBox.Axis(1)); fADdU[1] = Math::FAbs(fDdU[1]); if ( fADdU[1] > rkBox.Extent(1) && fDdU[1]*fWdU[1] >= 0.0f ) return false; fWdU[2] = rkRay.Direction().Dot(rkBox.Axis(2)); fAWdU[2] = Math::FAbs(fWdU[2]); fDdU[2] = kDiff.Dot(rkBox.Axis(2)); fADdU[2] = Math::FAbs(fDdU[2]); if ( fADdU[2] > rkBox.Extent(2) && fDdU[2]*fWdU[2] >= 0.0f ) return false; Vector3 kWxD = rkRay.Direction().Cross(kDiff); fAWxDdU[0] = Math::FAbs(kWxD.Dot(rkBox.Axis(0))); fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1]; if ( fAWxDdU[0] > fRhs ) return false; fAWxDdU[1] = Math::FAbs(kWxD.Dot(rkBox.Axis(1))); fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0]; if ( fAWxDdU[1] > fRhs ) return false; fAWxDdU[2] = Math::FAbs(kWxD.Dot(rkBox.Axis(2))); fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0]; if ( fAWxDdU[2] > fRhs ) return false; return true; }
//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Ray3& rkRay, const Triangle3& rkTriangle, Vector3& rkPoint) { Real fRayP; if ( SqrDistance(rkRay,rkTriangle,&fRayP) <= gs_fEpsilon ) { rkPoint = rkRay.Origin() + fRayP*rkRay.Direction(); return true; } return false; }
Real Mgc::SqrDistance (const Vector3& rkPoint, const Ray3& rkRay, Real* pfParam) { Vector3 kDiff = rkPoint - rkRay.Origin(); Real fT = kDiff.Dot(rkRay.Direction()); if ( fT <= 0.0f ) { fT = 0.0f; } else { fT /= rkRay.Direction().SquaredLength(); kDiff -= fT*rkRay.Direction(); } if ( pfParam ) *pfParam = fT; return kDiff.SquaredLength(); }
//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Ray3& rkRay, const Box3& rkBox, int& riQuantity, Vector3 akPoint[2]) { // convert ray to box coordinates Vector3 kDiff = rkRay.Origin() - rkBox.Center(); Vector3 kOrigin( kDiff.Dot(rkBox.Axis(0)), kDiff.Dot(rkBox.Axis(1)), kDiff.Dot(rkBox.Axis(2)) ); Vector3 kDirection( rkRay.Direction().Dot(rkBox.Axis(0)), rkRay.Direction().Dot(rkBox.Axis(1)), rkRay.Direction().Dot(rkBox.Axis(2)) ); Real fT0 = 0.0f, fT1 = Math::MAX_REAL; bool bIntersects = FindIntersection(kOrigin,kDirection,rkBox.Extents(), fT0,fT1); if ( bIntersects ) { if ( fT0 > 0.0f ) { riQuantity = 2; akPoint[0] = rkRay.Origin() + fT0*rkRay.Direction(); akPoint[1] = rkRay.Origin() + fT1*rkRay.Direction(); } else // fT0 == 0 { riQuantity = 1; akPoint[0] = rkRay.Origin() + fT1*rkRay.Direction(); } } else { riQuantity = 0; } return bIntersects; }
Real Wml::SqrDistance (const Vector3<Real>& rkPoint, const Ray3<Real>& rkRay, Real* pfParam) { Vector3<Real> kDiff = rkPoint - rkRay.Origin(); Real fT = kDiff.Dot(rkRay.Direction()); if ( fT <= (Real)0.0 ) { fT = (Real)0.0; } else { fT /= rkRay.Direction().SquaredLength(); kDiff -= fT*rkRay.Direction(); } if ( pfParam ) *pfParam = fT; return kDiff.SquaredLength(); }
//---------------------------------------------------------------------------- Real Mgc::SqrDistance (const Ray3& rkRay, const Box3& rkBox, Real* pfLParam, Real* pfBParam0, Real* pfBParam1, Real* pfBParam2) { #ifdef _DEBUG // The four parameters pointers are either all non-null or all null. if ( pfLParam ) { assert( pfBParam0 && pfBParam1 && pfBParam2 ); } else { assert( !pfBParam0 && !pfBParam1 && !pfBParam2 ); } #endif Line3 kLine; kLine.Origin() = rkRay.Origin(); kLine.Direction() = rkRay.Direction(); Real fLP, fBP0, fBP1, fBP2; Real fSqrDistance = SqrDistance(kLine,rkBox,&fLP,&fBP0,&fBP1,&fBP2); if ( fLP >= 0.0f ) { if ( pfLParam ) { *pfLParam = fLP; *pfBParam0 = fBP0; *pfBParam1 = fBP1; *pfBParam2 = fBP2; } return fSqrDistance; } else { fSqrDistance = SqrDistance(rkRay.Origin(),rkBox,pfBParam0, pfBParam1,pfBParam2); if ( pfLParam ) *pfLParam = 0.0f; return fSqrDistance; } }
bool Mgc::FindIntersection (const Ray3& rkRay, const Sphere& rkSphere, int& riQuantity, Vector3 akPoint[2]) { // set up quadratic Q(t) = a*t^2 + 2*b*t + c Vector3 kDiff = rkRay.Origin() - rkSphere.Center(); Real fA = rkRay.Direction().SquaredLength(); Real fB = kDiff.Dot(rkRay.Direction()); Real fC = kDiff.SquaredLength() - rkSphere.Radius()*rkSphere.Radius(); Real afT[2]; Real fDiscr = fB*fB - fA*fC; if ( fDiscr < 0.0f ) { riQuantity = 0; return false; } else if ( fDiscr > 0.0f ) { Real fRoot = Math::Sqrt(fDiscr); Real fInvA = 1.0f/fA; afT[0] = (-fB - fRoot)*fInvA; afT[1] = (-fB + fRoot)*fInvA; if ( afT[0] >= 0.0f ) { riQuantity = 2; akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction(); akPoint[1] = rkRay.Origin() + afT[1]*rkRay.Direction(); return true; } else if ( afT[1] >= 0.0f ) { riQuantity = 1; akPoint[0] = rkRay.Origin() + afT[1]*rkRay.Direction(); return true; } else { riQuantity = 0; return false; } } else { afT[0] = -fB/fA; if ( afT[0] >= 0.0f ) { riQuantity = 1; akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction(); return true; } else { riQuantity = 0; return false; } } }