Illusion Engine 01 - Preparation

Introduction

This article is aimed at doing all the preparation work before coding. It includes the construction of the project structure, the configuration of the project, and the introduction to third-party libraries.

Creating the project

The recommended IDE is visual studio 2022. This project also works for Visual Studio 2017 and 2019. The test on other IDE hasn’t been done.

Create a static library as our engine project, so that it could be statically linked to our game application.

This project would become our engine project. Other than that, we have to create an empty project in this solution which will become our game application.

Here I’ll name the engine project “Illusion”.


Project Structure

Game and Illusion could be included in a single folder, such as Root. In my project, I included them in a folder called Collection. So the structure looks like this:

  • Game
    • The Game project, includes: src/… folder, assets/shaders/… folder, and assets/textures/… folder.
    • The src folder contains all the source code for the game application
    • The shaders folder contains customized shaders and the textures folder contains all kinds of texture resources.
  • Illusion
    • The Illusion project, includes: Lib/… folder, and src/Engine/… folder
    • In the src folder, the source code is separated into different folders based on their function, such as Core, Event, Renderer, etc.
    • The content in the Lib folder would be explained in the third parties part below.
  • Lib
    • The third-party library or tools that are not necessary for the Illusion Engine and Game Application, but is helpful when we build the whole project, such as premake, cmake, etc.
    • Either Illusion or Game could be executed without the existence of premake, but premake could help us get rid of configuring the project over and over again.
  • Scripts
    • The bat files that calls premake or clean up the project.

As a result, the final structure of the project looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Collection
├─Game
│ ├─assets
│ │ ├─shaders
│ │ └─textures
│ └─src
├─Illusion
│ ├─Lib
│ │ ├─Glad
│ │ ├─GLFW
│ │ ├─glm
│ │ ├─imgui
│ │ ├─spdlog
│ │ └─stb_image
│ └─src
│ └─Engine
│ ├─Core
│ │ ├─Application
│ │ ├─Input
│ │ ├─Layer
│ │ ├─Log
│ │ ├─Resource
│ │ ├─Utils
│ │ └─Window
│ ├─Event
│ ├─ImGui
│ └─Renderer
├─Lib
└─Scripts

Third-party Libraries

As of the time this article is published, the third-party library used in this project includes:

  • SpdLog
    • A fast C++ logging library.
  • GLFW
    • GL Frame Work, a multi-platform library for OpenGL, OpenGL ES, Vulkan. Mainly used to handle input and window events.
  • Glad
    • The dependency library for OpenGL, including API for OpenGL.
  • ImGui
    • A Bloat-free Graphical User interface for C++ with minimal dependencies. Used to build viewer and editor
  • glm
    • A basic math library, including vector, matrix, and some other common math components.
  • Premake
    • A command line utility that reads a scripted definition of a software project, then uses it to perform build configuration tasks or generate project files.

All of these libraries could be found on GitHub. You could click on the name of the library to jump to its page on Github.

SpdLog, GLFW, Glad, ImGui, and glm are included in Collection/Illusion/Lib… folder.

Premake is included in Collection/Lib/… folder.


Configurations

Since we have premake, we could add a configuration file for our projects.

Inside Collection/… folder, create a file called “premake” and revise its extension to “.lua”.

In premake.lua, enter code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
-- Set up a workspace, this would work for every project
workspace "Project"
architecture "x64"
-- Set the starting project to be Game
startproject "Game"
-- Define Build Configuration
configurations
{
"Debug",
"Release",
"Dist"
}
-- Set the output file format to be like "Debug-Windows-x86_64"
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
-- Include directories relative to the root folder (solution directory)
IncludeDir = {}
IncludeDir["GLFW"] = "Illusion/Lib/GLFW/include"
IncludeDir["Glad"] = "Illusion/Lib/Glad/include"
IncludeDir["ImGui"] = "Illusion/Lib/imgui"
IncludeDir["glm"] = "Illusion/Lib/glm"
IncludeDir["stb_image"] = "Illusion/Lib/stb_image"
-- Include these folders to load the configuration files at those positions
include "Illusion/Lib/GLFW"
include "Illusion/Lib/Glad"
include "Illusion/Lib/imgui"
-- Define Illusion Project, set the relative path, set the kind to be a static library, and set the language
project "Illusion"
location "Illusion"
kind "StaticLib"
language "C++"
cppdialect "C++17"
staticruntime "on"
-- Set the output path and intermediate path
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
-- Define the precompile header
pchheader "pch.h"
pchsource "Illusion/src/pch.cpp"
-- Define files that would be compiled
files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp",
"%{prj.name}/Lib/stb_image/**.h",
"%{prj.name}/Lib/stb_image/**.cpp",
"%{prj.name}/Lib/glm/glm/**.hpp",
"%{prj.name}/Lib/glm/glm/**.inl",
}
-- Preprocess macros
defines
{
"_CRT_SECURE_NO_WARNINGS"
}
-- Define include path
includedirs
{
"%{prj.name}/src",
"%{prj.name}/Lib/spdlog/include",
"%{IncludeDir.GLFW}",
"%{IncludeDir.Glad}",
"%{IncludeDir.ImGui}",
"%{IncludeDir.glm}",
"%{IncludeDir.stb_image}"
}
-- Link these libraries to the project
links
{
"GLFW",
"Glad",
"ImGui",
"opengl32.lib"
}
-- Define some macros for different build options
filter "system:windows"
systemversion "latest"

