Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post Reply
Dox
Posts: 24
Joined: Thu Oct 18, 2018 5:16 pm

Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by Dox » Tue Apr 09, 2019 10:21 am

Hello,

I have a "complex" btCompoundShape hierarchy structured like this:

Code: Select all

btCompoundShape_0
	|--- btCollisionShape_0
	|--- btCompoundShape_1
		|--- btCollisionShape_1
		|--- btCompoundShape_2
			|--- btCollisionShape_2
			.....	
Using the btPersistentManifold I can get the btCollisionObjects involved using the internal tick callback of btDynamicWorld:

Code: Select all

  
  ...
  int numManifolds = p_dynamics_world->getDispatcher()->getNumManifolds();
  for (unsigned int i = 0; i < numManifolds; i++) {
    btPersistentManifold* l_contact_manifold = p_dynamics_world->getDispatcher()->getManifoldByIndexInternal(i);
    const btCollisionObject *l_obj0 = l_contact_manifold->getBody0();
    const btCollisionObject *l_obj1 = l_contact_manifold->getBody1();
    int l_num_contacts = l_contact_manifold->getNumContacts();
    for(unsigned int j = 0; j < l_num_contacts; j++) {
        btManifoldPoint& pt = l_contact_manifold->getContactPoint(j);
        .....
    }        
l_obj0 and l_obj1 are the btRigidBody, in my case, and I can get the btCompoundShape (with getCollisionShape()) which is the root of the "complex" hierarchy cited above. I'm interested to find the specific btCollisionShape in the hierarchy (or the relative btCompoundShape direct father) which has the collision. I need to retrieve this information because I need to get my stored user pointer in the specific btCollisionShape (or btCompoundShape) in order to do some action when a contact happens.

Is this possible? Maybe is there the possibility to add specific callback to the element's hierarchy?

I found some attributes of the btManifoldPoint like m_index0/1 and m_part0/1 but inside the code there is this comment:

//BP mod, store contact triangles.

So I think those variables speaks about the number of contact in terms of triangles.

Can you help me?

Many thanks,

bye

steven
Posts: 54
Joined: Mon Nov 05, 2018 8:16 am
Location: China

Re: Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by steven » Tue Apr 09, 2019 1:11 pm

the gContactProcessedCallback is the contact point process callback, don't know if it can help you. you can refer to the NN3DWalkers.cpp for details.

Dox
Posts: 24
Joined: Thu Oct 18, 2018 5:16 pm

Re: Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by Dox » Wed Apr 10, 2019 4:41 pm

Hello steven,

Thanks for your suggestion but It seems to not solve the problem. Using gContactProcessedCallback/gContactAddedCallback I can retrieve the btRigidBody involved and get its own btCollisionShape: if this one is a btCompoundShape, how I can retrieve the specific child (or more than one) that are in collision?

I found a similar question in the github here:

https://github.com/bulletphysics/bullet3/issues/588

The question was marked "closed", but without explanation. The guy on the above thread speaks about recursive btCompoundShape that is my problem.

There is something I miss?

Best regards,

Bye

steven
Posts: 54
Joined: Mon Nov 05, 2018 8:16 am
Location: China

Re: Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by steven » Thu Apr 11, 2019 7:37 am

hi, i just review the engine code especially the file btCompoundCollisionAlgorithm.cpp and also did some test, i think the engine can't support your special case currently. from the code below it only can record the shape index at some compound shape but don't konw which compound shape it belongs to, so i don't think it can cover the recursive case.

Code: Select all

                        if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
			{
				tmpWrap = m_resultOut->getBody0Wrap();
				m_resultOut->setBody0Wrap(&compoundWrap);
				m_resultOut->setShapeIdentifiersA(-1, index);
			}
			else
			{
				tmpWrap = m_resultOut->getBody1Wrap();
				m_resultOut->setBody1Wrap(&compoundWrap);
				m_resultOut->setShapeIdentifiersB(-1, index);
			}

			algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut)
i make some change in the btCompoundCollisionAlgorithm.cpp and also create a test demo which should can meet your requirement. but be noted i don't sure if it will cause other issues because of this change. just for a reference in order to involve more guy's discussion.

i use ths m_partId0 to indicate the compound shape level and m_index0 to indicate the shape index in the compund shape.

