added models and stuff

This commit is contained in:
2026-05-08 23:44:20 -04:00
parent 3c756d6230
commit 5484e265fb
24 changed files with 3281 additions and 199575 deletions

7
.gitmodules vendored
View File

@@ -7,6 +7,9 @@
[submodule "_ThirdParty/assimp"]
path = _ThirdParty/assimp
url = https://github.com/assimp/assimp.git
[submodule "glm"]
path = glm
[submodule "_ThirdParty/glm"]
path = _ThirdParty/glm
url = https://github.com/g-truc/glm.git
[submodule "_ThirdParty/entt"]
path = _ThirdParty/entt
url = https://github.com/skypjack/entt.git

View File

@@ -17,14 +17,15 @@ add_subdirectory(_ThirdParty/spdlog)
set (ASSIMP_INSTALL OFF)
add_subdirectory(_ThirdParty/assimp)
add_subdirectory(glm)
add_subdirectory(_ThirdParty/glm)
add_subdirectory(_ThirdParty/entt)
add_executable(${PROJECT_NAME}
src/main.cpp
${GLAD_SOURCE_DIR}/gl.c
src/Mesh.cpp
src/Mesh.h
src/Model.cpp
src/Model.h
src/Material.h
src/ModelManager.cpp
@@ -39,7 +40,10 @@ add_executable(${PROJECT_NAME}
src/FreeCamera.cpp
src/FreeCamera.h
src/InputManager.cpp
src/InputManager.h)
src/InputManager.h
src/Components.h
src/Scene.cpp
src/Scene.h)
add_custom_target(copy_resources
COMMAND ${CMAKE_COMMAND} -E copy_directory
@@ -48,5 +52,5 @@ add_custom_target(copy_resources
COMMENT "Copying resources..."
)
target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm)
target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT)
target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR})

1
_ThirdParty/entt vendored Submodule

Submodule _ThirdParty/entt added at 1333fa5312

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

View File

@@ -1,16 +0,0 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Scene_-_Root
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.0 0.0 0.0
Ni 1.450000
d 1.000000
illum 2
map_Kd diffuse.jpg
map_Bump normal.png
map_Ks specular.jpg

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

View File

@@ -1,3 +0,0 @@
Model by Berk Gedik, from: https://sketchfab.com/3d-models/survival-guitar-backpack-low-poly-799f8c4511f84fab8c3f12887f7e6b36
Modified material assignment (Joey de Vries) for easier load in OpenGL model loading chapter, and renamed albedo to diffuse and metallic to specular to match non-PBR lighting setup.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 MiB

12
resources/c4/C4Fixed.mtl Normal file
View File

@@ -0,0 +1,12 @@
# Blender 3.6.0 MTL File: 'None'
# www.blender.org
newmtl 01_-_Default.001
Ns 10.000005
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 1
map_Kd Corvette_C4_Base_Color.png

3095
resources/c4/C4Fixed.obj Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 MiB

View File

@@ -29,6 +29,7 @@ void main() {
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(-lightDirection);
vec3 viewDir = normalize(viewPosition - Position);
vec3 halfwayDir = normalize(lightDir + viewDir);
vec3 ambient = lightAmbient * (diffuseColor * phongAmbient);
@@ -37,9 +38,11 @@ void main() {
vec3 reflectDir = reflect(-lightDir, norm);
float effectiveShininess = max(phongShininess, 1.0);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), effectiveShininess);
float spec = pow(max(dot(norm, halfwayDir), 0.0), effectiveShininess);
vec3 specular = lightSpecular * (spec * specularColor * phongSpecular);
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
float gamma = 2.2;
FragColor.rgb = pow(result.rgb, vec3(1.0/gamma));
}

33
src/Components.h Normal file
View File

@@ -0,0 +1,33 @@
//
// Created by slinky on 5/7/26.
//
#ifndef B_ENGINE_COMPONENTS_H
#define B_ENGINE_COMPONENTS_H
#include <vector>
#include "Model.h"
#include "entt/entt.hpp"
#include "glm/glm.hpp"
namespace Components {
struct Transform {
glm::vec3 position;
glm::vec3 rotation;
glm::vec3 scale;
};
struct Relationship {
entt::entity entity;
std::vector<entt::entity> children;
};
struct Drawable {
std::shared_ptr<Model> model;
};
}
#endif //B_ENGINE_COMPONENTS_H

View File

