Welcome, Guest! Login | Register

FOV and LOS Checks [Print this Article]
Posted by: Mazor
Date posted: May 13 2003
User Rating: N/A
Number of views: 5270
Number of comments: 0
Description: Checking line of sight and field of view
This tutorial is sort of a compilation of several tutorials I have foun regarding field of view and line of sight. These people (including myself) should be given credit where/when it is due: X-0ut, bigguy, and the Holy Wars team.

For starters, we need to declare the external variable which stores the client's view angles, so towards the top of the file entity.cpp find:
 CODE  

extern vec3_t v_origin;
int g_iAlive = 1;

Add the v_angles variable to the end of the extern list after v_origin so that same block of code will look like this:
 CODE  

extern vec3_t v_origin, v_angles;
int g_iAlive = 1;

Now that we have the client's view angles, lets add some functions!
Still in the same file (entity.cpp) after:
 CODE  

extern "C"
{
---[SNIP]---
    struct cl_entity_s DLLEXPORT *HUD_GetUserEntity( int index );
}

Put this code in:
 CODE  

// mazor @add

// mazor - this is holy wars' code, be sure to thank them
#define FOV_MIN_DISTANCE 100
static bool PlayerIsInFOV( struct cl_entity_s *ent )
{
    Vector up, right, forward;
    AngleVectors( v_angles, forward, right, up );
    float distance = ( ent->curstate.origin - v_origin ).Length();

    // nearby players are always in FOV
    if ( distance <= FOV_MIN_DISTANCE * 2 )
        return true;

    // if it's not in front, don't even bother
    Vector vecDir = ( ent->curstate.origin - v_origin ).Normalize( );
    if ( DotProduct ( vecDir, forward ) < 0 )
        return false;

    return true;
}
// Returns true if the given entity is in the current Field Of View
// It's not 100% accurate, and it can fail for large objects - but it's fine
// for our purposes (optimization).
static bool IsInFOV( struct cl_entity_s *ent )
{
    Vector forward, right, up;
    AngleVectors( v_angles, forward, right, up );
    float distance = ( ent->curstate.origin - v_origin ).Length();

    // nearby objects are always in FOV
    if ( distance <= FOV_MIN_DISTANCE )
        return true;

    // if it's not in front, don't even bother
    Vector vecDir = ( ent->curstate.origin - v_origin ).Normalize( );
    if ( DotProduct ( vecDir, forward ) < 0 )
        return false;

    // this code is partially lifted from somewhere else in HL's code
    float dot = fabs( DotProduct ( vecDir, right ) )
        + fabs( DotProduct ( vecDir, up ) ) * 0.5;
    // tweak for distance
    dot *= 1.0 + 0.2 * ( distance / 8192 );

    float arc = 1 - (gHUD.m_iFOV/360); // mazor - I'm not sure how accurate this is, but it seem to work fine
    if ( dot > arc )
        return false;

    return true;
}
// mazor - end holy wars' code

// mazor - this is bigguy's code, thank him dearly
static bool IsInLOS( struct cl_entity_s *pTarget )
{
    // we've got a 3rd person camera...
    Vector forward, up, vecLook, vecTarget;
    pmtrace_t   tr;
    AngleVectors(v_angles, forward, NULL, up);
    vecLook = v_origin;
    vecTarget = pTarget->origin;

    for (int i = 0; i < 6; i++)
    {
        vecTarget.x += gEngfuncs.pfnRandomFloat(pTarget->curstate.mins.x, pTarget->curstate.maxs.x);
        vecTarget.y += gEngfuncs.pfnRandomFloat(pTarget->curstate.mins.y, pTarget->curstate.maxs.y);
        vecTarget.z += gEngfuncs.pfnRandomFloat(pTarget->curstate.mins.z, pTarget->curstate.maxs.z);

        if (!pTarget->player) // ALWAYS ALWAYS draw the player if theyre in the FOV, regardless if we can trace to them
        {
            tr = *(gEngfuncs.PM_TraceLine( (float *)&vecLook, (float *)&vecTarget, 0, 2, -1 ));
            // PM_ParticleLine((float *)&vecLook, (float *)&vecTarget, 77, 1.0, 0.0 );

            if (tr.fraction < 1)
            {
                if (tr.ent)
                    return true; // assume we hit something we can see through
                else
                    continue;
            }
            else
                return true;
        }
        else
            return true;
        vecTarget = pTarget->origin; // reset target's origin
    }

    return false;
}
// mazor - end bigguy's code

// mazor end

That just defined all the functions we'll need to calculate if a player or entity is inside the client's FOV and LOS. Now we just need to make use of these functions, so find the function int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname ), still in entity.cpp, and put this block of code inside of it:
 CODE  

// mazor begin
    switch ( type )
    {
    case ET_NORMAL:
        if( ent->model->type == mod_brush || ent->model->type == mod_sprite ) // always render brush models and sprites
            break; // always draw brush models
        if( g_iUser1 == 0 ) // if we aren't spectator
        {
            if( !IsInLOS(ent) )
                return 0;
            if( !IsInFOV(ent) )
                return 0;
        }
        // mazor end
        break;
    case ET_PLAYER:
        if( g_iUser1 == 0 )
        {
            if( !PlayerIsInFOV(ent) )
                return 0;
        }
        break;
    case ET_BEAM:
    case ET_TEMPENTITY:
    case ET_FRAGMENTED:
    default:
        break;
    }
// mazor end


Please note that if you have any other special things you need to do to the entities, it might be a good idea to add them to this struct, but by default, it should work.



KNOWN ISSUE: When an entity is on the verge of being masked by a world brush, the LOS calculation will cause the entity to flicker very rapidly, hence why this SHOULD NOT be calculated on players!


Thats all, any questions, email me
-Cale 'Mazor' Dunlap
Firearms Half-Life

Rate This Article
This article has not yet been rated.

You have to register to rate this article.
User Comments

No User Comments

You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 05 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (16 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!