Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying C++ Game Animation Programming
  • Table Of Contents Toc
C++ Game Animation Programming

C++ Game Animation Programming - Second Edition

By : Michael Dunsky, Gabor Szauer
4.4 (12)
close
close
C++ Game Animation Programming

C++ Game Animation Programming

4.4 (12)
By: Michael Dunsky, Gabor Szauer

Overview of this book

If you‘re fascinated by the complexities of animating video game characters and are curious about the transformation of model files into 3D avatars and NPCs that can explore virtual worlds, then this book is for you. In this new edition, you’ll find expanded content on high-performance graphics and modern animation techniques, along with improved workflows and enhanced guidance on using OpenGL and Vulkan. You’ll learn everything you need to know about game animation, from a simple graphical window to a large crowd of smoothly animated characters. First, you’ll learn how to use modern high-performance graphics, dig into the details of how virtual characters are stored, and load the models and animations into a minimalistic game-like application. Then, you’ll get an overview of the components of an animation system, how to play the animations and combine them, and how to blend from one animation into another. You’ll also get an introduction to topics that will make your programming life easier, such as debugging your code or stripping down the graphical output. By the end of this book, you’ll have gained deep insights into all the parts of game animation programming and how they work together, revealing the magic that brings life to the virtual worlds on your screen.
Table of Contents (22 chapters)
close
close
1
Part 1:Building a Graphics Renderer
7
Part 2: Mathematics Roundup
10
Part 3: Working with Models and Animations
15
Part 4: Advancing Your Code to the Next Level

Event handling in GLFW

Many modern OSs are event-based – the programs don’t just sit there and ask the OS over and over if any mouse or keyboard input has occurred or if the window has been moved, minimized, or resized. All these events are stored in an event queue and must be handled by the application code. If you never request the events of that queue, your application window won’t even close in a proper manner, that is, it can only be killed using Task Manager.

You can find the example code for these additions in the 04_event_handling folder.

Let’s have a look at how GLFW handles the events from the OS.

The GLFW event queue handling

You have already seen a bit of the event handling in the code for the Window class – we used these two GLFW calls to close our window and end the application:

int glfwWindowShouldClose(GLFWwindow *win);
void glfwPollEvents();

The first call, glfwWindowShouldClose(), checks whether an application window should be closed. This event is generated after the user clicks on the top-right close icon of the window. We are using this as a condition to step out of our while() loop, end the mainLoop() method of the Window class, and start the cleanup process.

Important note

The call to glfwPollEvents() is required in order to empty the event queue. It will also run any configured callbacks. If you forget this call, your window will do nothing, not even close down.

You should call glfwPollEvents() at the end of the main loop to process the newly arrived events.

There is another call to clear the event queue and fire the callbacks:

void glfwWaitEvents();

This one puts the thread to sleep and waits until at least one event has been generated for the window. Usually, this is used in non-interactive applications that are waiting for any input from the user.

Mixing the C++ classes and the C callbacks

A simple starting point is to react to the window close request and just output a message to the user. To get this to work, we need two parts – the function called by GLFW and a call that sets the function as a callback.

This sounds easy to do, but only at first glance. As GLFW is pure C code, it has no knowledge about C++ classes, member functions, the this pointer, and all the other moving parts. However, there are some solutions to this.

The first way is that we could use a static function of our Window class as it is technically similar to a C function. At the moment, we won’t use more than one application window, but if we add support for a pop-out window later, we might be in trouble with the static class function. It is the same for all objects of that class, and as it can only access static members, you have to take extra steps to avoid even more trouble when starting with multithreaded code.

So, let’s consider the second way and use a “free” function, outside the class, to dispatch the call to the C++ class. However, instead of having to define two separate functions for every callback, we will use a Lambda.

Lambda functions

