PositionSolverManifold.cpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  * 1. The origin of this software must not be misrepresented; you must not
12  * claim that you wrote the original software. If you use this software
13  * in a product, an acknowledgment in the product documentation would be
14  * appreciated but is not required.
15  * 2. Altered source versions must be plainly marked as such, and must not be
16  * misrepresented as being the original software.
17  * 3. This notice may not be removed or altered from any source distribution.
18  */
19 
21 
22 namespace playrho {
23 namespace d2 {
24 
25 namespace {
26 
34 inline PositionSolverManifold GetForCircles(const Transformation& xfA, Length2 lp,
35  const Transformation& xfB, Length2 plp)
36 {
37  const auto pointA = Transform(lp, xfA);
38  const auto pointB = Transform(plp, xfB);
39  const auto delta = pointB - pointA; // The edge from pointA to pointB
40  const auto normal = GetUnitVector(delta, UnitVec::GetZero()); // The direction of the edge.
41  const auto midpoint = (pointA + pointB) / Real{2};
42  const auto separation = Dot(delta, normal); // The length of edge without doing sqrt again.
43  return PositionSolverManifold{normal, midpoint, separation};
44 }
45 
55 inline PositionSolverManifold GetForFaceA(const Transformation& xfA, Length2 lp, UnitVec ln,
56  const Transformation& xfB, Length2 plp)
57 {
58  const auto planePoint = Transform(lp, xfA);
59  const auto normal = Rotate(ln, xfA.q);
60  const auto clipPoint = Transform(plp, xfB);
61  const auto separation = Dot(clipPoint - planePoint, normal);
62  return PositionSolverManifold{normal, clipPoint, separation};
63 }
64 
74 inline PositionSolverManifold GetForFaceB(const Transformation& xfB, Length2 lp, UnitVec ln,
75  const Transformation& xfA, Length2 plp)
76 {
77  const auto planePoint = Transform(lp, xfB);
78  const auto normal = Rotate(ln, xfB.q);
79  const auto clipPoint = Transform(plp, xfA);
80  const auto separation = Dot(clipPoint - planePoint, normal);
81  // Negate normal to ensure the PSM normal points from A to B
82  return PositionSolverManifold{-normal, clipPoint, separation};
83 }
84 
85 } // unnamed namespace
86 
88  const Transformation& xfA, const Transformation& xfB)
89 {
90  switch (manifold.GetType())
91  {
93  return GetForCircles(xfA, manifold.GetLocalPoint(),
94  xfB, manifold.GetPoint(index).localPoint);
95  case Manifold::e_faceA:
96  return GetForFaceA(xfA, manifold.GetLocalPoint(), manifold.GetLocalNormal(),
97  xfB, manifold.GetPoint(index).localPoint);
98  case Manifold::e_faceB:
99  return GetForFaceB(xfB, manifold.GetLocalPoint(), manifold.GetLocalNormal(),
100  xfA, manifold.GetPoint(index).localPoint);
101  case Manifold::e_unset:
102  break;
103  }
104  assert(manifold.GetType() == Manifold::e_unset);
105  return PositionSolverManifold{GetInvalid<UnitVec>(), GetInvalid<Length2>(), GetInvalid<Length>()};
106 }
107 
108 } // namespace d2
109 } // namespace playrho