void CPhysicsSpring::AttachListener() { if ( !(m_pObjStart->GetCallbackFlags() & CALLBACK_NEVER_DELETED) ) { m_pObjStart->GetObject()->add_listener_object( this ); } if ( !(m_pObjEnd->GetCallbackFlags() & CALLBACK_NEVER_DELETED) ) { m_pObjEnd->GetObject()->add_listener_object( this ); } }
bool CPlayerController::IsInContact() { CPhysicsEnvironment *pEnv = m_pObject->GetVPhysicsEnvironment(); int numManifolds = pEnv->GetBulletEnvironment()->getDispatcher()->getNumManifolds(); for (int i = 0; i < numManifolds; i++) { btPersistentManifold *contactManifold = pEnv->GetBulletEnvironment()->getDispatcher()->getManifoldByIndexInternal(i); const btCollisionObject *obA = contactManifold->getBody0(); const btCollisionObject *obB = contactManifold->getBody1(); CPhysicsObject *pPhysUs = NULL; CPhysicsObject *pPhysOther = NULL; if (contactManifold->getNumContacts() > 0 && (obA == m_pObject->GetObject() || obB == m_pObject->GetObject())) { if (obA == m_pObject->GetObject()) { pPhysUs = (CPhysicsObject *)obA->getUserPointer(); pPhysOther = (CPhysicsObject *)obB->getUserPointer(); } else if (obB == m_pObject->GetObject()) { pPhysUs = (CPhysicsObject *)obB->getUserPointer(); pPhysOther = (CPhysicsObject *)obA->getUserPointer(); } if (pPhysOther->IsStatic() || !pPhysOther->IsMotionEnabled() || (pPhysOther->GetCallbackFlags() & CALLBACK_SHADOW_COLLISION)) continue; return true; } } return false; }
void CPhysicsSpring::DetachListener() { if ( !(m_pObjStart->GetCallbackFlags() & CALLBACK_NEVER_DELETED) ) { m_pObjStart->GetObject()->remove_listener_object( this ); } if ( !(m_pObjEnd->GetCallbackFlags() & CALLBACK_NEVER_DELETED) ) { m_pObjEnd->GetObject()->remove_listener_object( this ); } m_pObjStart = NULL; m_pObjEnd = NULL; m_pSpring = NULL; }
bool CPlayerController::IsInContact( void ) { IVP_Real_Object *pivp = m_pObject->GetObject(); if ( !pivp->flags.collision_detection_enabled ) return false; IVP_Synapse_Friction *pfriction = pivp->get_first_friction_synapse(); while ( pfriction ) { extern IVP_Real_Object *GetOppositeSynapseObject( IVP_Synapse_Friction *pfriction ); IVP_Real_Object *pobj = GetOppositeSynapseObject( pfriction ); if ( pobj->flags.collision_detection_enabled ) { // skip if this is a static object if ( !pobj->get_core()->physical_unmoveable && !pobj->get_core()->pinned ) { CPhysicsObject *pPhys = static_cast<CPhysicsObject *>(pobj->client_data); // skip if this is a shadow object // UNDONE: Is this a hack? need a better way to detect shadows? if ( !(pPhys->GetCallbackFlags() & CALLBACK_SHADOW_COLLISION) ) return true; } } pfriction = pfriction->get_next(); } return false; }
void Tick() { btDiscreteDynamicsWorld *pBulletEnv = m_pEnv->GetBulletEnvironment(); btCollisionObjectArray &colObjArray = pBulletEnv->getCollisionObjectArray(); for (int i = 0; i < colObjArray.size(); i++) { CPhysicsObject *pObj = (CPhysicsObject *)colObjArray[i]->getUserPointer(); if (!pObj) continue; // Internal object that the game doesn't need to know about Assert(*(char *)pObj != 0xDD); // Make sure the object isn't deleted (only works in debug builds) // Don't add objects marked for delete if (pObj->GetCallbackFlags() & CALLBACK_MARKED_FOR_DELETE) { continue; } if (colObjArray[i]->getActivationState() != pObj->GetLastActivationState()) { int newState = colObjArray[i]->getActivationState(); // Not a state we want to track. if (newState == WANTS_DEACTIVATION) continue; if (m_pObjEvents) { switch (newState) { // FIXME: Objects may call objectwake twice if they go from disable_deactivation -> active_tag case DISABLE_DEACTIVATION: case ACTIVE_TAG: m_pObjEvents->ObjectWake(pObj); break; case ISLAND_SLEEPING: // Don't call ObjectSleep on DISABLE_SIMULATION on purpose. m_pObjEvents->ObjectSleep(pObj); break; } } switch (newState) { case DISABLE_DEACTIVATION: case ACTIVE_TAG: // Don't add the object twice! if (m_activeObjects.Find(pObj) == -1) m_activeObjects.AddToTail(pObj); break; case DISABLE_SIMULATION: case ISLAND_SLEEPING: m_activeObjects.FindAndRemove(pObj); break; } pObj->SetLastActivationState(newState); } } }
virtual void core_left_volume( IVP_Controller_Phantom *controller, IVP_Core *pCore ) { CPhysicsFluidController *pFluid = static_cast<CPhysicsFluidController *>( controller->client_data ); IVP_Real_Object *pivp = pCore->objects.element_at(0); CPhysicsObject *pObject = static_cast<CPhysicsObject *>(pivp->client_data); if ( !pObject ) return; if ( pFluid ) { if ( pObject && (pObject->GetCallbackFlags() & CALLBACK_FLUID_TOUCH) ) { m_pCallback->FluidEndTouch( pObject, pFluid ); } } else { // must be a trigger IVP_Real_Object *pTriggerIVP = controller->get_object(); CPhysicsObject *pTrigger = static_cast<CPhysicsObject *>(pTriggerIVP->client_data); m_pCallback->ObjectLeaveTrigger( pTrigger, pObject ); } }
//----------------------------------------------------------------------------- // 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(); } } }