Crash in CalculateContactToConvexHullDescrete

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Thu Oct 30, 2014 5:55 pm

In the function dgInt32 dgCollisionConvexPolygon::CalculateContactToConvexHullDescrete() I get a crash with a terrain against a convex hull shape. The crash occurs because m_count is a huge number. It looks like an unintialized variable. I ran Dr. Memory on my program, and it didn't detect any problems until this function call, when a block lands on the terrain.
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Thu Oct 30, 2014 6:00 pm

can you sync and tell the line? and the trace stack?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Thu Oct 30, 2014 6:17 pm

I also ran "Application Verifier" and got the same result. It's at line 529 in dgCollisionConvexPolygon.cpp.
Attachments
Untitled.jpg
Untitled.jpg (213.59 KiB) Viewed 6269 times
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Fri Oct 31, 2014 9:18 am

dgCollisionConvexPolygon is a collision shape, that is used to turn the faces of a polygonal mesh that can overlap of an box, into collision collision shapes on thy fly.
The data in populated on the stack by the caller function, that function is called form only one place
so it should be easy to see when the value become bad

the function is call form here

Code: Select all
dgInt32 dgWorld::CalculatePolySoupToHullContactsDescrete (dgCollisionParamProxy& proxy) const
{
   dgInt32 count = 0;
   dgAssert (proxy.m_floatingCollision->IsType (dgCollision::dgCollisionMesh_RTTI));
   dgAssert (proxy.m_referenceCollision->IsType (dgCollision::dgCollisionConvexShape_RTTI));

   dgCollisionInstance* const polySoupInstance = proxy.m_floatingCollision;
   dgPolygonMeshDesc& data = *proxy.m_polyMeshData;

   dgAssert (data.m_faceCount);

   dgCollisionConvexPolygon polygon (m_allocator);
   dgCollisionInstance polyInstance (*polySoupInstance, &polygon);
   polyInstance.SetScale(dgVector (dgFloat32 (1.0f)));

   proxy.m_floatingCollision = &polyInstance;

   polygon.m_vertex = data.m_vertex;
   polygon.m_stride = dgInt32 (data.m_vertexStrideInBytes / sizeof (dgFloat32));

   dgInt32 maxContacts = proxy.m_maxContacts;
   dgInt32 maxReduceLimit = maxContacts >> 2;
   dgInt32 countleft = maxContacts;

   dgAssert (proxy.m_contactJoint);
   dgVector separatingVector (proxy.m_matrix.m_posit & dgVector::m_triplexMask);
   dgFloat32 mag2 = separatingVector.DotProduct4 (separatingVector).m_x;
   if (mag2 > dgFloat32 (0.0f)) {
      separatingVector = separatingVector.Scale3 (dgRsqrt (mag2));
   } else {
      separatingVector =  dgVector(dgFloat32 (1.0f), dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
   }

   const dgVector& scale = polySoupInstance->GetScale();
   const dgVector& invScale = polySoupInstance->GetInvScale();
   const dgInt32 stride = polygon.m_stride;
   const dgFloat32* const vertex = polygon.m_vertex;

   dgAssert (polyInstance.m_scaleType == dgCollisionInstance::m_unit);
   dgFloat32 closestDist = dgFloat32 (1.0e10f);
   dgContactPoint* const contactOut = proxy.m_contacts;
   dgContact* const contactJoint = proxy.m_contactJoint;
   dgInt32* const indexArray = (dgInt32*)data.m_faceVertexIndex;
   data.SortFaceArray();

   for (dgInt32 i = data.m_faceCount - 1; (i >= 0) && (count < 32); i --) {
      dgInt32 address = data.m_faceIndexStart[i];
      const dgInt32* const localIndexArray = &indexArray[address];

      polygon.m_vertexIndex = localIndexArray;

[color=#FF0040]// set a break point here and see why the face is bad, since you are doing terrain collision
// face count should be three.
[/color]      polygon.m_count = data.m_faceIndexCount[i];
      polygon.m_adjacentFaceEdgeNormalIndex = data.GetAdjacentFaceEdgeNormalArray (localIndexArray, polygon.m_count);
      polygon.m_faceId = data.GetFaceId (localIndexArray, polygon.m_count);
      polygon.m_faceClipSize = data.GetFaceSize (localIndexArray, polygon.m_count);
      polygon.m_faceNormalIndex = data.GetNormalIndex (localIndexArray, polygon.m_count);
      polygon.m_normal = dgVector (&vertex[polygon.m_faceNormalIndex * stride]);
      dgAssert (dgAbsf(polygon.m_normal % polygon.m_normal - dgFloat32 (1.0f)) < dgFloat32 (1.0e-4f));
      dgAssert (polygon.m_normal.m_w == dgFloat32 (0.0f));
      contactJoint->m_separtingVector = separatingVector;

      proxy.m_maxContacts = countleft;
      proxy.m_contacts = &contactOut[count];
      dgInt32 count1 = polygon.CalculateContactToConvexHullDescrete (proxy, scale, invScale);
      closestDist = dgMin(closestDist, contactJoint->m_closestDistance);



I think the data you are shows bad because you are using a release build,

you can single out that that file and set debug compilier options, that way you can see beter why the count and the other dat is bad.
My guess is that is may be a memory over run.

The first thing to check in how many face are coming from function

Code: Select all
      dgCollisionMesh* const polysoup = (dgCollisionMesh *) data.m_polySoupCollision->GetChildShape();
      polysoup->GetCollidingFaces (&data);


that after that the face are sorted by the likelihood of collision first, that cont may be corrupted there.

set these file in debug mode, and when is crash see when the data when wrong

\coreLibrary_300\source\physics\dgCollisionConvexPolygon.cpp
\coreLibrary_300\source\physics\dgNarrowPhaseCollision.cpp

do not set the whole project in debug just the relevant file, that way you increase the chance of the bug happens.

Is you collison happening between a big convex shape and a high rest terrain?
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Fri Oct 31, 2014 5:14 pm

Is you collison happening between a big convex shape and a high rest terrain?

Yes. It is a large box shape on a terrain.

I don't use the Newton DLL, I just compile the Newton source code into my project. This is running with debug enabled.

I do have dgassert disabled, otherwise it hits some of the asserts earlier in the function, like the sizeof check.
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Fri Oct 31, 2014 5:47 pm

I'm installing VS pro to check for memory overruns. I assumed Application Verifier does this?
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Fri Oct 31, 2014 7:49 pm

the assert are important because you maybe have a early warining of what happens.

if the box is very large, and is collet too many triangle them the bug that might be an indication what where the problem is.

Memory overrun tool may not give to any useful information. Try setting a break point in terrain get colliding faces, and see if the face count is very large.

a large box when lading covet and area that is very could be very big and may cause the overrun.
I belie they are check for that, but iof you disable them it may be too large

do this test, reduce the box by half this will coy the facer found face by the square root,
if the crash go away, then increase the box size gradually only you fond the point at witch the crash happens. The engine has a debug call back for Polygonal meshed. It shows the faces that were colletect on each call to GetFeceCount, that will also tell you if the crash is dues to too many faces.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Fri Oct 31, 2014 8:40 pm

I remove the assert because I can't have my users running into random crashes in their programs, and not knowing why it's happening.

Here's a printout of the face count:
Code: Select all
269
0
1
322
0
6
354
0
6
340
0
6
289
1
6
226
6
6
177
6
6
139
6
6
6
6
103
6
6
6
6
52
26
4
0
2
1
1
0
0
0
0
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
3
10
27
164
134
113
94
83
69
61
88
119
161
173
181
177
179
186
191
192
202
214
221
224
224
221
219
217
(crash)


I just found the value DG_MAX_COLLIDING_FACES. If I increase this from 512 to 1024 the crash does not occur. Shouldn't the routine check to make sure the colliding faces are less than this value, and silently skip anything that goes beyond this?
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Fri Oct 31, 2014 9:17 pm

where does it says that the assert are for people use in a final application?
Assert are a start programing practice.
they are for the developer to detect condition that may be dangerous and make corrections.

by making that value 10 time bigger you are now change a whole lot of internal data structure when it looks as if this is not the problem.

The face count is is set to 512 and non of your counts come even close untiI it crashes.
The function does stops collecting face when the count or the index count reach that limit.

Code: Select all
dgIntersectStatus dgCollisionBVH::GetPolygon (void* const context, const dgFloat32* const polygon, dgInt32 strideInBytes, const dgInt32* const indexArray, dgInt32 indexCount, dgFloat32 hitDistance)
{
   dgPolygonMeshDesc& data = (*(dgPolygonMeshDesc*) context);
   if (data.m_faceCount >= DG_MAX_COLLIDING_FACES) {
      dgTrace (("buffer Over float, try using a lower resolution mesh for collision\n"));
      return t_StopSearh;
   }
   if ((data.m_globalIndexCount + indexCount * 2 + 3) >= DG_MAX_COLLIDING_INDICES) {
      dgTrace (("buffer Over float, try using a lower resolution mesh for collision\n"));
      return t_StopSearh;
   }



but now I see what the problems is, in the hieghfield code, there is not check for that.
in file
C:\Users\jjerez\Downloads\newton-dynamics\coreLibrary_300\source\physics\dgCollisionHeightField.cpp
line 965 you can add this

Code: Select all
   for (dgInt32 z = z0; (z < z1) && (faceCount < DG_MAX_COLLIDING_FACES); z ++) {
         dgInt32 zStep = z * m_width;
         for (dgInt32 x = x0; (x < x1) && (faceCount < DG_MAX_COLLIDING_FACES); x ++) {
            const dgInt32* const indirectIndex = &m_cellIndices[dgInt32 (m_diagonals[zStep + x])][0];


but that does not really fixes the problem because the code is picking a very large number of faces, either your terrain is too high rest or the AABB of the shape landing on the terrain is very big. 512 faces to detect just 4 to 8 contacts is a lot of work for only one shape.

bailing out will generate a collision malfunction because now the contact will not be the necessary one to support the shape, after faces are is collected the engine reject the once the are in the middle because those do not contribute to collision sine a contact in the model can be represent by a convex combination of the extreme contacts. be the cap prevent that for happening.

if you sync I added that limit, I will normally put an assert there indication that that is a warning, but this time I will not, I will do it later thought.
the assert if a good programing practice.

finally I would try doubling the limit, not making 5 time bigger
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Fri Oct 31, 2014 9:36 pm

I was wrong about the face count, the point where it crashes actually is when the facecount reaches 512.
Last edited by pHySiQuE on Fri Oct 31, 2014 9:45 pm, edited 1 time in total.
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Fri Oct 31, 2014 9:43 pm

Here's the new result:
Attachments
Image2.jpg
Image2.jpg (214.35 KiB) Viewed 6204 times
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Fri Oct 31, 2014 9:54 pm

oh yes that also has to be changed, just make the MAX_FACE_COUNT 1024 or 2048 for now, I will fix that tonight.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby Julio Jerez » Sat Nov 01, 2014 11:21 am

Ok I added that check.

The one thing I am saying is that if you have a shape that is hitting a heightfield flat and is finding more than 512 faces, that means is it finding an aread of
cell = 512 / 2 = 256 cells, the squared root of that is 16
assuming the height field one cell represent on meter.
this means your shape cover an are larger that 16 x 16 meters.
if you double the Max Face the area the are is only 22 x 22 and double again gives 32 x 32 and so son

but each time you do that you are adding lot of stress on the collision system for just one small gain.
this is a very big single shape.

The trick to make good games is to be clever not to stress the technology as most that you can just because you can.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Crash in CalculateContactToConvexHullDescrete

Postby pHySiQuE » Sat Nov 01, 2014 2:45 pm

I don't disagree with that, but my users will do everything and anything under the sun without regards to what is "right". If my engine doesn't work the way they expect, I take the blame. That turns into bad opinions of the software, regardless of the reason, and that loses money. And I like money. So please don't do this again. :mrgreen:
pHySiQuE
 
Posts: 608
Joined: Fri Sep 02, 2011 9:54 pm


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 2 guests

cron