defines
{
"ILLUSION_PLATFORM_WINDOWS",
"GLFW_INCLUDE_NONE"
}

filter "configurations:Debug"
defines "ILLUSION_DEBUG"
runtime "Debug"
symbols "on"

filter "configurations:Release"
defines "ILLUSION_RELEASE"
runtime "Release"
optimize "on"

filter "configurations:Dist"
defines "ILLUSION_DIST"
runtime "Release"
optimize "on"
-- Define Game Project
project "Game"
location "Game"
kind "ConsoleApp"
language "C++"
cppdialect "C++17"
staticruntime "on"
-- Set the output path and intermediate path
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
-- Define files that would be compiled
files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp"
}
-- Define include path
includedirs
{
"Illusion/Lib/spdlog/include",
"Illusion/src",
"Illusion/Lib",
"%{IncludeDir.glm}"
}
-- Link the engine to the project
links
{
"Illusion"
}
-- Define some macros for different build options
filter "system:windows"
systemversion "latest"

defines
{
"ILLUSION_PLATFORM_WINDOWS"
}

filter "configurations:Debug"
defines "ILLUSION_DEBUG"
runtime "Debug"
symbols "on"

filter "configurations:Release"
defines "ILLUSION_RELEASE"
runtime "Release"
optimize "on"

filter "configurations:Dist"
defines "ILLUSION_DIST"
runtime "Release"
optimize "on"

Additionally, since we have to build those third-party libraries, they also need their configuration files.

Inside Collection/Illusion/Lib/GLFW/… folder, create a file called “premake.lua”, and enter code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
project "GLFW"
kind "StaticLib"
language "C"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files
{
"include/GLFW/glfw3.h",
"include/GLFW/glfw3native.h",
"src/glfw_config.h",
"src/context.c",
"src/init.c",
"src/input.c",
"src/monitor.c",
"src/vulkan.c",
"src/window.c"
}
filter "system:windows"
systemversion "latest"
staticruntime "on"
files
{
"src/win32_init.c",
"src/win32_joystick.c",
"src/win32_monitor.c",
"src/win32_time.c",
"src/win32_thread.c",
"src/win32_window.c",
"src/wgl_context.c",
"src/egl_context.c",
"src/osmesa_context.c"
}
defines
{
"_GLFW_WIN32",
"_CRT_SECURE_NO_WARNINGS"
}
filter { "system:windows", "configurations:Release" }
buildoptions "/MT"

Inside Collection/Illusion/Lib/Glad/… folder, create a file called “premake.lua”, and enter the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
project "Glad"
kind "StaticLib"
language "C"
staticruntime "on"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files
{
"include/glad/glad.h",
"include/KHR/khrplatform.h",
"src/glad.c"
}
includedirs
{
"include"
}
filter "system:windows"
systemversion "latest"
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"

Inside Collection/Illusion/Lib/ImGui/… folder, create a file called “premake.lua”, and enter code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
project "ImGui"
kind "StaticLib"
language "C++"
cppdialect "C++17"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files
{
"imconfig.h",
"imgui.h",
"imgui.cpp",
"imgui_draw.cpp",
"imgui_internal.h",
"imgui_widgets.cpp",
"imstb_rectpack.h",
"imstb_textedit.h",
"imstb_truetype.h",
"imgui_demo.cpp"
}
filter "system:windows"
systemversion "latest"
staticruntime "on"
filter { "system:windows", "configurations:Release" }
buildoptions "/MT"

After this, the configuration information for the whole project is recorded. To build the project, we only have to call premake5 and tell it the toolset that we are using:

1
> Lib/Premake5/Premake5.exe vs2022

To simplify this procedure, we need a bat file inside Collection/Scripts/… folder.

Inside Build.bat, enter the code:

1
2
3
4
5
6
7
8
@echo off
pushd C:
cd Program Files (x86)\Microsoft Visual Studio\Installer
for /f "delims=" %%t in ('vswhere.exe -property catalog_productLineVersion') do set version=%%t
popd
cd ..\
call Lib\premake5\Premake5.exe vs%version%
PAUSE

This file would figure out the version of visual studio installed on this device and pass it to premake to generate the correct version of project files such as .vs, .sln, .vcproj, etc.

Inside Clear.bat, enter the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cd ..\
rd /s /q .vs
rd /s /q bin
rd /s /q bin-int
del /a Project.sln
del /a /s *.vcxproj.*
pushd Illusion\Lib\Glad
rd /s /q bin
rd /s /q bin-int
popd
pushd Illusion\Lib\GLFW
rd /s /q bin
rd /s /q bin-int
popd
pushd Illusion\Lib\imgui
rd /s /q bin
rd /s /q bin-int
popd
PAUSE

This file would delete all the project files, including .vs, .sln, .vcproj, etc. Only source code would be left. It is a tool that helps us clean up the project and save space.

Thus, by running Build.bat and Clear.bat, we could easily generate or clean up the project.

Conclusion

So far, we have completed the configuration of the entire project. We stored the configuration information in premake.lua, and handed over the creation and cleaning of the project to the batch files to complete. By doing so, we don’t have to configure the project and struggle with the linkclude problem over and over again.


Illusion Engine 01 - Preparation
https://rigel.github.io/Preparation/
Author
Rigel
Posted on
July 30, 2022
Licensed under