Raised This Month: $51 Target: $400
 12% 

FOV and Vector tutorial


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
LinLinLin
Senior Member
Join Date: Sep 2021
Old 05-01-2023 , 13:14   FOV and Vector tutorial
Reply With Quote #1

Introduction:

This is an example to explain what is FOV in game, and how can we use FOV to do someting.


Start:
  • Vector

    To explain what is FOV, we need to understand what is position and vector at first.
    Recommanded to read this page https://forums.alliedmods.net/showthread.php?t=91474
    it has explained position and vector in detail.

    Simply, you can image that there are two points in our life a(x,y,z), b(x1,y1,z1), and then let x1 -x, y1 -y, z1 -z, and use there result to make a new objec C(x2, y2, z2), then C is a vector from a to b.it's length is equal to the distance between point a and point b.All ot them is float[3]

    Click image for larger version

Name:	vector.png
Views:	56
Size:	20.1 KB
ID:	200447
  • FOV

    Now think that player is stand and his eyes is in the origin of coordinates, and eye sight is going to right. In this case we can draw his screen and FOV.

    Click image for larger version

Name:	fov.png
Views:	50
Size:	22.7 KB
ID:	200448

    Actually, FOV is a degree that tell the Horizontal+ Angular Field of View of player. In image it is θ the degree of that player can see in horizontal. If you are good at "space rectangular coordinate system", it is very clear to understand it.


How to use
  • If you want to know that player can see an entity or not, FOV can help you do this more efficiency than Trace.Here is old code to check this situation.
    Github
    PHP Code:
    stock bool PointWithinViewAngle(const float vecSrcPosition[3], const float vecTargetPosition[3],
            const 
    float vecLookDirection[3], float flCosHalfFOV) {
        
    float vecDelta[3];
        
        
    SubtractVectors(vecTargetPositionvecSrcPositionvecDelta);
        
        
    float cosDiff GetVectorDotProduct(vecLookDirectionvecDelta);
        
        if (
    cosDiff 0.0) {
            return 
    false;
        }
        
        
    float flLen2 GetVectorLength(vecDeltatrue);
        
        
    // a/sqrt(b) > c  == a^2 > b * c ^2
        
    return ( cosDiff cosDiff >= flLen2 flCosHalfFOV flCosHalfFOV );
    }
    /**
     * Calculates the width of the forward view cone as a dot product result from the given angle.
     * This manually calculates the value of CBaseCombatCharacter's `m_flFieldOfView` data property.
     *
     * For reference: https://github.com/ValveSoftware/source-sdk-2013/blob/master/sp/src/game/server/hl2/npc_bullseye.cpp#L151
     *
     * @param angle     The FOV value in degree
     * @return          Width of the forward view cone as a dot product result
     */
    float GetFOVDotProduct(float angle) {
        return 
    Cosine(DegToRad(angle) / 2.0);

  • It looks very difficult to understand what each function do,( i spend two hours to know what he done...) especially the return.( Why compare those var and what they are? )
    So i rewrite this code and make it easily to read.

    PHP Code:
    bool IsInClientView(int entityint client)
    {
        
    float ent_pos[3],player_pos[3],player_ang[3];
        
    float eye2ent_vector[3];
        
    float eye2fwd_vector[3];
        
    char temp[16];
        
    GetClientInfo(client"fov_desired"tempsizeof(temp));
        
    int fov StringToInt(temp);

        
    GetClientEyePosition(client,player_pos);
        
    GetEntPropVector(entity,Prop_Data,"m_vecOrigin",ent_pos);
        
    MakeVectorFromPoints(player_pos,ent_pos,eye2ent_vector);

        
    GetClientEyeAngles(client,player_ang);
        
    GetAngleVectors(player_ang,eye2fwd_vector,NULL_VECTOR,NULL_VECTOR);

        
    NormalizeVector(eye2ent_vectoreye2ent_vector);
        
    NormalizeVector(eye2fwd_vectoreye2fwd_vector);

        
    float radian ArcCosineGetVectorDotProduct(eye2ent_vectoreye2fwd_vector) );
        
    /**
         * let me explain how this degree radian.
         * 
         * DotProduct = |a||b|cosθ, this is the vector theorem.
         * we have normalize the vector so |a| = |b| = 1.
         * in this case DotProduct = cosθ.
         * ArcCosine() let us get the radian of θ.
         * FOV is a degree, we need make it become radian.
         */
        
    return radian <= DegToRad(fov 0.0) / 2;

  • Let me explain it by img.

    Click image for larger version

Name:	entity.png
Views:	53
Size:	28.8 KB
ID:	200449

    [1] Get the eye sight vector by eye angle.[the sky blue line in img]
    (note that eye angle is not equal to the vector)

    [2] Get ehe eye to ent vector by eye position and entity position.[the brown line in img]

    [3] Use DotProduct to get the δ degree between this two vector.

    [4] FOV is a degree , change it to radian.

    [5] Compare δ with FOV / 2, if bigger than FOV / 2, it is out of the screen.
  • So what is the diffierent betweent old code and new code?

    Actually, both of them are the same in getting the vector of eye sight and eye 2 ent.One difference comes when new code start normalize the vector.
    In fact, DotProduct = |a||b|cosθ, this is the vector theorem. if we have normalize the vector, |a| will be equal to |b| and equal to 1, since vector now becomes substrate vector.
    Now it is easy to get the value of cosθ, use ArcCosine so we get the θ in radian. The scond different comes when function in return. We already get the θ, so all we need is compare this radian with FOV in radian and since player sight is always in the middle of the screen, FOV degree need to divide 2.
    If θ is smaller than FOV / 2, it is in player view and return true, false otherwise.

  • Code Compare
    Click image for larger version

Name:	FOV3.png
Views:	41
Size:	24.4 KB
ID:	200490
    [1] There are the same before normalize the vector. Old code don't normalize this vector, so it's value is not the same as cosθ, it is just a float value. Only one thing can be confirm is that if this value is less than 0, it means θ is larger than 90°, so it is impossible to show in player screen.

    [2] Second, old code get the lenght of eye 2 ent vector. Know that the value is square.

    [3] Now comes to return, what is dotproduct * dot product? We don't need to know what it is in image, just use his function : |a||b|cosθ * |a||b|cosθ = |a|⑵|b|⑵cos⑵θ.

    [4] Now return is clear. Old code compare |a|⑵|b|⑵cos⑵θ >= |b|⑵ * cos⑵(FOV / 2)

    [5] Since eye sight vector is made by angle, it is length is 1. Return now can now can be equal to cos⑵θ >=cos⑵(FOV / 2).

    [6] This is the cosine value image. You can see that when angle is zero, the value comes the biggest.
    which mean that if ent is in player sight, θ should less than FOV / 2, and it is cosine value is larger than FOV / 2.

    That is what old code do.

Problem:
  1. Because FOV of player is just the horizontal angle of player screen. It is not the same as bot and player screen is rectangle so it will cause a problem that the area size FOV draw is over the screen in vertical as the image show. And in the four angle of player screen , it is not include in the area since it is angle is larger than FOV / 2.
    Click image for larger version

Name:	BOT FOV.png
Views:	41
Size:	22.3 KB
ID:	200488Click image for larger version

Name:	TRUEFOV.png
Views:	46
Size:	23.5 KB
ID:	200489
  2. FOV can also get the ent that behind wall. since this function only check this in math, not include the game entity. Trace is still need if you want a more correctly check.

Last edited by LinLinLin; 05-03-2023 at 18:36.
LinLinLin is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 15:55.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode