Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
C++ Game Animation Programming

You're reading from   C++ Game Animation Programming Learn modern animation techniques from theory to implementation using C++, OpenGL, and Vulkan

Arrow left icon
Product type Paperback
Published in Dec 2023
Publisher Packt
ISBN-13 9781803246529
Length 480 pages
Edition 2nd Edition
Languages
Tools
Concepts
Arrow right icon
Authors (2):
Arrow left icon
Gabor Szauer Gabor Szauer
Author Profile Icon Gabor Szauer
Gabor Szauer
Michael Dunsky Michael Dunsky
Author Profile Icon Michael Dunsky
Michael Dunsky
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Preface 1. Part 1:Building a Graphics Renderer
2. Chapter 1: Creating the Game Window FREE CHAPTER 3. Chapter 2: Building an OpenGL 4 Renderer 4. Chapter 3: Building a Vulkan Renderer 5. Chapter 4: Working with Shaders 6. Chapter 5: Adding Dear ImGui to Show Valuable Information 7. Part 2: Mathematics Roundup
8. Chapter 6: Understanding Vector and Matrix 9. Chapter 7: A Primer on Quaternions and Splines 10. Part 3: Working with Models and Animations
11. Chapter 8: Loading Models in the glTF Format 12. Chapter 9: The Model Skeleton and Skin 13. Chapter 10: About Poses, Frames, and Clips 14. Chapter 11: Blending between Animations 15. Part 4: Advancing Your Code to the Next Level
16. Chapter 12: Cleaning Up the User Interface 17. Chapter 13: Implementing Inverse Kinematics 18. Chapter 14: Creating Instanced Crowds 19. Chapter 15: Measuring Performance and Optimizing the Code 20. Index 21. Other Books You May Enjoy

Creating your first window

After all the necessary software products have been installed, we are ready for our first smoke test. We will create a small, non-resizable window, and its only purpose is to check your system for the correct path and configuration. You will be able to move it around, minimize and restore it, and close it… that’s mostly all at this stage.

But believe me, seeing your first test window on the screen will make you smile. For basic window operations, we are going to use GLFW to open and close a window.

GLFW is an open source toolkit that is used to handle the tasks around the application window, and it is available for different OSs and hardware platforms.

GLFW will do the following tasks with a few lines of code, independent of your OS:

  • Create and destroy the application window
  • Handle the window events (such as minimize, resize, or close)
  • Add an OpenGL context or Vulkan support to enable 3D rendering
  • Get the input from the mouse, keyboard, and gamepads/joysticks

If you want to check the source for this example, head to the chapter01 folder in the Git checkout or the extracted source for this book, and then go to the 01_simple_window folder. You can follow the explanation of the code snippets, or in case you have no questions about the intention of the code lines, you can compile the code in advance and check the code snippets only for clarification.

For the window code, start with the Window.h header file:

#pragma once
#include <string>
#include <GLFW/glfw3.h>
class Window {
  public:
    bool init(unsigned int width, unsigned int height,
      std::string title);
    void mainLoop();
    void cleanup();
  private:
    GLFWwindow *mWindow = nullptr;
};

After the include guard, we need to include the std::string header, which we will use to pass the window title to the instance, and the GLFW header for the GLFW functions.

The Window class contains a handle for the GLFW window that we will create as a private member, along with three other public methods.The init() method is used to initialize the new window; the mainLoop() method runs the code of the main loop of the window where we do all the work; and the cleanup() method cleans up the window to shut down the application properly.

The implementation of the three functions is done in the Window.cpp file:

#include "Window.h"
#include "Logger.h"

We include our previously created header file for the Window class, plus the header file for the Logger class to ensure the console logging is available:

bool Window::init(unsigned int width, unsigned int height, std::string title) {
  if (!glfwInit()) {
    Logger::log(1, "%s: glfwInit() error\n",
      __FUNCTION__);
    return false;
  }
  /* set a "hint" for the NEXT window created*/
  glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
  mWindow = glfwCreateWindow(width, height,
    title.c_str(), nullptr, nullptr);
  if (!mWindow) {
    Logger::log(1, "%s: Could not create window\n",
      __FUNCTION__);
    glfwTerminate();
    return false;
  }
  Logger::log(1, "%s: Window successfully initialized\n",
      __FUNCTION__);
  return true;
}

The init() function checks whether GLFW could be initialized at all. If something unexpected happens, it will return false in the main() function and stop the program.

