Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/bullet/Bullet/NarrowPhaseCollision/PersistentManifold.cpp')
-rw-r--r--extern/bullet/Bullet/NarrowPhaseCollision/PersistentManifold.cpp182
1 files changed, 182 insertions, 0 deletions
diff --git a/extern/bullet/Bullet/NarrowPhaseCollision/PersistentManifold.cpp b/extern/bullet/Bullet/NarrowPhaseCollision/PersistentManifold.cpp
new file mode 100644
index 00000000000..9085ffa0ef0
--- /dev/null
+++ b/extern/bullet/Bullet/NarrowPhaseCollision/PersistentManifold.cpp
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
+*
+* Permission to use, copy, modify, distribute and sell this software
+* and its documentation for any purpose is hereby granted without fee,
+* provided that the above copyright notice appear in all copies.
+* Erwin Coumans makes no representations about the suitability
+* of this software for any purpose.
+* It is provided "as is" without express or implied warranty.
+*/
+
+
+#include "PersistentManifold.h"
+#include "SimdTransform.h"
+#include <assert.h>
+
+
+PersistentManifold::PersistentManifold()
+:m_body0(0),
+m_body1(0),
+m_cachedPoints (0),
+m_index1(0)
+{
+}
+
+
+void PersistentManifold::ClearManifold()
+{
+ m_cachedPoints = 0;
+}
+
+
+
+
+
+int PersistentManifold::SortCachedPoints(const ManifoldPoint& pt)
+{
+
+ //calculate 4 possible cases areas, and take biggest area
+
+ SimdScalar res0,res1,res2,res3;
+
+ {
+ SimdVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+ SimdVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ SimdVector3 cross = a0.cross(b0);
+ res0 = cross.length2();
+ }
+ {
+ SimdVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ SimdVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+ SimdVector3 cross = a1.cross(b1);
+ res1 = cross.length2();
+ }
+ {
+ SimdVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ SimdVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+ SimdVector3 cross = a2.cross(b2);
+ res2 = cross.length2();
+ }
+ {
+ SimdVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+ SimdVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+ SimdVector3 cross = a3.cross(b3);
+ res3 = cross.length2();
+ }
+
+ SimdVector4 maxvec(res0,res1,res2,res3);
+ int biggestarea = maxvec.closestAxis4();
+
+ return biggestarea;
+
+
+}
+
+
+
+int PersistentManifold::GetCacheEntry(const ManifoldPoint& newPoint) const
+{
+ SimdScalar shortestDist = GetManifoldMargin() * GetManifoldMargin();
+ int size = GetNumContacts();
+ int nearestPoint = -1;
+ for( int i = 0; i < size; i++ )
+ {
+ const ManifoldPoint &mp = m_pointCache[i];
+
+ SimdVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
+ const SimdScalar distToManiPoint = diffA.dot(diffA);
+ if( distToManiPoint < shortestDist )
+ {
+ shortestDist = distToManiPoint;
+ nearestPoint = i;
+ }
+ }
+ return nearestPoint;
+}
+
+void PersistentManifold::AddManifoldPoint(const ManifoldPoint& newPoint)
+{
+ assert(ValidContactDistance(newPoint));
+
+ int insertIndex = GetNumContacts();
+ if (insertIndex == MANIFOLD_CACHE_SIZE)
+ {
+ //sort cache so best points come first
+ insertIndex = SortCachedPoints(newPoint);
+ } else
+ {
+ m_cachedPoints++;
+ }
+ ReplaceContactPoint(newPoint,insertIndex);
+}
+
+
+void PersistentManifold::RefreshContactPoints(const SimdTransform& trA,const SimdTransform& trB)
+{
+ int i;
+
+ /// first refresh worldspace positions and distance
+ for (i=GetNumContacts()-1;i>=0;i--)
+ {
+ ManifoldPoint &manifoldPoint = m_pointCache[i];
+ manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
+ manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
+ manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+ }
+
+ /// then
+ SimdScalar distance2d;
+ SimdVector3 projectedDifference,projectedPoint;
+ for (i=GetNumContacts()-1;i>=0;i--)
+ {
+
+ ManifoldPoint &manifoldPoint = m_pointCache[i];
+ //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+ if (!ValidContactDistance(manifoldPoint))
+ {
+ RemoveContactPoint(i);
+ } else
+ {
+ //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+ projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
+ projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
+ distance2d = projectedDifference.dot(projectedDifference);
+ if (distance2d > GetManifoldMargin()*GetManifoldMargin() )
+ {
+ RemoveContactPoint(i);
+ }
+ }
+ }
+}
+
+
+//todo: remove this treshold
+float gPenetrationDistanceCheck = -0.05f;
+
+float PersistentManifold::GetCollisionImpulse() const
+{
+ float averageImpulse = 0.f;
+ if (GetNumContacts() > 0)
+ {
+ float totalImpulse = 0.f;
+
+ //return the sum of the applied impulses on the box
+ for (int i=0;i<GetNumContacts();i++)
+ {
+ const ManifoldPoint& cp = GetContactPoint(i);
+ //avoid conflic noice
+ if ( cp.GetDistance() <gPenetrationDistanceCheck)
+ return 0.f;
+
+ totalImpulse += cp.m_appliedImpulse;
+
+ }
+ averageImpulse = totalImpulse / ((float)GetNumContacts());
+
+ }
+ return averageImpulse;
+
+}
+
+