mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(render): add model loading and rendering pipeline
This commit is contained in:
BIN
assets/model/creature/pig.glb
Normal file
BIN
assets/model/creature/pig.glb
Normal file
Binary file not shown.
15
assets/shaders/model_frag.glsl
Normal file
15
assets/shaders/model_frag.glsl
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 460
|
||||
|
||||
in vec2 tc;
|
||||
in vec3 normal;
|
||||
in vec3 vert_pos;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samp;
|
||||
|
||||
|
||||
void main() {
|
||||
color = texture(samp, tc);
|
||||
|
||||
}
|
||||
22
assets/shaders/model_vert.glsl
Normal file
22
assets/shaders/model_vert.glsl
Normal file
@@ -0,0 +1,22 @@
|
||||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 pos;
|
||||
layout (location = 1) in vec2 texCoord;
|
||||
layout (location = 2) in vec3 aNormal;
|
||||
|
||||
uniform mat4 mv_matrix;
|
||||
uniform mat4 proj_matrix;
|
||||
|
||||
out vec3 normal;
|
||||
out vec2 tc;
|
||||
out vec3 vert_pos;
|
||||
|
||||
|
||||
void main() {
|
||||
//vec4 worldPos = modelMatrix * vec4(pos, 1.0);
|
||||
vec4 viewPos = mv_matrix * vec4(pos, 1.0);
|
||||
tc = texCoord;
|
||||
vert_pos = pos;
|
||||
//normal = normalize(mat3(norm_matrix) * aNormal);
|
||||
gl_Position = proj_matrix * viewPos;
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Cubed/audio/audio_engine.hpp"
|
||||
#include "Cubed/config.hpp"
|
||||
#include "Cubed/dev_panel.hpp"
|
||||
#include "Cubed/render/model_manager.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/texture_manager.hpp"
|
||||
@@ -49,7 +50,7 @@ private:
|
||||
Window m_window;
|
||||
|
||||
TextureManager m_texture_manager;
|
||||
|
||||
ModelManager m_model_manager;
|
||||
AudioEngine m_audio;
|
||||
|
||||
Renderer m_renderer;
|
||||
|
||||
21
include/Cubed/render/model_manager.hpp
Normal file
21
include/Cubed/render/model_manager.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "Cubed/render/model_node.hpp"
|
||||
#include "Cubed/tools/model_loader.hpp"
|
||||
namespace Cubed {
|
||||
class ModelManager {
|
||||
public:
|
||||
ModelManager();
|
||||
ModelManager(const ModelManager&) = delete;
|
||||
ModelManager(ModelManager&&) = delete;
|
||||
ModelManager& operator=(const ModelManager&) = delete;
|
||||
ModelManager& operator=(ModelManager&&) = delete;
|
||||
~ModelManager();
|
||||
const ModelNode& get_model(const std::string& model_name);
|
||||
void init();
|
||||
|
||||
private:
|
||||
ModelLoader m_loader;
|
||||
std::unordered_map<std::string, ModelNode> m_models;
|
||||
const ModelNode& load_model(const std::string& model_name);
|
||||
};
|
||||
} // namespace Cubed
|
||||
42
include/Cubed/render/model_node.hpp
Normal file
42
include/Cubed/render/model_node.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/texture.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
#include "Cubed/render/vertex_buffer.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
|
||||
struct Mesh {
|
||||
std::vector<Vertex3D> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
std::unique_ptr<VertexBuffer> vbo;
|
||||
std::unique_ptr<VertexBuffer> ebo;
|
||||
std::unique_ptr<VertexArray> vao;
|
||||
std::unique_ptr<Texture> texture;
|
||||
void upload() {
|
||||
vao = std::make_unique<VertexArray>();
|
||||
vao->bind();
|
||||
vbo = std::make_unique<VertexBuffer>();
|
||||
vbo->buffer_data(vertices.data(), vertices.size() * sizeof(Vertex3D));
|
||||
ebo = std::make_unique<VertexBuffer>(BufferType::ELEMENT_ARRAY_BUFFER);
|
||||
ebo->buffer_data(indices.data(), indices.size() * sizeof(uint32_t));
|
||||
vao->attribute(0, 3, GL_FLOAT, sizeof(Vertex3D), (void*)0);
|
||||
vao->attribute(1, 2, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, s));
|
||||
vao->attribute(2, 3, GL_FLOAT, sizeof(Vertex3D),
|
||||
(void*)offsetof(Vertex3D, nx));
|
||||
};
|
||||
};
|
||||
struct ModelNode {
|
||||
std::string name;
|
||||
glm::mat4 transform{1.0f};
|
||||
std::vector<Mesh> meshes;
|
||||
std::vector<ModelNode> children;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
22
include/Cubed/render/model_renderer.hpp
Normal file
22
include/Cubed/render/model_renderer.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/render/model_node.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
namespace Cubed {
|
||||
class Renderer;
|
||||
class Camera;
|
||||
class ModelRender {
|
||||
public:
|
||||
ModelRender(Renderer& renderer);
|
||||
void render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera);
|
||||
|
||||
private:
|
||||
Renderer& m_renderer;
|
||||
void render_node(const ModelNode& node, const glm::mat4& parent,
|
||||
const glm::mat4& view, const Shader& shader);
|
||||
void render_mesh(const Mesh& mesh);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Cubed/constants.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/primitive_data.hpp"
|
||||
#include "Cubed/render/model_renderer.hpp"
|
||||
#include "Cubed/render/player_renderer.hpp"
|
||||
#include "Cubed/render/shader_manager.hpp"
|
||||
#include "Cubed/render/vertex_array.hpp"
|
||||
@@ -19,12 +20,14 @@
|
||||
namespace Cubed {
|
||||
class TextureManager;
|
||||
class ClientWorld;
|
||||
class ModelManager;
|
||||
class DevPanel;
|
||||
class Renderer {
|
||||
public:
|
||||
constexpr static int NUM_VAO = 7;
|
||||
|
||||
Renderer(TextureManager& texture_manager, Config& config);
|
||||
Renderer(TextureManager& texture_manager, Config& config,
|
||||
ModelManager& model_manager);
|
||||
~Renderer();
|
||||
void reload_config();
|
||||
void init();
|
||||
@@ -79,9 +82,14 @@ public:
|
||||
|
||||
bool handle_event(const Event& e);
|
||||
|
||||
void render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera);
|
||||
|
||||
ModelManager& model_manager();
|
||||
|
||||
private:
|
||||
TextureManager& m_texture_manager;
|
||||
|
||||
ModelManager& m_model_manager;
|
||||
bool m_init = false;
|
||||
|
||||
float m_aspect = 0.0f;
|
||||
@@ -118,6 +126,7 @@ private:
|
||||
std::vector<Vertex2D> m_ui;
|
||||
|
||||
WorldRenderer m_world_renderer;
|
||||
ModelRender m_model_renderer;
|
||||
Config& m_config;
|
||||
|
||||
bool handle_window_resize_event(const WindowResizeEvent& e);
|
||||
|
||||
@@ -38,9 +38,11 @@ enum TextureFormat : GLenum {
|
||||
R8 = GL_R8,
|
||||
RGB = GL_RGB,
|
||||
RGBA8 = GL_RGBA8,
|
||||
BGRA = GL_BGRA
|
||||
|
||||
};
|
||||
|
||||
// You need to set the texture scaling method, otherwise it will render as
|
||||
// black.
|
||||
class Texture {
|
||||
public:
|
||||
explicit Texture(TextureType type);
|
||||
|
||||
22
include/Cubed/tools/model_loader.hpp
Normal file
22
include/Cubed/tools/model_loader.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Cubed/render/model_node.hpp"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
namespace Cubed {
|
||||
|
||||
class ModelLoader {
|
||||
public:
|
||||
ModelLoader();
|
||||
ModelNode load(const std::string& path);
|
||||
|
||||
private:
|
||||
Assimp::Importer m_importer;
|
||||
ModelNode process_node(aiNode* node, const aiScene* scene);
|
||||
Mesh process_mesh(aiMesh* mesh, const aiScene* scene);
|
||||
bool process_texture(Mesh& mesh, aiMaterial* material, const aiScene* scene,
|
||||
aiTextureType type);
|
||||
glm::mat4 convert_matrix(const aiMatrix4x4& matrix);
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -47,7 +47,7 @@ bool check_opengl_error();
|
||||
std::string read_shader_source(const std::string& file_path);
|
||||
|
||||
ImageData load_image_data(const std::string& tex_image_path,
|
||||
bool check_exist = true);
|
||||
bool check_exist = true, bool full_path = false);
|
||||
|
||||
} // namespace Tools
|
||||
|
||||
|
||||
@@ -92,4 +92,7 @@ target_sources(${PROJECT_NAME}
|
||||
ui/row_layout.cpp
|
||||
ui/item_slot.cpp
|
||||
ui/inventory_ui.cpp
|
||||
tools/model_loader.cpp
|
||||
render/model_manager.cpp
|
||||
render/model_renderer.cpp
|
||||
)
|
||||
@@ -20,7 +20,8 @@ App::App()
|
||||
|
||||
: m_game_config(ASSETS_PATH "config.toml"), m_window(m_game_config),
|
||||
m_texture_manager(m_game_config), m_audio(m_game_config),
|
||||
m_renderer(m_texture_manager, m_game_config), m_scene_manager(*this) {}
|
||||
m_renderer(m_texture_manager, m_game_config, m_model_manager),
|
||||
m_scene_manager(*this) {}
|
||||
|
||||
App::~App() {
|
||||
stop_text_input();
|
||||
@@ -85,6 +86,7 @@ void App::init(int argc, char** argv) {
|
||||
Logger::info("Renderer Init Success");
|
||||
// MapTable::init_map();
|
||||
m_texture_manager.init_texture();
|
||||
m_model_manager.init();
|
||||
Logger::info("Texture Load Success");
|
||||
|
||||
m_scene_manager.request_push(SceneType::MAIN_MENU);
|
||||
|
||||
32
src/render/model_manager.cpp
Normal file
32
src/render/model_manager.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "Cubed/render/model_manager.hpp"
|
||||
|
||||
#include "Cubed/tools/log.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
ModelManager::ModelManager() {}
|
||||
|
||||
ModelManager::~ModelManager() {}
|
||||
|
||||
void ModelManager::init() {
|
||||
|
||||
};
|
||||
|
||||
const ModelNode& ModelManager::get_model(const std::string& model_name) {
|
||||
auto it = m_models.find(model_name);
|
||||
if (it == m_models.end()) {
|
||||
return load_model(model_name);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const ModelNode& ModelManager::load_model(const std::string& model_name) {
|
||||
std::string path = ASSETS_PATH + model_name;
|
||||
auto model = m_loader.load(path);
|
||||
auto [it, instert] = m_models.try_emplace(model_name, std::move(model));
|
||||
if (!instert) {
|
||||
Logger::error("Model Key {} already exist!", model_name);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
48
src/render/model_renderer.cpp
Normal file
48
src/render/model_renderer.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "Cubed/render/model_renderer.hpp"
|
||||
|
||||
#include "Cubed/camera.hpp"
|
||||
#include "Cubed/render/model_manager.hpp"
|
||||
#include "Cubed/render/renderer.hpp"
|
||||
namespace Cubed {
|
||||
ModelRender::ModelRender(Renderer& renderer) : m_renderer(renderer) {}
|
||||
|
||||
void ModelRender::render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera) {
|
||||
auto& model_manager = m_renderer.model_manager();
|
||||
auto& root = model_manager.get_model(name);
|
||||
glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos);
|
||||
auto& shader = m_renderer.get_shader("model_shader");
|
||||
glm::mat4 view = camera.get_camera_lookat();
|
||||
shader.use();
|
||||
shader.set_loc("proj_matrix", m_renderer.p_mat());
|
||||
render_node(root, transform, view, shader);
|
||||
}
|
||||
|
||||
void ModelRender::render_node(const ModelNode& node, const glm::mat4& parent,
|
||||
const glm::mat4& view, const Shader& shader) {
|
||||
|
||||
glm::mat4 transform = parent * node.transform;
|
||||
|
||||
shader.set_loc("mv_matrix", view * transform);
|
||||
for (auto& mesh : node.meshes) {
|
||||
render_mesh(mesh);
|
||||
}
|
||||
|
||||
for (auto& child : node.children) {
|
||||
render_node(child, transform, view, shader);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelRender::render_mesh(const Mesh& mesh) {
|
||||
mesh.vao->bind();
|
||||
if (mesh.texture) {
|
||||
mesh.texture->bind(0);
|
||||
} else {
|
||||
Logger::error("Model Texture Not Find");
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()),
|
||||
GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -15,9 +15,10 @@
|
||||
|
||||
namespace Cubed {
|
||||
|
||||
Renderer::Renderer(TextureManager& texture_manager, Config& config)
|
||||
: m_texture_manager(texture_manager), m_world_renderer(*this),
|
||||
m_config(config) {}
|
||||
Renderer::Renderer(TextureManager& texture_manager, Config& config,
|
||||
ModelManager& model_manager)
|
||||
: m_texture_manager(texture_manager), m_model_manager(model_manager),
|
||||
m_world_renderer(*this), m_model_renderer(*this), m_config(config) {}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
if (m_init) {
|
||||
@@ -249,6 +250,12 @@ void Renderer::render_dev_panel(DevPanel& dev_panel) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Renderer::render_model(const std::string& name, const glm::vec3& pos,
|
||||
Camera& camera) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
m_model_renderer.render_model(name, pos, camera);
|
||||
}
|
||||
|
||||
bool Renderer::handle_event(const Event& e) {
|
||||
return std::visit(Overloaded{[](const MouseMoveEvent&) { return false; },
|
||||
[](const MouseButtonEvent&) { return false; },
|
||||
@@ -340,4 +347,5 @@ float Renderer::frame_height() const { return m_frame_height; }
|
||||
float Renderer::frame_width() const { return m_frame_width; }
|
||||
const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; }
|
||||
const std::vector<VertexArray>& Renderer::vao() const { return m_vao; }
|
||||
ModelManager& Renderer::model_manager() { return m_model_manager; }
|
||||
} // namespace Cubed
|
||||
@@ -35,6 +35,8 @@ void ShaderManager::init() {
|
||||
"shaders/depth_player_fragment_shader.glsl");
|
||||
register_shader("rect", "shaders/rect_v_shader.glsl",
|
||||
"shaders/rect_f_shader.glsl");
|
||||
register_shader("model_shader", "shaders/model_vert.glsl",
|
||||
"shaders/model_frag.glsl");
|
||||
}
|
||||
|
||||
void ShaderManager::register_shader(const std::string& name,
|
||||
|
||||
@@ -65,6 +65,7 @@ void WorldScene::render(Renderer& renderer) {
|
||||
return;
|
||||
}
|
||||
renderer.render_world(m_client_world);
|
||||
renderer.render_model("model/creature/pig.glb", {0, 100, 0}, m_camera);
|
||||
if (m_show_hud) {
|
||||
m_hud_ui.render(renderer);
|
||||
}
|
||||
|
||||
124
src/tools/model_loader.cpp
Normal file
124
src/tools/model_loader.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "Cubed/tools/model_loader.hpp"
|
||||
|
||||
#include "Cubed/tools/cubed_assert.hpp"
|
||||
#include "Cubed/tools/log.hpp"
|
||||
#include "Cubed/tools/shader_tools.hpp"
|
||||
|
||||
#include <assimp/postprocess.h>
|
||||
#include <stb_image.h>
|
||||
namespace Cubed {
|
||||
ModelLoader::ModelLoader() {}
|
||||
|
||||
ModelNode ModelLoader::load(const std::string& path) {
|
||||
const aiScene* scene = m_importer.ReadFile(
|
||||
path, aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_FlipUVs |
|
||||
aiProcess_JoinIdenticalVertices |
|
||||
aiProcess_ImproveCacheLocality);
|
||||
if (!scene || !scene->mRootNode) {
|
||||
Logger::error("Load Model {} Error: {}", path,
|
||||
m_importer.GetErrorString());
|
||||
return {};
|
||||
}
|
||||
return process_node(scene->mRootNode, scene);
|
||||
}
|
||||
ModelNode ModelLoader::process_node(aiNode* node, const aiScene* scene) {
|
||||
ModelNode result;
|
||||
result.name = node->mName.C_Str();
|
||||
result.transform = convert_matrix(node->mTransformation);
|
||||
|
||||
for (unsigned i = 0; i < node->mNumMeshes; ++i) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
result.meshes.emplace_back(process_mesh(mesh, scene));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < node->mNumChildren; ++i) {
|
||||
result.children.emplace_back(process_node(node->mChildren[i], scene));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Mesh ModelLoader::process_mesh(aiMesh* mesh, const aiScene* scene) {
|
||||
Mesh result;
|
||||
for (unsigned i = 0; i < mesh->mNumVertices; ++i) {
|
||||
Vertex3D v{};
|
||||
v.x = mesh->mVertices[i].x;
|
||||
v.y = mesh->mVertices[i].y;
|
||||
v.z = mesh->mVertices[i].z;
|
||||
if (mesh->HasTextureCoords(0)) {
|
||||
v.s = mesh->mTextureCoords[0][i].x;
|
||||
v.t = mesh->mTextureCoords[0][i].y;
|
||||
}
|
||||
if (mesh->HasNormals()) {
|
||||
v.nx = mesh->mNormals[i].x;
|
||||
v.ny = mesh->mNormals[i].y;
|
||||
v.nz = mesh->mNormals[i].z;
|
||||
} else {
|
||||
Logger::warn("Model Does not have Normals!");
|
||||
}
|
||||
result.vertices.emplace_back(v);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < mesh->mNumFaces; ++i) {
|
||||
aiFace face = mesh->mFaces[i];
|
||||
|
||||
for (unsigned j = 0; j < face.mNumIndices; ++j) {
|
||||
result.indices.emplace_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
if (!process_texture(result, material, scene, aiTextureType_BASE_COLOR)) {
|
||||
if (!process_texture(result, material, scene, aiTextureType_DIFFUSE)) {
|
||||
if (!process_texture(result, material, scene,
|
||||
aiTextureType_UNKNOWN)) {
|
||||
Logger::error("Can't Load model texture");
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.upload();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ModelLoader::process_texture(Mesh& mesh, aiMaterial* material,
|
||||
const aiScene* scene, aiTextureType type) {
|
||||
aiString texture_path;
|
||||
if (material->GetTexture(type, 0, &texture_path) != AI_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
mesh.texture = std::make_unique<Texture>(TextureType::TEXTURE_2D);
|
||||
if (texture_path.C_Str()[0] == '*') {
|
||||
int index = std::stoi(texture_path.C_Str() + 1);
|
||||
aiTexture* texture = scene->mTextures[index];
|
||||
if (texture->mHeight == 0) {
|
||||
int width, height, channels;
|
||||
|
||||
unsigned char* data = stbi_load_from_memory(
|
||||
reinterpret_cast<unsigned char*>(texture->pcData),
|
||||
texture->mWidth, &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
mesh.texture->tex_image_2d(RGBA, RGBA, GL_UNSIGNED_BYTE, data,
|
||||
width, height);
|
||||
stbi_image_free(data);
|
||||
} else {
|
||||
mesh.texture->tex_image_2d(RGBA, BGRA, GL_UNSIGNED_BYTE,
|
||||
reinterpret_cast<char*>(texture->pcData),
|
||||
texture->mWidth, texture->mHeight);
|
||||
}
|
||||
} else {
|
||||
auto image_data =
|
||||
Tools::load_image_data(texture_path.C_Str(), true, true);
|
||||
|
||||
mesh.texture->tex_image_2d(RGBA, RGBA, GL_UNSIGNED_BYTE,
|
||||
image_data.data, image_data.width,
|
||||
image_data.height);
|
||||
}
|
||||
mesh.texture->set_nearest();
|
||||
return true;
|
||||
}
|
||||
|
||||
glm::mat4 ModelLoader::convert_matrix(const aiMatrix4x4& m) {
|
||||
return glm::mat4(m.a1, m.b1, m.c1, m.d1, m.a2, m.b2, m.c2, m.d2, m.a3, m.b3,
|
||||
m.c3, m.d3, m.a4, m.b4, m.c4, m.d4);
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -175,8 +175,14 @@ void delete_image_data(unsigned char* data) {
|
||||
stbi_image_free(data);
|
||||
}
|
||||
|
||||
ImageData load_image_data(const std::string& tex_image_path, bool check_exist) {
|
||||
fs::path path = ASSETS_PATH + tex_image_path;
|
||||
ImageData load_image_data(const std::string& tex_image_path, bool check_exist,
|
||||
bool full_path) {
|
||||
fs::path path;
|
||||
if (full_path) {
|
||||
path = tex_image_path;
|
||||
} else {
|
||||
path = ASSETS_PATH + tex_image_path;
|
||||
}
|
||||
if (check_exist) {
|
||||
ASSERT_MSG(fs::is_regular_file(path), path.c_str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user