the following is the code snippet that will be easy for other guy's review, more details are attached.

SimpleBox.cpp:

Code: Select all

bool testContactProcessedCallback(btManifoldPoint& cp, void* bod0, void* bod1)
{
	btCollisionObject* o1 = static_cast<btCollisionObject*>(bod0);
	btCollisionObject* o2 = static_cast<btCollisionObject*>(bod1);
	if (o1 == bodyGround || o2 == bodyGround) return true;
	printf("O1=%p, o2=%p ############\n", o1, o2);
	printf("m_partId0=%d, m_partId1=%d m_index0=%d m_index1=%d", cp.m_partId0, cp.m_partId1, cp.m_index0, cp.m_index1);

	const btCollisionShape* childShape = NULL;
	if (cp.m_index0 != -1)
	    childShape = compoundLevel[cp.m_partId0]->getChildShape(cp.m_index0);
	else if (cp.m_index1 != -1)
            childShape = compoundLevel[cp.m_partId1]->getChildShape(cp.m_index1);
	
	if (childShape == NULL)  
		printf("no compound shape #############");
	else
	    printf("childshape = %p  id=%p\n", childShape, childShape->getUserPointer())
btCompoundCollisionAlgorithm.cpp

Code: Select all

@@ -159,22 +159,39 @@ public:
 				algo = m_childCollisionAlgorithms[index];
 			}
 
 			const btCollisionObjectWrapper* tmpWrap = 0;
 
+                       int currentCompoundLevel = 0;
+			const btCollisionObjectWrapper* parentCompoundObj = 0;
+			parentCompoundObj = this->m_compoundColObjWrap->m_parent;
+			while (parentCompoundObj)
+			{
+				if (parentCompoundObj->getCollisionShape()->isCompound())
+				{
+					currentCompoundLevel++;
+					parentCompoundObj = parentCompoundObj->m_parent;
+				}
+				else
+				{
+					break;
+				}
+			}
 			///detect swapping case
 			if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
 			{
 				tmpWrap = m_resultOut->getBody0Wrap();
 				m_resultOut->setBody0Wrap(&compoundWrap);
-				m_resultOut->setShapeIdentifiersA(-1, index);
+				m_resultOut->setShapeIdentifiersA(currentCompoundLevel, index);
+				m_resultOut->setShapeIdentifiersB(-1, -1);
 			}
 			else
 			{
 				tmpWrap = m_resultOut->getBody1Wrap();
 				m_resultOut->setBody1Wrap(&compoundWrap);
-				m_resultOut->setShapeIdentifiersB(-1, index);
+				m_resultOut->setShapeIdentifiersB(currentCompoundLevel, index);
+				m_resultOut->setShapeIdentifiersA(-1, -1);
 			}
 
 			algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
 
 #if 0
Attachments
SimpleBox.cpp
(16.71 KiB) Downloaded 115 times
btManifoldResult.cpp
(8.75 KiB) Downloaded 108 times
btCompoundCollisionAlgorithm.cpp
(15.4 KiB) Downloaded 114 times

Dox
Posts: 24
Joined: Thu Oct 18, 2018 5:16 pm

Re: Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by Dox » Thu Apr 11, 2019 9:41 am

Hello,

thanks steven for your feedback.

Is not clear to me the original means of partId0/1 and index0/1. Code comments speaks about triangles, but in my tests partID is ever equals to -1 and index is variables (maybe the number of triangles in collision...).

I'll review and test your code ASAP.

Thanks again,

Bye

steven
Posts: 54
Joined: Mon Nov 05, 2018 8:16 am
Location: China

Re: Retrieve the specific btCollisionShape (in a btCompoundShape hierarchy) during a contact

Post by steven » Fri Apr 12, 2019 3:56 am

maybe these variables have different meaning for different collisionShap. for btCompoundShape the index should indicate the child shape index in the compoundShape from the code below. and it doesn't use the partd0/1 at all which value always is -1.

Code: Select all

const btCollisionShape* childShape = compoundShape->getChildShape(index)
this is my understanding just for your reference, for the triange mesh shape all the triages should be organized in a more efficient structure, like tree, the internel node can be identified by the partd0/1.

Overall, the partd0/1 is used to find the subpart from the whole and index0/1 is used to find one object in this subpart.

Post Reply