void MyCollisionListener::contactPointAddedCallback(	hkpContactPointAddedEvent& event )
{
	//
	// draw the contact point as a little red star
	//
	{
		const hkVector4& start = event.m_contactPoint->getPosition();
		for ( int i = 0; i < 20; i++ )
		{
			hkVector4 dir( hkMath::sin( i * 1.0f ), hkMath::cos( i * 1.0f ), hkMath::sin(i * 5.0f ) );
			dir.setMul4(0.3f, dir);
			hkVector4 end;		end.setAdd4(start, dir);
			HK_DISPLAY_LINE(start, end, hkColor::RED);
		}
	}

	//
	//	collect all information in our own data structure
	//  as the havok memory manager is really really fast,
	//  allocating lots of small structures is acceptable
	//
	if ( event.m_contactPointProperties->getUserData() == HK_NULL )
	{
		ContactPointInfo* info = new ContactPointInfo;
		info->m_uniqueId = m_uniqueIdCounter++;
		event.m_contactPointProperties->setUserData( reinterpret_cast<hkUlong>(info) );

		//
		//	printf some information 
		//
		if (m_reportLevel >= hkDemoEnvironment::REPORT_INFO)
		{
			if ( event.isToi() )
			{
 				hkprintf("Toi userId=%i created\n", info->m_uniqueId );
			}
			else
			{
				int cpId = event.asManifoldEvent().m_contactPointId;
				hkprintf("Contact Point userId=%i created: contactId=%i\n", info->m_uniqueId, cpId );
			}
		}
	}

	// 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);
}
Example #2
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);
}