// // Handle the changing state of collision between one entity and any colshape // void CClientColManager::DoHitDetectionForEntity ( const CVector& vecNowPosition, float fRadius, CClientEntity* pEntity ) { std::map < CClientColShape*, int > shortList; // Get all entities within the sphere CClientEntityResult queryResult; GetClientSpatialDatabase()->SphereQuery ( queryResult, CSphere ( vecNowPosition, fRadius ) ); // Extract colshapes for ( CClientEntityResult ::const_iterator it = queryResult.begin () ; it != queryResult.end (); ++it ) if ( (*it)->GetType () == CCLIENTCOLSHAPE ) shortList[ (CClientColShape*)*it ] = 1; // Add existing collisions, so they can be disconnected if required for ( list < CClientColShape* > ::const_iterator it = pEntity->CollisionsBegin () ; it != pEntity->CollisionsEnd (); ++it ) shortList[ *it ] = 1; // Test each colshape against the entity for ( std::map < CClientColShape*, int > ::const_iterator it = shortList.begin () ; it != shortList.end (); ++it ) { CClientColShape* pShape = it->first; // Enabled and not being deleted? if ( !pShape->IsBeingDeleted () && pShape->IsEnabled () ) { // Collided? bool bHit = pShape->DoHitDetection ( vecNowPosition, fRadius ); HandleHitDetectionResult ( bHit, pShape, pEntity ); } } }
/////////////////////////////////////////////////////////////// // // CClientModelCacheManagerImpl::DoPulseVehicleModels // // Pulse caching system for vehicle models // /////////////////////////////////////////////////////////////// void CClientModelCacheManagerImpl::DoPulseVehicleModels(void) { // Scale up query radius to compensate for the camera speed and possible vehicle speeds float fVehicleQueryRadius = VEHICLE_STREAM_IN_DISTANCE + STREAMER_STREAM_OUT_EXTRA_DISTANCE + m_fSmoothCameraSpeed * 2 + VEHICLE_MAX_VELOCITY * 2; // Get all entities within range CClientEntityResult result; GetClientSpatialDatabase()->SphereQuery(result, CSphere(m_vecCameraPos, fVehicleQueryRadius)); std::vector<CClientVehicle*> vehicleList; // For each entity found for (CClientEntityResult::const_iterator iter = result.begin(); iter != result.end(); ++iter) { switch ((*iter)->GetType()) { case CCLIENTVEHICLE: vehicleList.push_back((CClientVehicle*)*iter); break; } } // Compile a list of vehicle models which should be cached std::map<ushort, float> newNeedCacheList; ProcessVehicleList(newNeedCacheList, vehicleList, Square(VEHICLE_STREAM_IN_DISTANCE + STREAMER_STREAM_OUT_EXTRA_DISTANCE + m_fSmoothCameraSpeed * 2)); // Apply desired caching m_pCoreModelCacheManager->UpdateVehicleModelCaching(newNeedCacheList); }
/////////////////////////////////////////////////////////////// // // CClientSpatialDatabaseImpl::AllQuery // // Return the list of all entities // /////////////////////////////////////////////////////////////// void CClientSpatialDatabaseImpl::AllQuery ( CClientEntityResult& outResult ) { // Do any pending updates first FlushUpdateQueue (); // Copy results from map to output outResult.clear (); for ( std::map < CClientEntity*, SEntityInfo >::iterator it = m_InfoMap.begin (); it != m_InfoMap.end (); ++it ) outResult.push_back ( it->first ); }
// // Handle the changing state of collision between one colshape and any entity // void CClientColManager::DoHitDetectionForColShape ( CClientColShape* pShape ) { // Ensure colshape is enabled and not being deleted if ( pShape->IsBeingDeleted () || !pShape->IsEnabled () ) return; std::map < CClientEntity*, int > entityList; // Get all entities within the sphere CSphere querySphere = pShape->GetWorldBoundingSphere (); CClientEntityResult result; GetClientSpatialDatabase()->SphereQuery ( result, querySphere ); // Extract relevant types for ( CClientEntityResult::const_iterator it = result.begin () ; it != result.end (); ++it ) { CClientEntity* pEntity = *it; switch ( pEntity->GetType () ) { case CCLIENTRADARMARKER: case CCLIENTRADARAREA: case CCLIENTTEAM: case CCLIENTGUI: case CCLIENTCOLSHAPE: case CCLIENTDUMMY: case SCRIPTFILE: case CCLIENTDFF: case CCLIENTCOL: case CCLIENTTXD: case CCLIENTSOUND: break; default: if ( pEntity->GetParent () ) entityList[ pEntity ] = 1; } } // Add existing colliders, so they can be disconnected if required for ( CFastList < CClientEntity* > ::const_iterator it = pShape->CollidersBegin () ; it != pShape->CollidersEnd (); ++it ) { entityList[ *it ] = 1; } // Test each entity against the colshape for ( std::map < CClientEntity*, int > ::const_iterator it = entityList.begin () ; it != entityList.end (); ++it ) { CClientEntity* pEntity = it->first; CVector vecPosition; pEntity->GetPosition ( vecPosition ); // Collided? bool bHit = pShape->DoHitDetection ( vecPosition, 0.0f ); HandleHitDetectionResult ( bHit, pShape, pEntity ); } }
// // Distance streaming like what is done with visible objects // void CClientSoundManager::UpdateDistanceStreaming ( const CVector& vecListenerPosition ) { // // Make a copy of the current list of sounds that are active // std::set < CClientSound* > considerMap = m_DistanceStreamedInMap; // // Mix in all sounds near enough to the listener to be heard // { // Find all entities overlapping the listener position CClientEntityResult result; GetClientSpatialDatabase()->SphereQuery ( result, CSphere( vecListenerPosition, 0 ) ); // Extract relevant types for ( CClientEntityResult::const_iterator iter = result.begin () ; iter != result.end (); ++iter ) { if ( CClientSound* pSound = DynamicCast < CClientSound > ( *iter ) ) { if ( pSound->IsSound3D() ) { // Add to consider map considerMap.insert ( pSound ); } } } } // // Step through each sound // If the sound is more than 40 units away (or in another dimension), make sure it is deactivated // If the sound is less than 20 units away, make sure it is activated // for ( std::set < CClientSound* >::iterator iter = considerMap.begin () ; iter != considerMap.end () ; ++iter ) { CClientSound* pSound = *iter; // Calculate distance to the edge of the sphere CSphere sphere = pSound->GetWorldBoundingSphere (); float fDistance = ( vecListenerPosition - sphere.vecPosition ).Length () - sphere.fRadius; if ( fDistance > 40 || m_usDimension != pSound->GetDimension () ) pSound->DistanceStreamOut (); else if ( fDistance < 20 ) pSound->DistanceStreamIn (); } }
/////////////////////////////////////////////////////////////// // // CClientSpatialDatabaseImpl::SphereQuery // // Return the list of entities that intersect the sphere // /////////////////////////////////////////////////////////////// void CClientSpatialDatabaseImpl::SphereQuery ( CClientEntityResult& outResult, const CSphere& sphere ) { // Do any pending updates first FlushUpdateQueue (); if ( !IsValidSphere ( sphere ) ) return; // Make a box from the sphere CBox box ( sphere.vecPosition, fabsf ( sphere.fRadius ) ); // Make everything 2D for now box.vecMin.fZ = SPATIAL_2D_Z; box.vecMax.fZ = SPATIAL_2D_Z; // Find all entiites which overlap the box m_Tree.Search( &box.vecMin.fX, &box.vecMax.fX, outResult ); #ifdef SPATIAL_DATABASE_DEBUG_OUTPUTA OutputDebugLine ( SString ( "SpatialDatabase::SphereQuery %d results for %2.0f,%2.0f,%2.0f %2.2f" ,outResult.size () ,sphere.vecPosition.fX ,sphere.vecPosition.fY ,sphere.vecPosition.fZ ,sphere.fRadius ) ); #endif }
bool CClientObjectManager::ObjectsAroundPointLoaded ( const CVector& vecPosition, float fRadius, unsigned short usDimension, SString* pstrStatus ) { // Get list of objects that may be intersecting the sphere CClientEntityResult result; GetClientSpatialDatabase()->SphereQuery ( result, CSphere ( vecPosition, fRadius ) ); bool bResult = true; // Extract relevant types for ( CClientEntityResult::const_iterator it = result.begin () ; it != result.end (); ++it ) { CClientEntity* pEntity = *it; if ( pEntity->GetType () == CCLIENTOBJECT ) { CClientObject* pObject = static_cast < CClientObject* > ( pEntity ); if ( !pObject->GetGameObject () || !pObject->GetModelInfo ()->IsLoaded () || !pObject->IsStreamedIn () ) { if ( pObject->GetDimension () == usDimension ) { // Final distance check float fDistSquared = pObject->GetDistanceToBoundingBoxSquared ( vecPosition ); if ( fDistSquared < fRadius * fRadius ) bResult = false; if ( pstrStatus ) { // Debugging information *pstrStatus += SString ( "ID:%05d Dist:%4.1f GetGameObject:%d IsLoaded:%d IsStreamedIn:%d\n" ,pObject->GetModel () ,sqrtf ( fDistSquared ) ,pObject->GetGameObject () ? 1 : 0 ,pObject->GetModelInfo ()->IsLoaded () ? 1 : 0 ,pObject->IsStreamedIn () ? 1 : 0 ); } else if ( !bResult ) break; } } } } return bResult; }