This tutorial intends to make the chase camera a little more intelligent. You can stand with a back to the wall and the camera will
zoom nearer. You can stand on top of something and look down while the camera changes to some kind of first person perspective.
! It is based on the first chase camera tutorial and assumes you have made the changes notified in it !

The changes all take place again in Client.c in Function BuildClientViewXForm

static void BuildClientViewXForm(Client_Client *Client)
{
    float xtrans;
    float ztrans;
 
    geVec3d              Pos;
    GPlayer              *Player;

    float Ydistance,distance; //Distance between Actor and camera

    GE_Collision Collision;
    geVec3d   Front, Back, In, Help;
    geVec3d   Mins = {-1.0f, -1.0f, -1.0f};
    geVec3d   Maxs = { 1.0f,  1.0f,   1.0f};

 

    assert(Client->ViewPlayer >= 0 && Client->ViewPlayer < HOST_MAX_PLAYERS);
 
    Player = &Client->Players[Client->ViewPlayer];

    Client->ViewXForm = Player->XForm;

    if (Client->Host->Demo.Mode != HOST_DEMO_PLAY && !(Player->ViewFlags & VIEW_TYPE_FORCE_XFORM))
    {
        Pos = Client->ViewXForm.Translation;
 
        geXForm3d_GetIn(&Client->ViewXForm, &In);

        //Send ray to examine if player is looking up or down by determining the height difference
        //(300.0f = max camera distance)
        geVec3d_AddScaled(&Pos, &In, -1000.0f, &Help);
        Ydistance=300.0f-(float)fabs(Pos.Y-Help.Y);

        //Start sending ray 20.0f from behind Actor, or it will collide with the Actor self
        geVec3d_AddScaled(&Pos, &In, -20.0f, &Front);

        //Start sending ray in View-Height
        Front.Y = Front.Y +180.0f;
        Back.Y = Back.Y +180.0f;

        //Look 10000.0f behind
        geVec3d_AddScaled(&Front, &In, -100000.0f, &Back);

       //if backward ray collides with wall decrease camera distance
        if (geWorld_Collision(Client->Host->World, NULL, NULL, &Front, &Back, GE_COLLIDE_ALL, 0xffffffff, &Collision))
        {
        //Get Distance behind Actor and Wall
        distance=(float)fabs(geVec3d_DistanceBetween(&Collision.Impact,&Front));
        //Minimum between looking up/down and Wall behind
        distance=min(distance,Ydistance);
        //distance ranges:
        if (distance<1.0f) distance=-20.0f;
        if (distance>300.0f) distance=300.0f;
        }

 

        // Clear the matrix
        geXForm3d_SetIdentity(&Client->ViewXForm);

        // Rotate then translate.
        geXForm3d_RotateZ(&Client->ViewXForm, Client->Angles.Z);

        geXForm3d_RotateX(&Client->ViewXForm, Client->Angles.X);
        geXForm3d_RotateY(&Client->ViewXForm, Client->Angles.Y);

        //changed to variable camera distance
        xtrans = (float) (sin(Client->Angles.Y)*distance);
        ztrans = (float) (cos(Client->Angles.Y)*distance);

        geXForm3d_Translate(&Client->ViewXForm, Pos.X, Pos.Y, Pos.Z);
    }

    // HACK the view height till we get it in
    // Just use a vakue that looks good for now...
    // Set the viewheight from 140 to 180 else her big head will be in the way ;-)
    Client->ViewXForm.Translation.Y += 180.0f;
    Client->ViewXForm.Translation.X += xtrans;
    Client->ViewXForm.Translation.Z += ztrans;
}
 
This chase camera is quite away from being perfect (especially in the complex demo level) but it gives some nice effects.
Problems to solve are:
- Clipping problems when jumping in rooms with low ceiling.
- perhaps too fast changes of the camera view
- aiming crosshair has become false (since we changed view height i guess, must be easy to correct ...)

Send comments and suggestions to Mark or to the Forum at Genesis3D

Greetings,
Mark Müller