A lambda is a small piece of code, running as an anonymous function. It has no visible name, takes the number and types of arguments from its definition, and runs the code. Internally, the lambda function is converted into a small class by your compiler; there is no magic applied here. It’s only a convenient way to help reduce the code you write. If you want to know more about lambda functions, you can find a link to a tutorial in the Additional resources section.

The authors of GLFW are aware of this problem and have added a small helper to every window that might be created – a pointer that can be set and read by the user:

void glfwSetWindowUserPointer(GLFWwindow *win, void *ptr);

You can store any arbitrary data in the user pointer – it doesn’t have to be the this pointer of the class object, but it is only a pointer and must be accessible by your code. We will use it to store the pointer in our C++ Window object, and inside the lambda, this pointer will be read and used just like in any other C++ call.

The callback function itself looks a bit weird if you have never used C-style callbacks:

GLFWwindowclosefun glfwSetWindowCloseCallback (GLFWwindow *window, GLFWwindowclosefun callback);

It requires a pointer to a function and returns either NULL, if this is the first call, or the pointer to a previously set callback function. You could change this callback during runtime, which means moving to a different dialog to display any unsaved changes.

The last part of the puzzle is the window close function, which is called by the callback:

typedef void(* GLFWwindowclosefun) (GLFWwindow *window)

The GLFWwindowclosefun function is created using typedef, just like the other functions used for callbacks. This is done to avoid writing the expression in the second braces every time we use the function. As this is still C code, sadly, no modern C++ enhancements are available to change it.

And this is how you should put all the parts together – by adding the following lines to the init() function of the Window.cpp file:

  glfwSetWindowUserPointer(mWindow, this);
  glfwSetWindowCloseCallback(mWindow, [](GLFWwindow *win) {
    auto thisWindow = static_cast<Window*>(
      glfwGetWindowUserPointer(win));
    thisWindow->handleWindowCloseEvents();
  });

Here, the lambda is introduced by the square brackets, [], followed by the parameters the function takes. You could even capture some data from the outside of the function using the brackets, making it available, like in normal functions. We can’t use this capturing method for C-style callbacks, as such captures are not compatible with a function pointer.

Inside the lambda function, we can retrieve the user pointer set by glfwSetWindowUserPointer(), cast it back to a pointer to an instance of our Window class (this is our application window), and call the member function to handle the event. The function does not need to get the GLFWwindow parameter, as we already saved it as a private member in the Window class. The result of glfwSetWindowCloseCallback() can be safely ignored. It returns the address of the callback function that was set in a previous call. This is the first call in the code, so it will simply return NULL.

The class member function needs to be added to Window.cpp:

void Window::handleWindowCloseEvents() {
  Logger::log(1, "%s: Window got close event... bye!\n",
    __FUNCTION__);
}

Currently, the handleWindowCloseEvents() function just prints out a log line and does nothing else. But this is the perfect place to check whether the user really wants to quit or if unsaved changes have been made.

This function has to be declared in the Window.h header file, too:

private:
  void handleWindowCloseEvents();

If you start the compiled code and close the window, you should get an output like this:

init: Window successfully initialized
handleWindowCloseEvents: Window got close event... bye!
cleanup: Terminating Window

You can check the other events in the GLFW documentation and add other callback functions plus the respective lambdas. Additionally, you can check the example code for more calls – it has simple support for window movement, minimizing and maximizing, and printing out some log messages when the events are processed.

Important note

Some OSs stall the window content update if your application window has been moved or resized. So, don’t be alarmed if this happens – it is not a bug in your code. Workarounds are available to keep the window content updated on these window events, and you can check the GLFW documentation to find a way to solve this.

Now that our application window behaves in the way we would expect, we should add methods for a user to control what happens in our program.

CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
C++ Game Animation Programming
notes
bookmark Notes and Bookmarks search Search in title playlist Add to playlist download Download options font-size Font size

Change the font size

margin-width Margin width

Change margin width

day-mode Day/Sepia/Night Modes

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY

Submit Your Feedback

Modal Close icon
Modal Close icon
Modal Close icon