bool Mgc::TestIntersection (const Line3& rkLine, const Sphere& rkSphere) { Real fSqrDist = SqrDistance(rkSphere.Center(),rkLine); return fSqrDist <= rkSphere.Radius()*rkSphere.Radius(); }
Sphere Mgc::ContSphereOfAABB (int iQuantity, const Vector3* akPoint) { Vector3 kMin = akPoint[0], kMax = kMin; for (int i = 1; i < iQuantity; i++) { if ( akPoint[i].x < kMin.x ) kMin.x = akPoint[i].x; else if ( akPoint[i].x > kMax.x ) kMax.x = akPoint[i].x; if ( akPoint[i].y < kMin.y ) kMin.y = akPoint[i].y; else if ( akPoint[i].y > kMax.y ) kMax.y = akPoint[i].y; if ( akPoint[i].z < kMin.z ) kMin.z = akPoint[i].z; else if ( akPoint[i].z > kMax.z ) kMax.z = akPoint[i].z; } Sphere kSphere; kSphere.Center() = 0.5f*(kMax + kMin); Vector3 kHalfDiagonal = 0.5f*(kMax - kMin); kSphere.Radius() = kHalfDiagonal.Length(); return kSphere; }
//---------------------------------------------------------------------------- Sphere Mgc::MergeSpheres (const Sphere& rkSphere0, const Sphere& rkSphere1) { Vector3 kCDiff = rkSphere1.Center() - rkSphere0.Center(); Real fLSqr = kCDiff.SquaredLength(); Real fRDiff = rkSphere1.Radius() - rkSphere0.Radius(); Real fRDiffSqr = fRDiff*fRDiff; if ( fRDiffSqr >= fLSqr ) return ( fRDiff >= 0.0f ? rkSphere1 : rkSphere0 ); Real fLength = Math::Sqrt(fLSqr); const Real fTolerance = 1e-06f; Sphere kSphere; if ( fLength > fTolerance ) { Real fCoeff = (fLength + fRDiff)/(2.0f*fLength); kSphere.Center() = rkSphere0.Center() + fCoeff*kCDiff; } else { kSphere.Center() = rkSphere0.Center(); } kSphere.Radius() = 0.5f*(fLength + rkSphere0.Radius() + rkSphere1.Radius()); return kSphere; }
//---------------------------------------------------------------------------- bool Mgc::Culled (const Plane& rkPlane, const Sphere& rkSphere, bool bUnitNormal) { Vector3 kNormal = rkPlane.Normal(); Real fConstant = rkPlane.Constant(); if ( !bUnitNormal ) { Real fLength = kNormal.Unitize(); fConstant /= fLength; } Real fTmp = kNormal.Dot(rkSphere.Center()) - fConstant; return fTmp <= -rkSphere.Radius(); }
//---------------------------------------------------------------------------- bool Mgc::TestIntersection (const Plane& rkPlane, const Sphere& rkSphere, bool bUnitNormal) { Vector3 kNormal = rkPlane.Normal(); Real fConstant = rkPlane.Constant(); if ( !bUnitNormal ) { Real fLength = kNormal.Unitize(); fConstant /= fLength; } Real fPseudoDistance = kNormal.Dot(rkSphere.Center()) - fConstant; return Math::FAbs(fPseudoDistance) <= rkSphere.Radius(); }
bool Mgc::InSphere (const Vector3& rkPoint, const Sphere& rkSphere, Real fEpsilon) { Real fRSqr = rkSphere.Radius()*rkSphere.Radius(); Vector3 kDiff = rkPoint - rkSphere.Center(); Real fSqrDist = kDiff.SquaredLength(); return fSqrDist <= fRSqr + fEpsilon; }
Sphere Mgc::ContSphereAverage (int iQuantity, const Vector3* akPoint) { Vector3 kCenter = akPoint[0]; int i; for (i = 1; i < iQuantity; i++) kCenter += akPoint[i]; Real fInvQuantity = 1.0f/iQuantity; kCenter *= fInvQuantity; Real fMaxRadiusSqr = 0.0f; for (i = 0; i < iQuantity; i++) { Vector3 kDiff = akPoint[i] - kCenter; Real fRadiusSqr = kDiff.SquaredLength(); if ( fRadiusSqr > fMaxRadiusSqr ) fMaxRadiusSqr = fRadiusSqr; } Sphere kSphere; kSphere.Center() = kCenter; kSphere.Radius() = Math::Sqrt(fMaxRadiusSqr); return kSphere; }
//---------------------------------------------------------------------------- bool Mgc::ContSphereOfAABB (int iQuantity, const Vector3* akPoint, const bool* abValid, Sphere& rkSphere) { Vector3 kMin, kMax; int i; for (i = 0; i < iQuantity; i++) { if ( abValid[i] ) { kMin = akPoint[i]; kMax = kMin; break; } } if ( i == iQuantity ) return false; for (i++; i < iQuantity; i++) { if ( abValid[i] ) { if ( akPoint[i].x < kMin.x ) kMin.x = akPoint[i].x; else if ( akPoint[i].x > kMax.x ) kMax.x = akPoint[i].x; if ( akPoint[i].y < kMin.y ) kMin.y = akPoint[i].y; else if ( akPoint[i].y > kMax.y ) kMax.y = akPoint[i].y; if ( akPoint[i].z < kMin.z ) kMin.z = akPoint[i].z; else if ( akPoint[i].z > kMax.z ) kMax.z = akPoint[i].z; } } rkSphere.Center() = 0.5f*(kMax + kMin); Vector3 kHalfDiagonal = 0.5f*(kMax - kMin); rkSphere.Radius() = kHalfDiagonal.Length(); return true; }
//---------------------------------------------------------------------------- bool Mgc::ContSphereAverage (int iQuantity, const Vector3* akPoint, const bool* abValid, Sphere& rkSphere) { Vector3 kCenter = Vector3::ZERO; int i, iValidQuantity = 0; for (i = 0; i < iQuantity; i++) { if ( abValid[i] ) { kCenter += akPoint[i]; iValidQuantity++; } } if ( iValidQuantity == 0 ) return false; Real fInvQuantity = 1.0f/iValidQuantity; kCenter *= fInvQuantity; Real fMaxRadiusSqr = 0.0f; for (i = 0; i < iQuantity; i++) { if ( abValid[i] ) { Vector3 kDiff = akPoint[i] - kCenter; Real fRadiusSqr = kDiff.SquaredLength(); if ( fRadiusSqr > fMaxRadiusSqr ) fMaxRadiusSqr = fRadiusSqr; } } rkSphere.Center() = kCenter; rkSphere.Radius() = Math::Sqrt(fMaxRadiusSqr); return true; }
bool Mgc::FindIntersection (const Segment3& rkSegment, const Sphere& rkSphere, int& riQuantity, Vector3 akPoint[2]) { // set up quadratic Q(t) = a*t^2 + 2*b*t + c Vector3 kDiff = rkSegment.Origin() - rkSphere.Center(); Real fA = rkSegment.Direction().SquaredLength(); Real fB = kDiff.Dot(rkSegment.Direction()); Real fC = kDiff.SquaredLength() - rkSphere.Radius()*rkSphere.Radius(); // no intersection if Q(t) has no real roots 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; // assert: t0 < t1 since A > 0 if ( afT[0] > 1.0f || afT[1] < 0.0f ) { riQuantity = 0; return false; } else if ( afT[0] >= 0.0f ) { if ( afT[1] > 1.0f ) { riQuantity = 1; akPoint[0] = rkSegment.Origin()+afT[0]*rkSegment.Direction(); return true; } else { riQuantity = 2; akPoint[0] = rkSegment.Origin()+afT[0]*rkSegment.Direction(); akPoint[1] = rkSegment.Origin()+afT[1]*rkSegment.Direction(); return true; } } else // afT[1] >= 0 { riQuantity = 1; akPoint[0] = rkSegment.Origin()+afT[1]*rkSegment.Direction(); return true; } } else { afT[0] = -fB/fA; if ( 0.0f <= afT[0] && afT[0] <= 1.0f ) { riQuantity = 1; akPoint[0] = rkSegment.Origin()+afT[0]*rkSegment.Direction(); return true; } else { riQuantity = 0; return false; } } }
bool Mgc::FindIntersection (const Line3& rkLine, const Sphere& rkSphere, int& riQuantity, Vector3 akPoint[2]) { // set up quadratic Q(t) = a*t^2 + 2*b*t + c Vector3 kDiff = rkLine.Origin() - rkSphere.Center(); Real fA = rkLine.Direction().SquaredLength(); Real fB = kDiff.Dot(rkLine.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; riQuantity = 2; afT[0] = (-fB - fRoot)*fInvA; afT[1] = (-fB + fRoot)*fInvA; akPoint[0] = rkLine.Origin() + afT[0]*rkLine.Direction(); akPoint[1] = rkLine.Origin() + afT[1]*rkLine.Direction(); return true; } else { riQuantity = 1; afT[0] = -fB/fA; akPoint[0] = rkLine.Origin() + afT[0]*rkLine.Direction(); return true; } }
Sphere(const Sphere<U>& that) : _center(that.Center()) , _radius(that.Radius()) { assert(_radius >= T(0)); }
//---------------------------------------------------------------------------- bool Mgc::TestIntersection (const Sphere& rkSphere, const Frustum& rkFrustum) { Real fSqrDist = SqrDistance(rkSphere.Center(),rkFrustum); Real fSqrRadius = rkSphere.Radius()*rkSphere.Radius(); return fSqrDist <= fSqrRadius; }