feat: bare-bones input system

This commit is contained in:
Kevin J. 2025-01-27 19:16:31 +01:00
parent 93431eccf0
commit 1489671f24
21 changed files with 219 additions and 113 deletions

1
.gitignore vendored
View File

@ -1,3 +1,2 @@
thirdparty/*/
build/
.cache/

6
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "thirdparty/bgfx.cmake"]
path = thirdparty/bgfx.cmake
url = https://github.com/bkaradzic/bgfx.cmake
[submodule "thirdparty/imgui.cmake"]
path = thirdparty/imgui.cmake
url = https://github.com/tamaskenez/imgui-cmake
[submodule "thirdparty/glfw.cmake"]
path = thirdparty/glfw.cmake
url = https://github.com/glfw/glfw
@ -13,3 +10,6 @@
[submodule "thirdparty/glm.cmake"]
path = thirdparty/glm.cmake
url = https://github.com/icaven/glm
[submodule "thirdparty/imgui.cmake"]
path = thirdparty/imgui.cmake
url = https://github.com/tamaskenez/imgui-cmake

View File

@ -75,3 +75,9 @@ foreach(TEXTURE_SOURCE ${TEXTURE_SOURCE_FILES})
)
endforeach()
# build models into /build/models
add_custom_target("models" ALL
COMMAND /bin/bash -c "cp -rf ${PROJECT_SOURCE_DIR}/models/ ${CMAKE_CURRENT_BINARY_DIR}/"
)
# file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/models")
# file(COPY "${PROJECT_SOURCE_DIR}/models/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/models/")

Binary file not shown.

View File

@ -5,6 +5,8 @@
#include <bgfx/bgfx.h>
#include <bx/file.h>
#define GLFW_DEBUG
#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 720

View File

@ -16,17 +16,24 @@ class Engine {
public:
Engine(void);
int Init(void);
void Start(void);
int Update(void);
void Shutdown(void);
static void GlfwErrorCallback(int error, const char *s);
void Instantiate(EngineObject* obj);
unsigned int GetInput(void);
GLFWwindow* main_window;
int main_view;
int keyboard_slots[GLFW_KEY_LAST];
int cursor_slots[GLFW_MOUSE_BUTTON_LAST+1];
int cursor_xpos;
int cursor_ypos;
static void keyboard_callback(GLFWwindow *window, int key, int scancode, int action, int mods);
static void cursor_callback(GLFWwindow *window, double x, double y);
static void cursor_button_callback(GLFWwindow *window, int button, int action, int mods);
private:
int width;
int height;
@ -36,7 +43,6 @@ class Engine {
bgfx::UniformHandle u_position;
bgfx::UniformHandle u_rotation;
bgfx::UniformHandle u_scale;
bgfx::UniformHandle u_texture_color;
std::vector<EngineObject *> objs;
};

View File

@ -1,21 +1,27 @@
#ifndef OBJECT_HPP
#define OBJECT_HPP
#include "bgfx/bgfx.h"
#include <glm/glm.hpp>
#include <vector>
#include <engine/quad.hpp>
#include <glm/glm.hpp>
#include <bgfx/bgfx.h>
#include <assimp/scene.h>
class EngineObject {
public:
EngineObject(void);
EngineObject(std::string texture);
EngineObject();
EngineQuad quad_data;
int load_node(aiScene *scene, aiNode *node);
int load_model(std::string filename);
glm::vec4 position;
glm::vec4 rotation;
glm::vec4 scale;
std::vector<float> vertices;
std::vector<uint16_t> indices;
bgfx::VertexLayout layout;
bgfx::TextureHandle texture;
bgfx::VertexBufferHandle vbh;
bgfx::IndexBufferHandle ibh;

25
models/cube.obj Normal file
View File

@ -0,0 +1,25 @@
# Blender 4.3.2
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
s 0
g off
f 5 3 1
f 3 8 4
f 7 6 8
f 2 8 6
f 1 4 2
f 5 2 6
f 5 7 3
f 3 7 8
f 7 5 6
f 2 4 8
f 1 3 4
f 5 1 2

View File

@ -1,14 +1,8 @@
$input v_texcoord0
uniform sampler2D u_texture_color;
$input f_position
#include <bgfx_shader.sh>
#include <shaderlib.sh>
void main() {
vec4 color = texture2D(u_texture_color, v_texcoord0);
if (color.r == 0 && color.g == 0 && color.b == 0) {
return;
}
gl_FragColor = color;
gl_FragColor = vec4(f_position.xyz, 1.0f);
}

View File

@ -1,5 +1,3 @@
vec2 a_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
vec3 a_position : POSITION;
vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
vec3 f_position : POSITION;

View File

@ -1,17 +1,34 @@
$input a_position, a_texcoord0
$output v_texcoord0
$input a_position
$output f_position
uniform vec4 u_position;
uniform vec4 u_rotation;
uniform vec4 u_scale;
#include <bgfx_shader.sh>
#include <shaderlib.sh>
void main() {
vec4 scale = mul(u_scale, vec4(a_position, 1.0f));
// rotation
mat3 x_rot = mat3(1, 0, 0,
0, cos(u_rotation.x), -sin(u_rotation.x),
0, sin(u_rotation.x), cos(u_rotation.x));
mat3 y_rot = mat3(cos(u_rotation.y), 0, sin(u_rotation.y),
0, 1, 0,
-sin(u_rotation.y), 0, cos(u_rotation.y));
mat3 z_rot = mat3(cos(u_rotation.z), -sin(u_rotation.z), 0,
sin(u_rotation.z), cos(u_rotation.z), 0,
0, 0, 1);
vec3 r_position = a_position;
r_position = mul(r_position, x_rot);
r_position = mul(r_position, y_rot);
r_position = mul(r_position, z_rot);
vec4 scale = mul(u_scale, vec4(r_position, 1.0f));
vec4 view = mul(u_view, scale);
vec4 pos = view + u_position;
gl_Position = mul(u_proj, pos);
v_texcoord0 = a_texcoord0;
f_position = r_position;
}

View File

@ -1,10 +1,11 @@
#include <iostream>
#include "bgfx/defines.h"
#include "engine/object.hpp"
#include <bx/file.h>
#include <bx/math.h>
#include <glm/fwd.hpp>
#include <iostream>
#include <vector>
#include <cstring>
#include <engine.hpp>
#include <bgfx/bgfx.h>
#include <glm/glm.hpp>
@ -21,23 +22,51 @@ Engine::Engine(void) {
this->title = "EO";
this->main_view = 0;
memset(this->keyboard_slots, 0, sizeof(this->keyboard_slots));
memset(this->cursor_slots, 0, sizeof(this->cursor_slots));
}
void Engine::keyboard_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
Engine *engine = (Engine *) glfwGetWindowUserPointer(window);
engine->keyboard_slots[key] = action;
}
void Engine::cursor_callback(GLFWwindow *window, double x, double y) {
Engine *engine = (Engine *) glfwGetWindowUserPointer(window);
engine->cursor_xpos = x;
engine->cursor_ypos = y;
}
void Engine::cursor_button_callback(GLFWwindow *window, int button, int action, int mods) {
Engine *engine = (Engine *) glfwGetWindowUserPointer(window);
engine->cursor_slots[button] = action;
}
int Engine::Init(void) {
int ret = 0;
glfwSetErrorCallback(Engine::GlfwErrorCallback);
ret = glfwInit();
int ret = glfwInit();
if (ret < 0) {
ERROR("failed initializing glfw");
return -1;
}
glfwSetErrorCallback(Engine::GlfwErrorCallback);
this->main_window = glfwCreateWindow(this->width, this->height, this->title.c_str(), NULL, NULL);
if (!this->main_window) {
ERROR("failed creating window");
return -1;
}
glfwSetWindowUserPointer(this->main_window, this);
glfwSetKeyCallback(this->main_window, Engine::keyboard_callback);
glfwSetCursorPosCallback(this->main_window, Engine::cursor_callback);
glfwSetMouseButtonCallback(this->main_window, Engine::cursor_button_callback);
#ifndef GLFW_DEBUG
glfwSetInputMode(this->main_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
bgfx::Init init;
init.platformData.ndt = glfwGetX11Display();
init.platformData.nwh = (void*) (uintptr_t) glfwGetX11Window(this->main_window);
@ -51,6 +80,10 @@ int Engine::Init(void) {
return -1;
}
#ifndef BGFX_DEBUG
bgfx::setDebug(BGFX_DEBUG_NONE);
#endif
bgfx::setViewClear(this->main_view,
BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH,
0x478effff,
@ -64,25 +97,14 @@ int Engine::Init(void) {
float view[16];
bx::mtxLookAt(view, eye, at);
float ortho[16];
bx::mtxOrtho(ortho,
(float) -this->width/(CAMERA_WIDTH*2),
(float) this->width/(CAMERA_WIDTH*2),
(float) -this->height/(CAMERA_WIDTH*2),
(float) this->height/(CAMERA_WIDTH*2),
CAMERA_NEAR,
CAMERA_FAR,
0.0f,
bgfx::getCaps()->homogeneousDepth
);
float proj[16];
bx::mtxProj(proj, 60.0f, float(this->width)/float(this->height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
bgfx::setViewTransform(this->main_view, view, ortho);
bgfx::setViewTransform(this->main_view, view, proj);
}
bgfx::setViewRect(this->main_view, 0, 0, this->width, this->height);
this->u_texture_color = bgfx::createUniform("u_texture_color", bgfx::UniformType::Sampler);
this->u_position = bgfx::createUniform("u_position", bgfx::UniformType::Vec4);
this->u_rotation = bgfx::createUniform("u_rotation", bgfx::UniformType::Vec4);
this->u_scale = bgfx::createUniform("u_scale", bgfx::UniformType::Vec4);
@ -91,9 +113,6 @@ int Engine::Init(void) {
return 0;
}
void Engine::Start(void) {
}
int Engine::Update(void) {
std::int32_t new_width;
std::int32_t new_height;
@ -107,14 +126,15 @@ int Engine::Update(void) {
bgfx::touch(this->main_view);
for (int i = 0; i < this->objs.size(); i++) {
bgfx::setState(
BGFX_STATE_WRITE_R |
bgfx::setState(BGFX_STATE_WRITE_R |
BGFX_STATE_WRITE_G |
BGFX_STATE_WRITE_B |
BGFX_STATE_WRITE_A |
BGFX_STATE_BLEND_ALPHA
);
BGFX_STATE_BLEND_ALPHA |
BGFX_STATE_DEPTH_TEST_LESS |
BGFX_STATE_CULL_CCW );
EngineObject* obj = this->objs[i];
@ -125,8 +145,6 @@ int Engine::Update(void) {
bgfx::setUniform(this->u_rotation, &obj->rotation);
bgfx::setUniform(this->u_scale, &obj->scale);
bgfx::setTexture(0, this->u_texture_color, obj->texture);
bgfx::submit(this->main_view, this->program);
}
@ -145,7 +163,6 @@ void Engine::Shutdown(void) {
bgfx::destroy(this->u_position);
bgfx::destroy(this->u_rotation);
bgfx::destroy(this->u_scale);
bgfx::destroy(this->u_texture_color);
bgfx::destroy(this->program);
@ -160,21 +177,3 @@ void Engine::GlfwErrorCallback(int error, const char *s) {
void Engine::Instantiate(EngineObject* obj) {
this->objs.push_back(obj);
}
unsigned int Engine::GetInput(void) {
unsigned int ret = 0;
int keys[] = {
GLFW_KEY_A,
GLFW_KEY_D,
GLFW_KEY_W,
GLFW_KEY_S,
};
for (int i = sizeof(keys)/sizeof(int); i >= 0; i--) {
int state = glfwGetKey(this->main_window, keys[i]);
ret = (ret << 1) + (state == GLFW_PRESS ? 1 : 0);
}
return ret;
}

View File

@ -1,35 +1,90 @@
#include "assimp/mesh.h"
#include "assimp/vector3.h"
#include "common.hpp"
#include "glm/fwd.hpp"
#include <engine/object.hpp>
#include <bgfx/bgfx.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
EngineObject::EngineObject(void) : quad_data() {
this->position = glm::vec4(0.0f);
EngineObject::EngineObject() {
this->position = glm::vec4(0.0f, 0.0f, 1.0f, 0.0f);
this->rotation = glm::vec4(0.0f);
this->scale = glm::vec4(1.0f);
this->vbh = bgfx::createVertexBuffer(bgfx::makeRef(
this->quad_data.vertices.data(),
this->quad_data.vertices.size()*sizeof(VertexData)),
this->quad_data.layout);
this->ibh = bgfx::createIndexBuffer(bgfx::makeRef(
this->quad_data.indices.data(),
this->quad_data.indices.size()*sizeof(uint16_t))
);
this->layout.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.end();
}
EngineObject::EngineObject(std::string texture) : quad_data() {
this->position = glm::vec4(0.0f);
this->rotation = glm::vec4(0.0f);
this->scale = glm::vec4(1.0f);
int EngineObject::load_node(aiScene *scene, aiNode *node) {
if (node == nullptr) {
return -1;
}
if (scene == nullptr) {
return -1;
}
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
aiMesh *mesh = scene->mMeshes[i];
for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
this->vertices.push_back(mesh->mVertices[j].x);
this->vertices.push_back(mesh->mVertices[j].y);
this->vertices.push_back(mesh->mVertices[j].z);
}
for (unsigned int j = 0; j < mesh->mNumFaces; ++j) {
aiFace *face = &(mesh->mFaces[j]);
this->indices.insert(this->indices.end(), &face->mIndices[0], &face->mIndices[face->mNumIndices]);
}
}
for (int i = 0; i < node->mNumChildren; ++i) {
this->load_node(scene, node->mChildren[i]);
}
return 0;
}
struct vertex {
float x;
float y;
float z;
};
int EngineObject::load_model(std::string filename) {
Assimp::Importer importer;
aiScene *scene = (aiScene *) importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs);
if (scene == nullptr || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
std::cout << "--error: failed loading model from file-system" << std::endl;
return -1;
}
aiNode *root = scene->mRootNode;
if (root == NULL) {
std::cout << "--error: no model inside the loaded scene" << std::endl;
return -1;
}
int ret = this->load_node(scene, root);
if (ret < 0) {
std::cout << "-error: failed loading node tree" << std::endl;
return -1;
}
std::cout << "--log: successfully loaded model (" << filename << ")" << std::endl;
this->vbh = bgfx::createVertexBuffer(bgfx::makeRef(
this->quad_data.vertices.data(),
this->quad_data.vertices.size()*sizeof(VertexData)),
this->quad_data.layout);
this->vertices.data(),
this->vertices.size()*sizeof(float)),
this->layout);
this->ibh = bgfx::createIndexBuffer(bgfx::makeRef(
this->quad_data.indices.data(),
this->quad_data.indices.size()*sizeof(uint16_t))
this->indices.data(),
this->indices.size()*sizeof(uint16_t))
);
this->texture = load_texture(texture);
return 0;
}

View File

@ -4,7 +4,6 @@
#include <engine.hpp>
#include <engine/animation.hpp>
#include <chrono>
#include <ratio>
#define GET_MS \
std::chrono::duration_cast<std::chrono::milliseconds>( \
@ -15,21 +14,17 @@ int main(int argc, char *argv[]) {
Engine engine;
int ret = engine.Init();
std::cout << "ret " << ret << std::endl;
if (ret < 0) {
ERROR("failed initializing engine");
return EXIT_FAILURE;
}
Animation idle_animation(&engine, "textures/idle.dds", 32, 32, 4, 0.2f);
Animation run_animation(&engine, "textures/run.dds", 32, 32, 8, 0.2f);
Animation* active_animation;
EngineObject obj;
obj.load_model("models/cube.obj");
obj.position.z = -30.0f;
EngineObject* character = new EngineObject("textures/knight.dds");
character->scale.x = 2.5f;
character->scale.y = 2.5f;
engine.Instantiate(character);
engine.Start();
engine.Instantiate(&obj);
std::chrono::milliseconds ms = GET_MS;
int delta_time = 0;
@ -37,19 +32,18 @@ int main(int argc, char *argv[]) {
while (!glfwWindowShouldClose(engine.main_window)) {
glfwPollEvents();
unsigned int input = engine.GetInput();
active_animation = input > 0 ? &run_animation : &idle_animation;
active_animation->Cycle(time, character);
obj.rotation.y += 0.01f;
obj.rotation.z -= 0.01f;
obj.rotation.z += 0.02f;
std::chrono::milliseconds tmp = GET_MS;
delta_time = tmp.count() - ms.count();
time += delta_time;
ms = tmp;
engine.Update();
}
engine.Shutdown();
delete(character);
return EXIT_SUCCESS;
}

1
thirdparty/assimp.cmake vendored Submodule

@ -0,0 +1 @@
Subproject commit 2aac984fa3e2459fcca18d5b8f88e648170ee694

1
thirdparty/bgfx.cmake vendored Submodule

@ -0,0 +1 @@
Subproject commit 06144dcb9b8924c096966432d7702e3d66f7721a

1
thirdparty/glfw.cmake vendored Submodule

@ -0,0 +1 @@
Subproject commit e7ea71be039836da3a98cea55ae5569cb5eb885c

1
thirdparty/glm.cmake vendored Submodule

@ -0,0 +1 @@
Subproject commit dca38025fba63bb9284023e6de55f756b9e37cec

1
thirdparty/imgui.cmake vendored Submodule

@ -0,0 +1 @@
Subproject commit 21a8fa1d0f46f100c142dace636bae85699e5aeb

Binary file not shown.

Binary file not shown.