The window hint set with the glfwWindowHint() call is a special property in GLFW, which changes the settings for the creation of the next window. For example, we can disable the ability to resize our window. After this, the creation of the window itself is done, and the result is saved inside our member variable. If the window cannot be created, the process of creating a window will also be aborted and GLFW will be terminated. In a successful window creation, we output a log line to the console and return to the main() function, stating that everything went fine.

The mainLoop() function does nothing special for the first window; it simply checks whether the user generated an event to close the window, that is, by selecting the close button. If this is not the case, it instructs GLFW to poll any events. This call is required to react to anything happening to the window itself – keyboard presses, mouse events, and window operations such as minimizing or even closing:

void Window::mainLoop() {
  while (!glfwWindowShouldClose(mWindow)) {
    /* poll events in a loop */
    glfwPollEvents();
  }
}

Finally, the cleanup() function destroys the window and terminates GLFW, removing our window from the screen and ending the usage of GLFW. At this point, the destroy window operation is slightly redundant, as glfwTerminate() also kills all windows that are still onscreen. But using the explicit destroy function on the application window should remain here, in case of later additions to the termination process of the application:

void Window::cleanup() {
  Logger::log(1, "%s: Terminating Window\n",
      __FUNCTION__);
  glfwDestroyWindow(mWindow);
  glfwTerminate();
}

To compile the preceding code, we also need a file named CMakeLists.txt in our project folder. This file instructs the CMake build system about the configuration of the project; it states which files to compile and how to add the required additional dependencies.

In the following code snippet, at the top of the file, we set the minimum version of CMake to 3.19. This is the first version that provides support to find the shader compiler for Vulkan. We will need this in Chapter 3 for the Vulkan renderer:

cmake_minimum_required(VERSION 3.19)

Setting C++17 as the minimum version might seem a bit overkill for the projects in this book, but as I stated earlier, I will try to get rid of the legacy features of C++ and use the newer ones instead:

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

The next lines add the cmake folder inside the project folder to the list of locations CMake uses to store helper scripts for the find_package command:

# use custom file to find libraries
if(WIN32)
  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CUR
  RENT_LIST_DIR}/cmake")
endif()

As the current version of CMake does not search for GLFW, I have added a script to search for it. This extra script requires GLFW to be stored in a fixed location on the system, and by using the location we have chosen at installation time, we are able to use the single GLFW installation for all projects in the book, instead of having a copy per project.The GLFW search script is only needed on Windows, as Linux already includes a helper script in the GLFW package. So,we instruct CMake to only add this on Windows by using a check to WIN32. This variable is only defined on Windows.

Next, we name our project Main. You could use any arbitrary name here, and this could be used in other commands by referencing a variable. Then, we add the C++ (*.cpp) and header (.h) files in the local folder via a GLOB search and add them to the list of files to compile to our main executable, which will also be named Main. Under Windows, this will automatically get an extension, resulting in Main.exe:

project(Main)
file(GLOB SOURCES
     .h
     .cpp)
add_executable(Main ${SOURCES})

Now, the CMake command called find_package is used to locate the GLFW headers in version 3.3 or higher, marking GLFW also as required for the code compilation. The corresponding CMake helper script will set a couple of variables if GLFW has been found – here, the two important ones are GWLF3_LIBRARY and GLFW3_INCLUDE_DIR. Due to the different searches on Windows and Linux, we will reuse the GLFW3_LIBRARY variable to avoid any further splits in the control structures:

find_package(glfw3 3.3 REQUIRED)
#variable is set by FindGLFW3.cmake, reuse for Linux
if(UNIX)
  set(GLFW3_LIBRARY glfw)
endif()

Finally, the last two lines of the following code add the GLFW3 headers to the list of include paths for the compiler and the library to link to the final executable:

include_directories(${GLFW3_INCLUDE_DIR})
target_link_libraries(Main ${GLFW3_LIBRARY})

Now you can build the project, and it should compile the code without any errors or warnings. If the compilation fails, please check the Technical requirements section for all the required tools and libraries.

Start the executable file, Main.exe (Windows) or Main (Linux), and you will see a small window appear on the screen, as shown in the following screenshot:

Figure 1.20: Your first window

Figure 1.20: Your first window

Depending on your OS, the window might be filled in black, white, or even contain some parts of the screen where it was opened. The system does a “cheap” copy when creating the window, and we don’t clear the window content. So, don’t be alarmed if you don’t get exactly the same picture as Figure 1.1. As long as your window has the proper caption and the OS-specific buttons to close and minimize, everything has worked fine.

Now, let’s check out the available 3D-rendering APIs on the system.

You have been reading a chapter from
C++ Game Animation Programming - Second Edition
Published in: Dec 2023
Publisher: Packt
ISBN-13: 9781803246529
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime