Thanks to Bill Ainsworth for contributing this great new tutorial:

Hello.  This tutorial builds on the overhead camera tutorial generously posted by Mr. J.C. Smith.  In this tutorial we will add the ability to zoom the camera in and out dynamically.

The first modification is to the file "client.h" at line 127.  You should see something like the following when you get there:

Server_Client  ServerClient;
int32    ClientPlayer;

float    NextSend;

GenVSI    GenVSI;

} Client_Client;

We need to add a variable to track the current camera position on what I'll call the "Y" axis.  Since the player could rotate, I'm not sure this nomenclature is accurate, but it should suffice for now. Add the following line:

float    CameraYPositionOffset; //Used for overhead zoom feature

so you end up with this:

Server_Client  ServerClient;
int32    ClientPlayer;

float    NextSend;

GenVSI    GenVSI;

float    CameraYPositionOffset; //Used for overhead zoom feature

} Client_Client;

--->

From here on out, all of the modifications are to the file "client.c". Now that we have our variable, we need to initialize it.  Go to line 103.  You should see the following:

NewClient->geClient = *geClient;

// The client was created
Console_Printf(Host->Console, "[CLIENT] Client Created...\n");

NewClient->CurrentItem = 0;

Buffer_Set(&SendBuffer, SData, 5000);

Client_SetupGenVSI(NewClient);

Client_Main(&NewClient->GenVSI);
Console_Printf(Host->Console, "Client_Create:  Client_Main
initialized...\n");

return NewClient;
}

Add the following line:
NewClient->CameraYPositionOffset = 800;     //Camera Y Pos default

You should end up with this:


NewClient->geClient = *geClient;

// The client was created
Console_Printf(Host->Console, "[CLIENT] Client Created...\n");

NewClient->CurrentItem = 0;

NewClient->CameraYPositionOffset = 800;     //Camera Y Pos default

Buffer_Set(&SendBuffer, SData, 5000);

Client_SetupGenVSI(NewClient);

Client_Main(&NewClient->GenVSI);
Console_Printf(Host->Console, "Client_Create:  Client_Main
initialized...\n");

return NewClient;
}

Now we need to add the code to read in the keystrokes that control the zoom level.  I have chosen the "7" key to be zoom in and the "8" key top be zoom out.  All we're really doing is adding to or decrementing from the CameraYPositionOffset and making sure we don't cross some sensible boundaries.

Go to line 554.  You should see some code like this:

else if (NewKeyDown(KeyLut[VK_CONTROL], Host->hWnd))
{
  Client->CurrentItem ++;
  Client->CurrentItem %= 4;
}

Client->ButtonBits = ButtonBits;

You want to modify it to look like this:

else if (NewKeyDown(KeyLut[VK_CONTROL], Host->hWnd))
{
  Client->CurrentItem ++;
  Client->CurrentItem %= 4;
}
else if (IsKeyDown('7', Host->hWnd))  // Zoom camera in
{
  Client->CameraYPositionOffset = Client->CameraYPositionOffset - 10.0f;

  if (Client->CameraYPositionOffset < 200.0) {
   Client->CameraYPositionOffset = 200.0f;
  }
}
else if (IsKeyDown('8', Host->hWnd)) // Zoom camera out
{
  Client->CameraYPositionOffset = Client->CameraYPositionOffset + 10.0f;

  if (Client->CameraYPositionOffset > 1000.0) {
   Client->CameraYPositionOffset = 1000.0f;
  }
}


Client->ButtonBits = ButtonBits;

Now all that remains is to plug in our new variable into the calculation of the camera view.  Goto line 1542.  You should see something like this:

  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...

Client->ViewXForm.Translation.Y += 800.0f;
//Client->ViewXForm.Translation.Y += 140.0f;
}

This is where the overhead tutorial added the fixed camera height.  Now that it is dynamic we merely need to reference the new variable like this:

  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...

Client->ViewXForm.Translation.Y += Client->CameraYPositionOffset;
//Zoom Level
//Client->ViewXForm.Translation.Y += 140.0f;
}

That does it!  This whole exercise only took about a half hour to write.  I encourage people to play around with the engine and gtest code.  Don't be intimidated, it's really very readable and well written code.

-Bill