small3d Tutorial

Published December 10, 2020 by dimi309
Do you see issues with this article? Let us know.
Advertisement

small3d is a small, cross-platform 3D game development library I have put together and have been maintaining over the past few years. This is a tutorial on creating a ball in Blender, and then writing a C++ program that loads it and moves it around on the screen, using small3d. Alternatively you can skip the ball creation and use a model of your own, if you have one in a glTF .glb file.

The source code for this tutorial can be found here: https://github.com/dimi309/ball

Getting small3d and Blender

The first thing to do is to download small3d from GitHub: https://github.com/dimi309/small3d​​

Just follow the instructions in the README file to build it.

If you have or can find a glTF .glb file containing a model somewhere, you can use that for the tutorial. Just skip to “Cmake setup”. Otherwise you need to install Blender since this tutorial begins with creating a model of a ball: https://www.blender.org/

Creating a 3D Model with Blender

When you start Blender, you see a cube, and probably a camera:

Press a to select them. If they are selected already, pressing a will de-select them. Press it again in that case. Then x to delete everything.

You will be asked to confirm the deletion:

Just press enter to do so. Then, from the menu, select Add > Mesh > UV Sphere:

This will create, as it says, a sphere:

With the sphere selected (use the a key if it is not), select Object > Shade Smooth from the menu:

This is not important but it will make the sphere look better.

We now need to create the Wavefront file. From the menu at the top, select File > Export > glTF 2.0 (.glb/.gltf):

Save the exported file as ball.obj (name it and click on the Export OBJ button):

CMake Setup

Let's proceed to make our first program. Note that, instead of writing all the CMake code below, we could have just created a Visual Studio project for example, adding the small3d library and dependencies to it. But using CMake as described will truly make our demo cross-platform, being able to compile and run on Windows, MacOS or Linux.

Create a directory, called ball. Then create another directory within it, called resources and place ball.obj in it. Also add the following code to a CMakeFiles.txt within the ball directory:

cmake_minimum_required(VERSION 3.15.0)

project(ball)

file(COPY "resources" DESTINATION "${PROJECT_BINARY_DIR}/bin")
file(COPY "deps/shaders" DESTINATION "${PROJECT_BINARY_DIR}/bin/resources")

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/deps/cmake)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
if(MSVC)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin")
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin")
endif(MSVC)

set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/deps")

subdirs(src)

Create a directory called src within the ball directory and, inside it, another CMakeLists.txt file:

find_package(small3d REQUIRED)

add_executable(ball main.cpp)

target_link_libraries(ball PRIVATE small3d::small3d)

if(MSVC)
  set_target_properties(ball PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY
    "${PROJECT_BINARY_DIR}/bin")
endif()

The code

Inside ball/src, create the main.cpp file:

int main(int argc, char **argv) {

 return 0;
}

Include small3d's Renderer and SceneObject and GlbFile classes:

#include <small3d/Renderer.hpp>
#include <small3d/SceneObject.hpp>
#include <small3d/GlbFile.hpp>

Now we need the GLFW header files:

#include <GLFW/glfw3.h>

We also need to be using the small3d namespace, so this goes under our include statements:

using namespace small3d;

We also need to write the logic that will be detecting key presses:

bool downkey, leftkey, rightkey, upkey, esckey;

void keyCallback(GLFWwindow* window, int key, int scancode, int action,
 int mods)
{
if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
     downkey = true;
if (key == GLFW_KEY_UP && action == GLFW_PRESS)
     upkey = true;
if (key == GLFW_KEY_LEFT && action == GLFW_PRESS)
     leftkey = true;
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS)
     rightkey = true;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
     esckey = true;
if (key == GLFW_KEY_DOWN && action == GLFW_RELEASE)
     downkey = false;
if (key == GLFW_KEY_UP && action == GLFW_RELEASE)
     upkey = false;
if (key == GLFW_KEY_LEFT && action == GLFW_RELEASE)
     leftkey = false;
if (key == GLFW_KEY_RIGHT && action == GLFW_RELEASE)
     rightkey = false;
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
     esckey = false;

}

And finally, we go to the main program, and we create the renderer. The renderer is a singleton, so it can only be retrieved via the getInstance method, and assigned to a pointer:

Renderer *renderer = &Renderer::getInstance("Ball demo");

We will later need to access the window of the application, in order to pick up key events:

GLFWwindow* window = renderer->getWindow();

We create the ball:

SceneObject ball("ball", Model(GlbFile("resources/ball.glb")));

small3d uses vectors a lot as parameters for convenience. When positioning the ball, the components are in order, x (-left, +right), y(+up, -down), and z (-away from the camera, +towards the camera):

ball.position = glm::vec3(0.0f, -1.0f, -8.0f);

So let's start our main loop now. small3d uses GLFW and you can use it too! First we need to declare the callback function, which will be the keyCallback

method we wrote above.

glfwSetKeyCallback(window, keyCallback);

Now in every iteration, we need to check whether we want to exit the program. Let's say that we'll be doing that with the Esc key:

while (!glfwWindowShouldClose(window) && !esckey) {

glfwPollEvents();
 if (esckey)
  break;

If after that we are still in the loop (so, no Esc key pressed), we will want to move the ball around with the keyboard.

We will have the up arrow move the ball away from the camera. Down will do the opposite. Left and right move the ball as implied.

if (upkey)
  ball.position.z -= 0.001f;
else if (downkey)
  ball.position.z += 0.001f;
else if (leftkey)
  ball.position.x -= 0.001f;
else if (rightkey)
  ball.position.x += 0.001f;

Ok, the ball is positioned. Now we need to actually render it. The second parameter is the colour. Let's say it's yellow (the vector below symbolises an rgb colour, together with the alpha channel):

renderer->render(ball, glm::vec4(1.0f, 1.0f, 0.0f, 1.0f));

We are using a buffered system (we draw on one buffer, while the user is looking at the other one), so we also need to swap the buffers:

renderer->swapBuffers();

And we close the loop :)

}

That's it!

Let's try it out. Create a ball/deps directory and from the built small3d library copy the cmake, build/include, build/lib and build/shaders directories to this deps directory. Then, back from the root ball directory execute:

mkdir build
cd build
cmake ..
cmake --build .
cd bin
./ball

On Windows, you need to execute cmake .. -G"MinGW Makefiles", or with the preferred Visual Studio configuration (e.g. cmake .. -G"Visual Studio 17 2022" -A x64).

On some platforms where the C++ '14 (at least) standard is not supported by default (this is the case on MacOS for example), in order to avoid compilation errors, you need to pass it to cmake:

cmake .. -DCMAKE_CXX_STANDARD=14

Note that you have to be inside the build/bin directory in order to execute the program, otherwise it will not find the necessary resource files (shaders, textures, etc).

There's our ball:

Try moving it around with the arrows.

small3d supports a lot more features than those presented here, like playing sounds, collision detection and building with the conan build system which is a lot faster and easier than plain cmake. A good way to learn about all that is to read the documentation and also to explore the source code of the sample game, Gloom.

Don't hesitate to comment if you have some trouble with this tutorial, or if you have any other questions.

Cancel Save
1 Likes 0 Comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement