Example #1
0
void MyExtendedUserDataListener::contactPointAddedCallback(	hkpContactPointAddedEvent& event )
{
	//
	// Read the shape key hierarchy -- this is done identically for both Psi and Toi contact points.
	//
	hkpShapeKey shapeKey;
	{
		// This is the body to which the listener is attached.
		hkpEntity* body = event.m_callbackFiredFrom;

		// Extended user data only works when you use the default hkpSimpleConstraintContactMgr.
		// The function below will assert otherwise.

		// The atom caches information on how many extended user datas we store for each body.
		// Each body stores its data independently.
		const int numDatas = event.getNumExtendedUserDatas(event.m_callbackFiredFrom);

		// Now we can read the data.
		// The first user data stores the hkpShapeKey of the bottom most hkpCdBody in the shape hierarchy, 
		// the next one stores hkpShapeKey of its parent, and so on, till we store '-1' as the hkpShapeKey
		// of the root collidable, or we run out of extended user data slots, in which case only a part
		// of the hierarchy is stored.
		//
		// In this demo we expect to have:
		// extendedUserDatas[0] in the [0,7] range -- this is the hkpShapeKey of one of the 8 transformed sphere shapes grouped under a hkpListShape
		// extendedUserDatas[1] equal -1 -- this is the root hkpListShape, with no parent, and therefore no hkpShapeKey
		//
		// Note that we only have two levels of hierarchy, while our shape is composed of hkpListShape->hkpConvexTransformShape->hkpSphereShape.
		// That's because hkpConvexTransform/TranslateShapes don't create a corresponding hkpCdBody during collision detection.
		// Note that the above is not the case for the deprecated hkpTransformShape.
		hkInplaceArray<hkpContactPointProperties::UserData,8> data; data.setSize(numDatas);
		event.getExtendedUserDatas(body, data.begin(), numDatas);

		// Let us store our custom contact point id. Let's store it in the last data slot to avoid overwriting the hkpShapeKey hierarchy.
		// We know we have enough room, as we set entity->m_numUserDatasInContactPointProperties = 3 which is more that the max hierarchy depth for our shape.
		data[numDatas-1] = m_uniqueIdCounter++;

		// And write back all datas
		event.setExtendedUserDatas(body, data.begin(), numDatas);

		// Get the hkpShapeKey
		shapeKey = data[0];
	}

	// Sample demo structure holding history about callbacks triggered for this contact point.
	{
		ContactPointInfo& info = m_contactInfos.expandOne();
		new (&info) ContactPointInfo();
		HK_ASSERT2(0xad7853aa, m_contactInfos.getSize() == m_uniqueIdCounter, "Unique ID is not in synch with m_contactInfos array.");
		info.m_type = event.isToi() ? ContactPointInfo::TOI : ContactPointInfo::PSI;
		info.m_added = true;
		info.m_key = int(shapeKey);
	}

	// By setting the  ProcessContactCallbackDelay to 0 we will receive callbacks for 
	// any collisions processed for this body every frame (simulation step), i.e. the delay between
	// any such callbacks is 0 frames.

	// If you wish to only be notified every N frames simply set the delay to be N-1.
	// The default is 65536, i.e. (for practical purpose) once for the first collision only, until
	// the bodies separate to outside the collision tolerance. 
	event.m_callbackFiredFrom->setProcessContactCallbackDelay(0);
}