void GenericContactProcess (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex)
{
	int isHightField;
	NewtonBody* body;
	NewtonCollision* collision;
	NewtonCollisionInfoRecord info;

	isHightField = 1;
	body = NewtonJointGetBody0 (contactJoint);
	collision = NewtonBodyGetCollision(body);
	NewtonCollisionGetInfo(collision, &info);
	if (info.m_collisionType != SERIALIZE_ID_HEIGHTFIELD) {
		body = NewtonJointGetBody1 (contactJoint);
		collision = NewtonBodyGetCollision(body);
		NewtonCollisionGetInfo(collision, &info);
		isHightField  = (info.m_collisionType == SERIALIZE_ID_HEIGHTFIELD); 
	}

	#define HOLE_IN_TERRAIN 10
	if (isHightField) {
		void* nextContact;
		for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = nextContact) {
			int faceID;
			NewtonMaterial* material;

			nextContact = NewtonContactJointGetNextContact (contactJoint, contact);

			material = NewtonContactGetMaterial (contact);
			faceID = NewtonMaterialGetContactFaceAttribute (material);
			if (faceID == HOLE_INTERRAIN) {
				NewtonContactJointRemoveContact (contactJoint, contact); 
			}
		}
	}
}
	void PhysWorld3D::ProcessContact(const NewtonJoint* const contactJoint, float timestep, int threadIndex)
	{
		RigidBody3D* bodyA = static_cast<RigidBody3D*>(NewtonBodyGetUserData(NewtonJointGetBody0(contactJoint)));
		RigidBody3D* bodyB = static_cast<RigidBody3D*>(NewtonBodyGetUserData(NewtonJointGetBody1(contactJoint)));
		assert(bodyA && bodyB);

		using ContactJoint = void*;

		// Query all joints first, to prevent removing a joint from the list while iterating on it
		StackVector<ContactJoint> contacts = NazaraStackVector(ContactJoint, NewtonContactJointGetContactCount(contactJoint));
		for (ContactJoint contact = NewtonContactJointGetFirstContact(contactJoint); contact; contact = NewtonContactJointGetNextContact(contactJoint, contact))
			contacts.push_back(contact);

		for (ContactJoint contact : contacts)
		{
			NewtonMaterial* material = NewtonContactGetMaterial(contact);
			Callback* callbackData = static_cast<Callback*>(NewtonMaterialGetMaterialPairUserData(material));
			assert(callbackData);
			assert(callbackData->collisionCallback);

			if (!callbackData->collisionCallback(*bodyA, *bodyB))
				NewtonContactJointRemoveContact(contactJoint, contact);
		}
	}
		void ApplyTracktionForce (dFloat timestep, const NewtonBody* track)
		{
			dVector veloc;
			dVector omega;
			dMatrix matrix;

			NewtonBodyGetOmega(m_body0, &omega[0]);
			NewtonBodyGetVelocity(m_body0, &veloc[0]);
			NewtonBodyGetMatrix (m_body0, &matrix[0][0]);
			

			// itetate over the contact list and condition each contact direction anc contact acclerations
			for (NewtonJoint* contactJoint = NewtonBodyGetFirstContactJoint (track); contactJoint; contactJoint = NewtonBodyGetNextContactJoint (track, contactJoint)) {
				_ASSERTE ((NewtonJointGetBody0 (contactJoint) == track) || (NewtonJointGetBody1 (contactJoint) == track));

				#ifdef REMOVE_REDUNDAT_CONTACT	
				int contactCount;
				contactCount = NewtonContactJointGetContactCount(contactJoint);
				if (contactCount > 2) {
					// project the contact to the bounday of the conve hull o fteh trhread foot ptint 
					dFloat maxDist;
					dFloat minDist;
					void* minContact;
					void* maxContact;
					
					dMatrix matrix;
			
					minContact = NULL;
				    maxContact = NULL;
					NewtonBodyGetMatrix (track, &matrix[0][0]);

					maxDist = -1.0e10f;
					minDist = -1.0e10f;
					//find the best two contacts and remove all others
					for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
						dFloat dist;
						dVector point;
						dVector normal;
						NewtonMaterial* material;

					    material = NewtonContactGetMaterial (contact);
						NewtonMaterialGetContactPositionAndNormal(material, &point[0], &normal[0]);
						
						dist = matrix.m_front % point;
						if (dist > maxDist) {
							maxDist = dist;
							maxContact = contact;
						} 
						if (-dist > minDist) {
							minDist = -dist;
							minContact = contact;
						}
						
					}

					// now delete all reduntact contacts
					void* nextContact;
					NewtonWorld* world;

					world = NewtonBodyGetWorld (track);
					NewtonWorldCriticalSectionLock(world);
					for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = nextContact) {
						nextContact = NewtonContactJointGetNextContact (contactJoint, contact);
						if (!((contact == minContact) || (contact == maxContact))) {
							NewtonContactJointRemoveContact (contactJoint, contact);
						}
					}
					NewtonWorldCriticalSectionUnlock(world);
				}

				#endif

			
				for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
					dFloat speed;
					dFloat accel;
					dVector point;
					dVector normal;
					dVector dir0;
					dVector dir1;
					NewtonMaterial* material;

				    material = NewtonContactGetMaterial (contact);
					NewtonMaterialContactRotateTangentDirections (material, &matrix.m_front[0]);
					NewtonMaterialGetContactPositionAndNormal(material, &point[0], &normal[0]);
					NewtonMaterialGetContactTangentDirections (material, &dir0[0], &dir1[0]);


					dVector posit (point - matrix.m_posit);
					veloc += omega * posit;
					speed = veloc % dir0;
				//	accel = m_accel - 0.1f * speed + (((posit % m_matrix.m_right) > 0.0f) ? m_turnAccel : - m_turnAccel);
					accel = m_veloc + (((posit % matrix.m_right) > 0.0f) ? m_turnVeloc : - m_turnVeloc);

					accel = (accel - speed) * 0.5f / timestep;

			//		NewtonMaterialSetContactStaticFrictionCoef (material, 1.0f, 0);
			//		NewtonMaterialSetContactKineticFrictionCoef (material, 1.0f, 0);
					NewtonMaterialSetContactFrictionCoef (material, 1.0f, 1.0f, 0);

			//		NewtonMaterialSetContactStaticFrictionCoef (material, 0.5f, 1);
			//		NewtonMaterialSetContactKineticFrictionCoef (material, 0.5f, 1);
					NewtonMaterialSetContactFrictionCoef (material, 0.5f, 0.5f, 1);
					
					NewtonMaterialSetContactTangentAcceleration (material, accel, 0);
				}

				// for debug purpose show the contact
				ShowJointContacts (contactJoint);
			}
		}
void dNewtonContactMaterial::RemoveContact(void* const contact) const
{
	NewtonContactJointRemoveContact((NewtonJoint*)m_materialHandle, contact);
}