Bullet Collision Detection & Physics Library
btPersistentManifold.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 
17 #include "btPersistentManifold.h"
18 #include "LinearMath/btTransform.h"
19 
20 
27 
28 
31 m_body0(0),
32 m_body1(0),
33 m_cachedPoints (0),
34 m_index1a(0)
35 {
36 }
37 
38 
39 
40 
41 #ifdef DEBUG_PERSISTENCY
42 #include <stdio.h>
43 void btPersistentManifold::DebugPersistency()
44 {
45  int i;
46  printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
47  for (i=0;i<m_cachedPoints;i++)
48  {
49  printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
50  }
51 }
52 #endif //DEBUG_PERSISTENCY
53 
55 {
56 
57  void* oldPtr = pt.m_userPersistentData;
58  if (oldPtr)
59  {
60 #ifdef DEBUG_PERSISTENCY
61  int i;
62  int occurance = 0;
63  for (i=0;i<m_cachedPoints;i++)
64  {
65  if (m_pointCache[i].m_userPersistentData == oldPtr)
66  {
67  occurance++;
68  if (occurance>1)
69  printf("error in clearUserCache\n");
70  }
71  }
72  btAssert(occurance<=0);
73 #endif //DEBUG_PERSISTENCY
74 
76  {
77  (*gContactDestroyedCallback)(pt.m_userPersistentData);
78  pt.m_userPersistentData = 0;
79  }
80 
81 #ifdef DEBUG_PERSISTENCY
82  DebugPersistency();
83 #endif
84  }
85 
86 
87 }
88 
89 static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3)
90 {
91  // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
92 
93  btVector3 a[3],b[3];
94  a[0] = p0 - p1;
95  a[1] = p0 - p2;
96  a[2] = p0 - p3;
97  b[0] = p2 - p3;
98  b[1] = p1 - p3;
99  b[2] = p1 - p2;
100 
101  //todo: Following 3 cross production can be easily optimized by SIMD.
102  btVector3 tmp0 = a[0].cross(b[0]);
103  btVector3 tmp1 = a[1].cross(b[1]);
104  btVector3 tmp2 = a[2].cross(b[2]);
105 
106  return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2());
107 }
108 
110 {
111  //calculate 4 possible cases areas, and take biggest area
112  //also need to keep 'deepest'
113 
114  int maxPenetrationIndex = -1;
115 #define KEEP_DEEPEST_POINT 1
116 #ifdef KEEP_DEEPEST_POINT
117  btScalar maxPenetration = pt.getDistance();
118  for (int i=0;i<4;i++)
119  {
120  if (m_pointCache[i].getDistance() < maxPenetration)
121  {
122  maxPenetrationIndex = i;
123  maxPenetration = m_pointCache[i].getDistance();
124  }
125  }
126 #endif //KEEP_DEEPEST_POINT
127 
128  btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
129 
131  {
132  if (maxPenetrationIndex != 0)
133  {
136  btVector3 cross = a0.cross(b0);
137  res0 = cross.length2();
138  }
139  if (maxPenetrationIndex != 1)
140  {
143  btVector3 cross = a1.cross(b1);
144  res1 = cross.length2();
145  }
146 
147  if (maxPenetrationIndex != 2)
148  {
151  btVector3 cross = a2.cross(b2);
152  res2 = cross.length2();
153  }
154 
155  if (maxPenetrationIndex != 3)
156  {
159  btVector3 cross = a3.cross(b3);
160  res3 = cross.length2();
161  }
162  }
163  else
164  {
165  if(maxPenetrationIndex != 0) {
167  }
168 
169  if(maxPenetrationIndex != 1) {
171  }
172 
173  if(maxPenetrationIndex != 2) {
175  }
176 
177  if(maxPenetrationIndex != 3) {
179  }
180  }
181  btVector4 maxvec(res0,res1,res2,res3);
182  int biggestarea = maxvec.closestAxis4();
183  return biggestarea;
184 
185 }
186 
187 
189 {
191  int size = getNumContacts();
192  int nearestPoint = -1;
193  for( int i = 0; i < size; i++ )
194  {
195  const btManifoldPoint &mp = m_pointCache[i];
196 
197  btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
198  const btScalar distToManiPoint = diffA.dot(diffA);
199  if( distToManiPoint < shortestDist )
200  {
201  shortestDist = distToManiPoint;
202  nearestPoint = i;
203  }
204  }
205  return nearestPoint;
206 }
207 
208 int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive)
209 {
210  if (!isPredictive)
211  {
212  btAssert(validContactDistance(newPoint));
213  }
214 
215  int insertIndex = getNumContacts();
216  if (insertIndex == MANIFOLD_CACHE_SIZE)
217  {
218 #if MANIFOLD_CACHE_SIZE >= 4
219  //sort cache so best points come first, based on area
220  insertIndex = sortCachedPoints(newPoint);
221 #else
222  insertIndex = 0;
223 #endif
224  clearUserCache(m_pointCache[insertIndex]);
225 
226  } else
227  {
228  m_cachedPoints++;
229 
230 
231  }
232  if (insertIndex<0)
233  insertIndex=0;
234 
235  btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
236  m_pointCache[insertIndex] = newPoint;
237  return insertIndex;
238 }
239 
241 {
243 }
244 
245 
246 
248 {
249  int i;
250 #ifdef DEBUG_PERSISTENCY
251  printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
252  trA.getOrigin().getX(),
253  trA.getOrigin().getY(),
254  trA.getOrigin().getZ(),
255  trB.getOrigin().getX(),
256  trB.getOrigin().getY(),
257  trB.getOrigin().getZ());
258 #endif //DEBUG_PERSISTENCY
259  for (i=getNumContacts()-1;i>=0;i--)
261  {
262  btManifoldPoint &manifoldPoint = m_pointCache[i];
263  manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
264  manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
265  manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
266  manifoldPoint.m_lifeTime++;
267  }
268 
270  btScalar distance2d;
271  btVector3 projectedDifference,projectedPoint;
272  for (i=getNumContacts()-1;i>=0;i--)
273  {
274 
275  btManifoldPoint &manifoldPoint = m_pointCache[i];
276  //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
277  if (!validContactDistance(manifoldPoint))
278  {
280  } else
281  {
282  //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
283  projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
284  projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
285  distance2d = projectedDifference.dot(projectedDifference);
287  {
289  } else
290  {
291  //contact point processed callback
293  (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
294  }
295  }
296  }
297 #ifdef DEBUG_PERSISTENCY
298  DebugPersistency();
299 #endif //
300 }
301 
302 
303 
304 
305