void CShadowController::AttachObject( void )
{
	IVP_Real_Object *pivp = m_pObject->GetObject();
	IVP_Core *pCore = pivp->get_core();
	m_saveRot = pCore->rot_speed_damp_factor;
	m_savedRI = *pCore->get_rot_inertia();
	m_savedMass = pCore->get_mass();
	m_savedMaterialIndex = m_pObject->GetMaterialIndexInternal();
	
	m_pObject->SetMaterialIndex( MATERIAL_INDEX_SHADOW );

	pCore->rot_speed_damp_factor = IVP_U_Float_Point( 100, 100, 100 );

	if ( !m_allowPhysicsRotation )
	{
		IVP_U_Float_Point ri( 1e15f, 1e15f, 1e15f );
		pCore->set_rotation_inertia( &ri );
	}
	if ( !m_allowPhysicsMovement )
	{
		m_pObject->SetMass( 1e6f );
		//pCore->inv_rot_inertia.hesse_val = 0.0f;
		m_pObject->EnableGravity( false );
	}

	pCore->calc_calc();
	pivp->get_environment()->get_controller_manager()->add_controller_to_core( this, pCore );
	m_shadow.lastPosition.set_to_zero();
}
	//-----------------------------------------------------------------------------
	// Purpose: This walks the objects in the environment and generates friction events
	//			for any scraping that is occurring.
	//-----------------------------------------------------------------------------
	void ProcessActiveObjects( IVP_Environment *pEnvironment, IPhysicsCollisionEvent *pEvent )
	{
		// FIXME: Is this correct? Shouldn't it do next PSI - lastScrape?
		float nextTime = pEnvironment->get_old_time_of_last_PSI().get_time();
		float delta = nextTime - m_lastScrapeTime;

		// only process if we have done a PSI
		if ( delta < pEnvironment->get_delta_PSI_time() )
			return;

		float t = 1.0f;
		t /= delta;
		if ( t > 10.0f )
			t = 10.0f;

		m_lastScrapeTime = nextTime;

		// UNDONE: This only calls friciton for one object in each pair.
		// UNDONE: Split energy in half and call for both objects?
		// UNDONE: Don't split/call if one object is static (like the world)?
		for ( int i = 0; i < m_activeObjects.Count(); i++ )
		{
			CPhysicsObject *pObject = m_activeObjects[i];
			IVP_Real_Object *ivpObject = pObject->GetObject();
			
			// no friction callbacks for this object
			if ( ! (pObject->GetCallbackFlags() & CALLBACK_GLOBAL_FRICTION) )
				continue;

			// UNDONE: IVP_Synapse_Friction is supposed to be opaque.  Is there a better way
			// to implement this?  Using the friction listener is much more work for the CPU
			// and considers sleeping objects.
			IVP_Synapse_Friction *pfriction = ivpObject->get_first_friction_synapse();
			while ( pfriction )
			{
				IVP_Contact_Point *contact = pfriction->get_contact_point();
				IVP_Synapse_Friction *pOpposite = GetOppositeSynapse( pfriction );
				IVP_Real_Object *pobj = pOpposite->get_object();
				CPhysicsObject *pScrape = (CPhysicsObject *)pobj->client_data;

				// friction callbacks for this object?
				if ( pScrape->GetCallbackFlags() & CALLBACK_GLOBAL_FRICTION )
				{
					float energy = IVP_Contact_Point_API::get_eliminated_energy( contact );
					if ( energy ) 
					{
						IVP_Contact_Point_API::reset_eliminated_energy( contact );
						// scrape with an estimate for the energy per unit mass
						// This assumes that the game is interested in some measure of vibration
						// for sound effects.  This also assumes that more massive objects require
						// more energy to vibrate.
						energy = energy * t * ivpObject->get_core()->get_inv_mass();

						if ( energy > 0.05f )
						{
							int hitSurface = physprops->RemapIVPMaterialIndex( pOpposite->get_material_index() );
							CPhysicsFrictionData data(pfriction);
							pEvent->Friction( pObject, ConvertEnergyToHL(energy), pObject->GetMaterialIndexInternal(), hitSurface, &data );
						}
					}
				}
				pfriction = pfriction->get_next();
			}
		}
	}