void PhysicsContactSoundManager::physicsContact(const PhysicsContact &contact)
	{
		// WARNING: unsafe IGamePhysicsObject -> AbstractPhysicsObject casts!
		AbstractPhysicsObject *o1 = (AbstractPhysicsObject *)contact.obj1;
		AbstractPhysicsObject *o2 = (AbstractPhysicsObject *)contact.obj2;
		//assert(o1 != NULL);
		//assert(o2 != NULL);
		assert(contact.physicsObject1);
		assert(contact.physicsObject2);

#ifdef PHYSICS_PHYSX
		int sm1 = contact.physicsObject1->getIntData();
		int sm2 = contact.physicsObject2->getIntData();

		// int claw_material = impl->soundmp->getMaterialIndexByName( "claw" );
		// int claw_body_material = impl->soundmp->getMaterialIndexByName( "claw_body" );

		if(sm1 == SOUNDMATERIALPARSER_NO_SOUND_INDEX || sm2 == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#else
		if (o1->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX
			|| o2->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#endif

		const util::SoundMaterialParser::SoundMaterialList &smlist = impl->soundmp->getSoundMaterials();
		for (int i = 0; i < 2; i++)
		{
			AbstractPhysicsObject *o = o1;
			if (i == 1) 
			{
				o = o2;
			}
#ifdef PHYSICS_PHYSX
			int smindex = sm1;
			if (i == 1) 
			{
				smindex = sm2;
			}
			assert(smindex >= 0 && smindex < (int)smlist.size());
#else
			int smindex = o->getSoundMaterial();
#endif

			bool makeSound = false;
			VC3 soundpos;

			if(o)
			{
				/*
				// debug logging
				if( contact.contactForceLen > 1.0f && smlist[smindex].sounds.empty() == false )
				{
					VC3 accel = o->getAcceleration();
					VC3 angaccel = o->getAngularAcceleration();

					std::stringstream ss;
					ss << contact.contactForceLen << ", " << accel.GetLength() << ", " << angaccel.GetLength() << std::endl;
					Logger::getInstance()->error( ss.str().c_str() );
				}
				*/

				if(contact.contactForceLen >= smlist[smindex].requiredForce)
				{
					// TODO: use contact position instead of object's position.
					soundpos = o->getPosition();

					VC3 accel = o->getAcceleration();
					VC3 angaccel = o->getAngularAcceleration();

					

					

					if (accel.GetSquareLength() >= smlist[smindex].requiredAcceleration * smlist[smindex].requiredAcceleration
						|| angaccel.GetSquareLength() >= smlist[smindex].requiredAngularAcceleration * smlist[smindex].requiredAngularAcceleration)
					{
						makeSound = true;

						/*
						std::vector<std::string> soundlist = smlist[smindex].sounds;
						if (soundlist.size() > 0)
						{
							// TODO: some better pseudo-random logic here maybe...
							int sndnum = rand() % soundlist.size();
							const char *soundfile = soundlist[sndnum].c_str();

							float volumeFactor = 1.0f;
							if (smlist[smindex].requiredForce > 0.0f)
							{
								// 40% - 100% volume factor (100% required force - 200% required force)
								volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f;
								volumeFactor *= 0.6f;
								volumeFactor += 0.4f;
								if (volumeFactor > 1.0f)
									volumeFactor = 1.0f;

								assert(volumeFactor >= 0.4f);
								assert(volumeFactor <= 1.0f);
							}

							impl->gameUI->playSoundEffect(soundfile, soundpos.x, soundpos.y, soundpos.z, 
								false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL);
						}
						*/
					}

				}

				// not to repeat the effect too frequently
				if( o != NULL && makeSound && ( impl->gameUI->game->gameTimer - o->getLastEffectSoundTick() ) > ( 200 / GAME_TICK_MSEC ) )
				{
					o->setLastEffectSoundTick( impl->gameUI->game->gameTimer ); 
				}
				else
				{
					makeSound = false;
				}
			}
			else
			{
				if(contact.contactForceLen >= smlist[smindex].requiredForce)
				{
					makeSound = true;

#ifdef PHYSICS_PHYSX
					if(i == 0)
						contact.physicsObject1->getPosition(soundpos);
					else
						contact.physicsObject2->getPosition(soundpos);
#endif
				}
			}

			if(makeSound)
			{
				std::vector<std::string> soundlist = smlist[smindex].sounds;
				if (soundlist.size() > 0)
				{
					// TODO: some better pseudo-random logic here maybe...
					int sndnum = rand() % soundlist.size();
					// const char *soundfile = soundlist[sndnum].c_str();
					
					float volumeFactor = 1.0f;
					std::string soundfile = soundlist[sndnum];

					if (smlist[smindex].requiredForce > 0.0f)
					{
						// 100% required force - 500% required force
						float contactFactor = contact.contactForceLen / ( smlist[smindex].requiredForce * 5.0f );
						if( contactFactor > 1.0f ) 
							contactFactor = 1.0f;

						int sndnum = (int)((float)( soundlist.size() - 1 ) * contactFactor + 0.5f);
						sndnum += ( rand() % 3 ) - 1;

						if( sndnum < 0 ) 
							sndnum = 0;
						
						if( sndnum > (signed)( soundlist.size() - 1 ) ) 
							sndnum = (signed)( soundlist.size() - 1 );
						
						soundfile = soundlist[sndnum];
						/*
						// 40% - 100% volume factor (100% required force - 200% required force)
						volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f;
						volumeFactor *= 0.6f;
						volumeFactor += 0.4f;
						if (volumeFactor > 1.0f)
							volumeFactor = 1.0f;

						assert(volumeFactor >= 0.4f);
						assert(volumeFactor <= 1.0f);
						*/
					}

					impl->gameUI->playSoundEffect(soundfile.c_str(), soundpos.x, soundpos.y, soundpos.z, 
						false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL);
				}
			}
		}
	}