123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- #pragma once
- #include <Mathematics/DCPQuery.h>
- #include <Mathematics/Segment.h>
- namespace WwiseGTE
- {
- template <int N, typename Real>
- class DCPQuery<Real, Segment<N, Real>, Segment<N, Real>>
- {
- public:
- struct Result
- {
- Real distance, sqrDistance;
- Real parameter[2];
- Vector<N, Real> closest[2];
- };
- Result operator()(Segment<N, Real> const& segment0,
- Segment<N, Real> const& segment1)
- {
- return operator()(segment0.p[0], segment0.p[1], segment1.p[0], segment1.p[1]);
- }
- Result operator()(Vector<N, Real> const& P0, Vector<N, Real> const& P1,
- Vector<N, Real> const& Q0, Vector<N, Real> const& Q1)
- {
- Result result;
-
-
-
-
-
-
-
- Vector<N, Real> P1mP0 = P1 - P0;
- Vector<N, Real> Q1mQ0 = Q1 - Q0;
- Vector<N, Real> P0mQ0 = P0 - Q0;
- mA = Dot(P1mP0, P1mP0);
- mB = Dot(P1mP0, Q1mQ0);
- mC = Dot(Q1mQ0, Q1mQ0);
- mD = Dot(P1mP0, P0mQ0);
- mE = Dot(Q1mQ0, P0mQ0);
- mF00 = mD;
- mF10 = mF00 + mA;
- mF01 = mF00 - mB;
- mF11 = mF10 - mB;
- mG00 = -mE;
- mG10 = mG00 - mB;
- mG01 = mG00 + mC;
- mG11 = mG10 + mC;
- if (mA > (Real)0 && mC > (Real)0)
- {
-
-
-
-
-
-
-
- Real sValue[2];
- sValue[0] = GetClampedRoot(mA, mF00, mF10);
- sValue[1] = GetClampedRoot(mA, mF01, mF11);
- int classify[2];
- for (int i = 0; i < 2; ++i)
- {
- if (sValue[i] <= (Real)0)
- {
- classify[i] = -1;
- }
- else if (sValue[i] >= (Real)1)
- {
- classify[i] = +1;
- }
- else
- {
- classify[i] = 0;
- }
- }
- if (classify[0] == -1 && classify[1] == -1)
- {
-
- result.parameter[0] = (Real)0;
- result.parameter[1] = GetClampedRoot(mC, mG00, mG01);
- }
- else if (classify[0] == +1 && classify[1] == +1)
- {
-
- result.parameter[0] = (Real)1;
- result.parameter[1] = GetClampedRoot(mC, mG10, mG11);
- }
- else
- {
-
-
-
-
-
- int edge[2];
- Real end[2][2];
- ComputeIntersection(sValue, classify, edge, end);
-
-
-
-
-
-
-
- ComputeMinimumParameters(edge, end, result.parameter);
- }
- }
- else
- {
- if (mA > (Real)0)
- {
-
-
-
-
-
- result.parameter[0] = GetClampedRoot(mA, mF00, mF10);
- result.parameter[1] = (Real)0;
- }
- else if (mC > (Real)0)
- {
-
-
-
-
-
- result.parameter[0] = (Real)0;
- result.parameter[1] = GetClampedRoot(mC, mG00, mG01);
- }
- else
- {
-
- result.parameter[0] = (Real)0;
- result.parameter[1] = (Real)0;
- }
- }
- result.closest[0] =
- ((Real)1 - result.parameter[0]) * P0 + result.parameter[0] * P1;
- result.closest[1] =
- ((Real)1 - result.parameter[1]) * Q0 + result.parameter[1] * Q1;
- Vector<N, Real> diff = result.closest[0] - result.closest[1];
- result.sqrDistance = Dot(diff, diff);
- result.distance = std::sqrt(result.sqrDistance);
- return result;
- }
- private:
-
-
-
- Real GetClampedRoot(Real slope, Real h0, Real h1)
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Real r;
- if (h0 < (Real)0)
- {
- if (h1 > (Real)0)
- {
- r = -h0 / slope;
- if (r > (Real)1)
- {
- r = (Real)0.5;
- }
-
-
- }
- else
- {
- r = (Real)1;
- }
- }
- else
- {
- r = (Real)0;
- }
- return r;
- }
-
-
-
-
- void ComputeIntersection(Real const sValue[2], int const classify[2],
- int edge[2], Real end[2][2])
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (classify[0] < 0)
- {
- edge[0] = 0;
- end[0][0] = (Real)0;
- end[0][1] = mF00 / mB;
- if (end[0][1] < (Real)0 || end[0][1] > (Real)1)
- {
- end[0][1] = (Real)0.5;
- }
- if (classify[1] == 0)
- {
- edge[1] = 3;
- end[1][0] = sValue[1];
- end[1][1] = (Real)1;
- }
- else
- {
- edge[1] = 1;
- end[1][0] = (Real)1;
- end[1][1] = mF10 / mB;
- if (end[1][1] < (Real)0 || end[1][1] > (Real)1)
- {
- end[1][1] = (Real)0.5;
- }
- }
- }
- else if (classify[0] == 0)
- {
- edge[0] = 2;
- end[0][0] = sValue[0];
- end[0][1] = (Real)0;
- if (classify[1] < 0)
- {
- edge[1] = 0;
- end[1][0] = (Real)0;
- end[1][1] = mF00 / mB;
- if (end[1][1] < (Real)0 || end[1][1] > (Real)1)
- {
- end[1][1] = (Real)0.5;
- }
- }
- else if (classify[1] == 0)
- {
- edge[1] = 3;
- end[1][0] = sValue[1];
- end[1][1] = (Real)1;
- }
- else
- {
- edge[1] = 1;
- end[1][0] = (Real)1;
- end[1][1] = mF10 / mB;
- if (end[1][1] < (Real)0 || end[1][1] > (Real)1)
- {
- end[1][1] = (Real)0.5;
- }
- }
- }
- else
- {
- edge[0] = 1;
- end[0][0] = (Real)1;
- end[0][1] = mF10 / mB;
- if (end[0][1] < (Real)0 || end[0][1] > (Real)1)
- {
- end[0][1] = (Real)0.5;
- }
- if (classify[1] == 0)
- {
- edge[1] = 3;
- end[1][0] = sValue[1];
- end[1][1] = (Real)1;
- }
- else
- {
- edge[1] = 0;
- end[1][0] = (Real)0;
- end[1][1] = mF00 / mB;
- if (end[1][1] < (Real)0 || end[1][1] > (Real)1)
- {
- end[1][1] = (Real)0.5;
- }
- }
- }
- }
-
-
- void ComputeMinimumParameters(int const edge[2], Real const end[2][2],
- Real parameter[2])
- {
- Real delta = end[1][1] - end[0][1];
- Real h0 = delta * (-mB * end[0][0] + mC * end[0][1] - mE);
- if (h0 >= (Real)0)
- {
- if (edge[0] == 0)
- {
- parameter[0] = (Real)0;
- parameter[1] = GetClampedRoot(mC, mG00, mG01);
- }
- else if (edge[0] == 1)
- {
- parameter[0] = (Real)1;
- parameter[1] = GetClampedRoot(mC, mG10, mG11);
- }
- else
- {
- parameter[0] = end[0][0];
- parameter[1] = end[0][1];
- }
- }
- else
- {
- Real h1 = delta * (-mB * end[1][0] + mC * end[1][1] - mE);
- if (h1 <= (Real)0)
- {
- if (edge[1] == 0)
- {
- parameter[0] = (Real)0;
- parameter[1] = GetClampedRoot(mC, mG00, mG01);
- }
- else if (edge[1] == 1)
- {
- parameter[0] = (Real)1;
- parameter[1] = GetClampedRoot(mC, mG10, mG11);
- }
- else
- {
- parameter[0] = end[1][0];
- parameter[1] = end[1][1];
- }
- }
- else
- {
- Real z = std::min(std::max(h0 / (h0 - h1), (Real)0), (Real)1);
- Real omz = (Real)1 - z;
- parameter[0] = omz * end[0][0] + z * end[1][0];
- parameter[1] = omz * end[0][1] + z * end[1][1];
- }
- }
- }
-
- Real mA, mB, mC, mD, mE;
-
- Real mF00, mF10, mF01, mF11;
-
- Real mG00, mG10, mG01, mG11;
- };
-
- template <int N, typename Real>
- using DCPSegmentSegment = DCPQuery<Real, Segment<N, Real>, Segment<N, Real>>;
- template <typename Real>
- using DCPSegment2Segment2 = DCPSegmentSegment<2, Real>;
- template <typename Real>
- using DCPSegment3Segment3 = DCPSegmentSegment<3, Real>;
- }
|