diff options
author | Chuyan Zhang <me@zcy.moe> | 2024-10-04 22:43:11 -0700 |
---|---|---|
committer | Chuyan Zhang <me@zcy.moe> | 2024-10-04 22:43:11 -0700 |
commit | 1866dd531dffc4084dfaf261591bc7ac2a376d67 (patch) | |
tree | 55e6cbe7b54fc24fb80463f337a86089ef8b9bc3 | |
parent | d116dfacb8dc50ad9fb98d67d084d901ae95e456 (diff) | |
download | iris-1866dd531dffc4084dfaf261591bc7ac2a376d67.tar.gz iris-1866dd531dffc4084dfaf261591bc7ac2a376d67.zip |
add basic gltf loader
-rw-r--r-- | src/gltf_loader.cpp | 67 | ||||
-rw-r--r-- | src/render_assets.h | 34 | ||||
-rw-r--r-- | xmake.lua | 6 |
3 files changed, 84 insertions, 23 deletions
diff --git a/src/gltf_loader.cpp b/src/gltf_loader.cpp index 142b69f..bf64740 100644 --- a/src/gltf_loader.cpp +++ b/src/gltf_loader.cpp @@ -1,6 +1,6 @@ #include "gltf_loader.h" #include "spdlog/spdlog.h" -#include <concepts> +#include <cstdint> enum class SceneFileType { GLTF, @@ -79,6 +79,8 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { iris::Mesh iris_mesh { .name = mesh.name, .vertices = {}, + .normals = {}, + .texcoords = {}, .indices = {}, }; for (const auto &primitive : mesh.primitives) { @@ -87,7 +89,7 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { const auto &index_buffer = model.buffers[index_buffer_view.buffer]; const uint8_t *index_data_ptr = index_buffer.data.data() + index_buffer_view.byteOffset + index_accessor.byteOffset; - auto extract_index = [&index_data_ptr]<typename T>() -> T requires std::integral<T> { + auto extract = [&index_data_ptr]<typename T>() -> T { const T *index_data = reinterpret_cast<const T *>(index_data_ptr); index_data_ptr += sizeof(T); return *index_data; @@ -95,32 +97,32 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { switch (index_accessor.componentType) { case TINYGLTF_COMPONENT_TYPE_BYTE: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<int8_t>()); + iris_mesh.indices.push_back(extract.operator()<int8_t>()); } break; case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<uint8_t>()); + iris_mesh.indices.push_back(extract.operator()<uint8_t>()); } break; case TINYGLTF_COMPONENT_TYPE_SHORT: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<int16_t>()); + iris_mesh.indices.push_back(extract.operator()<int16_t>()); } break; case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<uint16_t>()); + iris_mesh.indices.push_back(extract.operator()<uint16_t>()); } break; case TINYGLTF_COMPONENT_TYPE_INT: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<int32_t>()); + iris_mesh.indices.push_back(extract.operator()<int32_t>()); } break; case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: for (size_t i = 0; i < index_accessor.count; i++) { - iris_mesh.indices.push_back(extract_index.operator()<uint32_t>()); + iris_mesh.indices.push_back(extract.operator()<uint32_t>()); } break; default: @@ -135,7 +137,12 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { const auto &accessor = model.accessors[accessor_index]; const auto &buffer_view = model.bufferViews[accessor.bufferView]; const auto &buffer = model.buffers[buffer_view.buffer]; - const float *data = reinterpret_cast<const float *>(buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset); + const uint8_t *data = buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset; + auto extract_data = [&data]<typename T>() -> T { + const T *typed_data = reinterpret_cast<const T *>(data); + data += sizeof(T); + return *typed_data; + }; // TODO: support other types. Currently only float3 is supported if (accessor.type != TINYGLTF_TYPE_VEC3 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { @@ -146,24 +153,20 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { // spdlog::info("attribute: {}, count: {}", attrib_name, accessor.count); if (attrib_name == "POSITION") { spdlog::info("loading POSITION, count {}", accessor.count); + iris_mesh.p_min = glm::vec3(accessor.minValues[0], accessor.minValues[1], accessor.minValues[2]); + iris_mesh.p_max = glm::vec3(accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2]); for (size_t i = 0; i < accessor.count; i++) { - iris_mesh.vertices.push_back(data[i * 3 + 0]); - iris_mesh.vertices.push_back(data[i * 3 + 1]); - iris_mesh.vertices.push_back(data[i * 3 + 2]); + iris_mesh.vertices.push_back(extract_data.operator()<glm::vec3>()); } } else if (attrib_name == "NORMAL") { spdlog::info("loading NORMAL, count {}", accessor.count); for (size_t i = 0; i < accessor.count; i++) { - iris_mesh.vertices.push_back(data[i * 3 + 0]); - iris_mesh.vertices.push_back(data[i * 3 + 1]); - iris_mesh.vertices.push_back(data[i * 3 + 2]); + iris_mesh.normals.push_back(extract_data.operator()<glm::vec3>()); } - // TODO reorder normals correctly } else if (attrib_name == "TEXCOORD_0") { spdlog::info("loading TEXCOORD_0, count {}", accessor.count); for (size_t i = 0; i < accessor.count; i++) { - iris_mesh.vertices.push_back(data[i * 2 + 0]); - iris_mesh.vertices.push_back(data[i * 2 + 1]); + iris_mesh.texcoords.push_back(extract_data.operator()<glm::vec2>()); } } else { spdlog::warn("Unsupported attribute: {}", attrib_name); @@ -179,5 +182,33 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { scene.meshes.push_back(iris_mesh); } + // TODO load materials and textures + + for (const tinygltf::Camera &camera : model.cameras) { + iris::Camera iris_camera { + .position = glm::vec3(0.0f), + .direction = glm::vec3(0.0f), + .up = glm::vec3(0.0f, 1.0f, 0.0f), + }; + spdlog::info("Camera: {}, type: {}", camera.name, camera.type); + if (camera.type == "perspective") { + const auto &perspective = camera.perspective; + iris_camera.intrinsic_tag = iris::Camera::Tag::Perspective; + iris_camera.intrinsic.perspective.fovx = 2 * glm::atan(glm::tan(perspective.yfov / 2) * perspective.aspectRatio); + iris_camera.intrinsic.perspective.fovy = perspective.yfov; + iris_camera.intrinsic.perspective.aspect = perspective.aspectRatio; + iris_camera.intrinsic.perspective.znear = perspective.znear; + iris_camera.intrinsic.perspective.zfar = perspective.zfar; + } else { + const auto &orthographic = camera.orthographic; + iris_camera.intrinsic_tag = iris::Camera::Tag::Orthographic; + iris_camera.intrinsic.orthographic.xmag = orthographic.xmag; + iris_camera.intrinsic.orthographic.ymag = orthographic.ymag; + iris_camera.intrinsic.orthographic.znear = orthographic.znear; + iris_camera.intrinsic.orthographic.zfar = orthographic.zfar; + } + scene.camera = iris_camera; + } + return true; }
\ No newline at end of file diff --git a/src/render_assets.h b/src/render_assets.h index 2dfff07..8c28ead 100644 --- a/src/render_assets.h +++ b/src/render_assets.h @@ -9,10 +9,14 @@ namespace iris { struct Mesh { std::string name; - std::vector<float> vertices; - std::vector<float> normals; - std::vector<float> texcoords; + std::vector<glm::vec3> vertices; + std::vector<glm::vec3> normals; + std::vector<glm::vec2> texcoords; std::vector<uint32_t> indices; + + // AABB + glm::vec3 p_min; + glm::vec3 p_max; }; struct Material { @@ -23,6 +27,28 @@ struct Texture { }; struct Camera { + enum struct Tag { + Perspective, + Orthographic, + } intrinsic_tag; + struct PerspectiveCamera { + float fovx; + float fovy; + float aspect; + float znear; + float zfar; + }; + + struct OrthographicCamera { + float xmag; + float ymag; + float znear; + float zfar; + }; + union { + PerspectiveCamera perspective; + OrthographicCamera orthographic; + } intrinsic; glm::vec3 position; glm::vec3 direction; glm::vec3 up; @@ -33,7 +59,7 @@ struct Scene { std::vector<Material> materials; std::vector<Texture> textures; - Camera camera_position; + Camera camera; }; } // namespace iris
\ No newline at end of file @@ -57,13 +57,17 @@ target("stb") set_kind("headeronly") add_includedirs(path.join(ext_dir, "stb"), {public = true}) +target("glm") + set_kind("headeronly") + add_includedirs(path.join(ext_dir, "glm"), {public = true}) + -- Main executable target target("iris_renderer") set_kind("binary") add_files(path.join(src_dir, "**.cpp")) -- Link external libraries - add_deps("argparse", "imgui", "tinygltf", "tinyobjloader", "stb") + add_deps("argparse", "imgui", "tinygltf", "tinyobjloader", "stb", "glm") -- Add libraries add_packages("vulkansdk", "glfw", "fmt", "vulkan-memory-allocator", "spdlog", "glm") |