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(); } } }