//
// 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);
}
//
// 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 ();
    }
}
Beispiel #5
0
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;
}