@@ -7,15 +7,14 @@
bool InputManager::mouseInit = false;
float InputManager::lastMousePositionX = 0;
float InputManager::lastMousePositionY = 0;
std::unordered_map<std::string, std::unique_ptr<InputAction>> InputManager::registeredActions = {};
std::unordered_map<std::string, std::unique_ptr<InputAction>> registeredActions = {};
static bool currentKeyStatesData[512] = {};
bool* InputManager::currentKeyStates = currentKeyStatesData;
static bool previousKeyStatesData[512] = {};
bool* InputManager::previousKeyStates = previousKeyStatesData;
std::vector<MouseDeltaCallback> InputManager::mouse_listeners = {};
static std::vector<MouseDeltaCallback> mouse_listeners = {};
static void set_key_state(int key, bool state);
void InputManager::mouse_pos_callback(GLFWwindow *window, double x, double y) {
const auto xpos = static_cast<float>(x);
@@ -112,7 +111,7 @@ bool InputManager::key_held(int key) {
return previousKeyStatesData[key] && currentKeyStatesData[key];
}
void InputManager::set_key_state(int key, bool state) {
void set_key_state(int key, bool state) {
previousKeyStatesData[key] = currentKeyStatesData[key];
currentKeyStatesData[key] = state;
}

View File

@@ -36,11 +36,6 @@ public:
static float lastMousePositionX;
static float lastMousePositionY;
static bool* currentKeyStates;
static bool* previousKeyStates;
static std::unordered_map<std::string, std::unique_ptr<InputAction>> registeredActions;
static void mouse_pos_callback(GLFWwindow* window, double x, double y);
static void add_mouse_listener(MouseDeltaCallback callback);
@@ -53,9 +48,6 @@ public:
static bool key_released(int key);
static bool key_down(int key);
static bool key_up(int key);
private:
static std::vector<MouseDeltaCallback> mouse_listeners;
static void set_key_state(int key, bool state);
};
#endif //B_ENGINE_INPUTMANAGER_H

View File

@@ -1,5 +0,0 @@
//
// Created by lbmas on 4/28/2026.
//
#include "Model.h"

View File

@@ -5,17 +5,24 @@
#ifndef B_ENGINE_MODEL_H
#define B_ENGINE_MODEL_H
#include <string_view>
#include <vector>
#include <filesystem>
#include "Mesh.h"
#include "Material.h"
struct ModelNode {
glm::mat4 transform{};
std::vector<unsigned int> meshIndices{};
std::vector<ModelNode> children{};
};
struct Model
{
std::vector<std::shared_ptr<Mesh>> meshes;
std::vector<std::shared_ptr<Material>> materials;
std::vector<std::shared_ptr<Mesh>> meshes{};
std::vector<std::shared_ptr<Material>> materials{};
ModelNode root{};
};
#endif //B_ENGINE_MODEL_H

View File

@@ -17,10 +17,11 @@
std::unordered_map<std::string, std::shared_ptr<Model>> ModelManager::models;
void process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, glm::mat4 transform, Mesh& mesh);
void process_ai_node(aiNode* node, const aiScene* scene, glm::mat4 transform, Model* model);
void process_ai_node(aiNode* node, const aiScene* scene, glm::mat4 transform, ModelNode& model);
void process_ai_material(aiMaterial* aiMat, const aiScene* scene, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh);
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
@@ -38,7 +39,7 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
const aiScene* scene = importer.ReadFile(_path.data(),
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FlipUVs);
aiProcess_RemoveRedundantMaterials);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
@@ -48,14 +49,25 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
auto model = std::make_shared<Model>();
std::filesystem::path modelPath = {_path};
model->materials.resize(scene->mNumMaterials);
const std::filesystem::path modelPath = {_path};
for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
aiMaterial* aiMat = scene->mMaterials[i];
aiString matName;
if (aiMat->Get(AI_MATKEY_NAME, matName) && strcmp(matName.data, "DefaultMaterial") == 0) {
continue;
}
Material mat{};
process_ai_material(aiMat, scene, mat, modelPath.parent_path());
model->materials[i] = std::make_shared<Material>(mat);
process_ai_material(aiMat, mat, modelPath.parent_path());
model->materials.push_back(std::make_shared<Material>(mat));
}
model->meshes.resize(scene->mNumMeshes);
for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
aiMesh* aiMesh = scene->mMeshes[i];
Mesh mesh{};
mesh.materialId = aiMesh->mMaterialIndex;
process_ai_mesh(aiMesh, mesh);
model->meshes.push_back(std::make_shared<Mesh>(mesh));
}
auto transform = glm::identity<glm::mat4>();
@@ -63,32 +75,31 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
transform = zUpMatrix;
}
process_ai_node(scene->mRootNode, scene, transform, model.get());
process_ai_node(scene->mRootNode, scene, transform, model->root);
return model;
}
void process_ai_node(aiNode* node, const aiScene* scene, glm::mat4 transform, Model* model)
void process_ai_node(aiNode* aiNode, const aiScene* scene, glm::mat4 transform, ModelNode* node)
{
const auto t = node->mTransformation;
const auto t = aiNode->mTransformation;
transform = transform * glm::mat4(t.a1, t.a2, t.a3, t.a4, t.b1, t.b2, t.b3, t.b4, t.c1, t.c2, t.c3, t.c4, t.d1, t.d2, t.d3, t.d4);
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* aiMesh = scene->mMeshes[node->mMeshes[i]];
Mesh mesh{};
mesh.materialId = aiMesh->mMaterialIndex;
process_ai_mesh(aiMesh, scene, transform, mesh);
model->meshes.push_back(std::make_shared<Mesh>(mesh));
node->transform = transform;
for (unsigned int i = 0; i < aiNode->mNumMeshes; i++) {
node->meshIndices.push_back(aiNode->mMeshes[i]);
}
for (unsigned int i = 0; i < node->mNumChildren; i++)
for (unsigned int i = 0; i < aiNode->mNumChildren; i++)
{
process_ai_node(node->mChildren[i], scene, transform, model);
ModelNode newNode{};
process_ai_node(aiNode->mChildren[i], scene, transform, newNode);
node->children.push_back(newNode);
}
}
void process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, glm::mat4 transform, Mesh& mesh)
void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh)
{
auto positions = std::vector<float>(aiMesh->mNumVertices * 3);
auto uvs = std::vector<float>(aiMesh->mNumVertices * 2);
@@ -97,7 +108,7 @@ void process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, glm::mat4 transform,
for (unsigned int i = 0; i < aiMesh->mNumVertices; i++)
{
auto position = transform * glm::vec4(aiMesh->mVertices[i].x, aiMesh->mVertices[i].y, aiMesh->mVertices[i].z, 1.0f);
auto position = glm::vec4(aiMesh->mVertices[i].x, aiMesh->mVertices[i].y, aiMesh->mVertices[i].z, 1.0f);
positions[3 * i] = position.x;
positions[3 * i + 1] = position.y;
positions[3 * i + 2] = position.z;
@@ -138,7 +149,7 @@ void process_ai_mesh(aiMesh* aiMesh, const aiScene* scene, glm::mat4 transform,
mesh = {positions, uvs, normals, indices};
}
void process_ai_material(aiMaterial* aiMat, const aiScene* scene, Material& mat, const std::filesystem::path& modelDirectory) {
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
aiString matName;
aiReturn ret = aiMat->Get(AI_MATKEY_NAME, matName);
if (ret != AI_SUCCESS) {

10
src/Scene.cpp Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by slinky on 5/7/26.
//
#include "Scene.h"
entt::entity Scene::create_game_obejct() {
const entt::entity entity = _registry.create();
return entity;
}

20
src/Scene.h Normal file
View File

@@ -0,0 +1,20 @@
//
// Created by slinky on 5/7/26.
//
#ifndef B_ENGINE_SCENE_H
#define B_ENGINE_SCENE_H
#include "entt/entt.hpp"
class Scene {
public:
Scene() = default;
~Scene() = default;
entt::entity create_game_obejct();
private:
entt::registry _registry{};
};
#endif //B_ENGINE_SCENE_H

View File

@@ -7,6 +7,8 @@
#include "glm/ext/matrix_clip_space.hpp"
#include "glm/ext/matrix_transform.hpp"
#include "entt/entt.hpp"
#define STB_IMAGE_IMPLEMENTATION
#include "FreeCamera.h"
#include "InputManager.h"
@@ -32,6 +34,8 @@ float gMouseSensitivity = 0.1f;
FreeCamera gCamera {};
entt::registry gRegistry{};
void glfw_error_callback(int error, const char* description);
void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height);
@@ -42,6 +46,8 @@ void load_gl();
void init_camera();
void load_default_textures();
void load_shaders();
void load_inputs();
void load_default_models();
void loop();
std::shared_ptr<Model> load_model(std::string_view _path);
@@ -67,18 +73,9 @@ int main() {
load_shaders();
InputManager::generate_input_action("move_forward", {{GLFW_KEY_W, KEY_DOWN}});
InputManager::generate_input_action("move_backward", {{GLFW_KEY_S, KEY_DOWN}});
InputManager::generate_input_action("move_right", {{GLFW_KEY_D, KEY_DOWN}});
InputManager::generate_input_action("move_left", {{GLFW_KEY_A, KEY_DOWN}});
load_inputs();
InputManager::generate_input_action("exit_application", {{GLFW_KEY_ESCAPE, KEY_DOWN}});
spdlog::info("loading models");
ModelManager::models["cube"] = ModelManager::load_from_file("./resources/cube.obj");
ModelManager::models["backpack"] = ModelManager::load_from_file("./resources/backpack/backpack.obj");
ModelManager::models["male"] = ModelManager::load_from_file("./resources/male.obj");
spdlog::info("done");
load_default_models();
loop();
@@ -132,7 +129,9 @@ void create_main_window()
glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback);
#ifndef GLFW_CONTEXT_DEBUG
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
}
void load_gl()
@@ -183,19 +182,33 @@ void load_shaders() {
}
}
void load_inputs() {
InputManager::generate_input_action("move_forward", {{GLFW_KEY_W, KEY_DOWN}});
InputManager::generate_input_action("move_backward", {{GLFW_KEY_S, KEY_DOWN}});
InputManager::generate_input_action("move_right", {{GLFW_KEY_D, KEY_DOWN}});
InputManager::generate_input_action("move_left", {{GLFW_KEY_A, KEY_DOWN}});
InputManager::generate_input_action("move_up", {{GLFW_KEY_SPACE, KEY_DOWN}});
InputManager::generate_input_action("move_down", {{GLFW_KEY_LEFT_SHIFT, KEY_DOWN}});
InputManager::generate_input_action("exit_application", {{GLFW_KEY_ESCAPE, KEY_DOWN}});
}
void load_default_models() {
spdlog::info("loading default models");
ModelManager::models["cube"] = ModelManager::load_from_file("./resources/cube.obj");
ModelManager::models["vette"] = ModelManager::load_from_file("./resources/c4/C4Fixed.obj");
ModelManager::models["male"] = ModelManager::load_from_file("./resources/male.obj");
}
void loop() {
std::shared_ptr<Texture> defaultDiffuse = TextureManager::textures["default_diffuse"];
std::shared_ptr<Texture> defaultSpecular = TextureManager::textures["default_specular"];
std::shared_ptr<ShaderProgram> shader = ShaderManager::shaders["phong_shader"];
const auto vette = ModelManager::models["vette"];
auto model = glm::identity<glm::mat4>();
model = glm::scale(model, glm::vec3(.1f, .1f, .1f));
ShaderProgram* shader = ShaderManager::shaders["phong_shader"].get();
const auto cube = ModelManager::models["cube"];
const auto backpack = ModelManager::models["backpack"];
const auto male = ModelManager::models["male"];
const auto& activeModel = backpack;
const auto& activeModel = vette;
while (!glfwWindowShouldClose(gWindow)) {
glfwPollEvents();
@@ -222,6 +235,14 @@ void loop() {
gCamera.move(CAMERA_MOVEMENT::RIGHT, .05);
}
if (InputManager::check_action_performed("move_up")) {
gCamera.move(CAMERA_MOVEMENT::UP, .05);
}
if (InputManager::check_action_performed("move_down")) {
gCamera.move(CAMERA_MOVEMENT::DOWN, .05);
}
// gl frame prep
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -237,18 +258,18 @@ void loop() {
shader->setVec3("viewPosition", gCamera.position());
shader->setVec3("lightPosition", glm::vec3{-2.f, 0, 2.0f});
shader->setVec3("lightDirection", glm::vec3(1, -1, -1));
shader->setVec3("lightDirection", glm::vec3(1, -1, 1));
shader->setVec3("lightAmbient", glm::vec3(0.3f, 0.3f, 0.3f));
shader->setVec3("lightDiffuse", glm::vec3(0.5f, 0.5f, 0.5f));
shader->setVec3("lightSpecular", glm::vec3(1.0f, 1.0f, 1.0f));
for (const auto& mesh: activeModel->meshes) {
unsigned int materialId = mesh->materialId;
unsigned int materialId = 0;
if (materialId >= activeModel->materials.size()) {
materialId = 0;
}
const std::shared_ptr<Material> mat = activeModel->materials[1];
const std::shared_ptr<Material> mat = activeModel->materials[materialId];
shader->setVec3("phongAmbient", mat->phong.ambient);
shader->setVec3("phongDiffuse", mat->phong.diffuse);