diff --git a/src/inferno/application.cpp b/src/inferno/application.cpp index f358d93..cea36fe 100644 --- a/src/inferno/application.cpp +++ b/src/inferno/application.cpp @@ -16,8 +16,6 @@ #include "inferno/event/event.h" #include "inferno/event/keyevent.h" #include "inferno/event/mouseevent.h" -// #include "inferno/io/gltffile.h" -#include "inferno/asset/font.h" #include "inferno/io/input.h" #include "inferno/keycodes.h" #include "inferno/render/buffer.h" @@ -55,8 +53,6 @@ Application::Application() m_scene = std::make_shared(); m_scene->initialize(); - // Load assets - // m_font = FontManager::the().load("assets/fnt/dejavu-sans"); // auto bla = GlTFFile::read("assets/gltf/box.glb"); @@ -145,12 +141,13 @@ int Application::run() // offset #endif + // m_window->setVSync(false); while (!m_window->shouldClose()) { float time = Time::time(); float deltaTime = time - m_lastFrameTime; m_lastFrameTime = time; - // ruc::debug("Frametime " << deltaTime * 1000 << "ms"); + // ruc::debug("Frametime {}ms", deltaTime * 1000); // Update diff --git a/src/inferno/application.h b/src/inferno/application.h index 7578281..489f2e7 100644 --- a/src/inferno/application.h +++ b/src/inferno/application.h @@ -8,8 +8,6 @@ #include // std::unique_ptr, std::shared_ptr -#include "ruc/singleton.h" - namespace Inferno { class Event; diff --git a/src/inferno/asset/model.cpp b/src/inferno/asset/model.cpp index f71abf1..8af3f1a 100644 --- a/src/inferno/asset/model.cpp +++ b/src/inferno/asset/model.cpp @@ -8,10 +8,10 @@ #include // std::shared_ptr #include "assimp/Importer.hpp" +#include "assimp/mesh.h" #include "assimp/postprocess.h" #include "assimp/scene.h" #include "assimp/texture.h" -#include "ruc/format/log.h" #include "inferno/asset/model.h" #include "inferno/asset/texture.h" @@ -23,6 +23,7 @@ std::shared_ptr Model::create(std::string_view path) auto result = std::shared_ptr(new Model(path)); Assimp::Importer importer; // importer destructor uses RAII cleanup + importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE); const aiScene* scene = importer.ReadFile( path.data(), aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); @@ -51,7 +52,7 @@ void Model::processNode(std::shared_ptr model, aiNode* node, const aiScen { for (uint32_t i = 0; i < node->mNumMeshes; ++i) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - processMesh(model, mesh, scene); + processMesh(model, mesh, scene, node->mTransformation); } for (uint32_t i = 0; i < node->mNumChildren; ++i) { @@ -59,52 +60,51 @@ void Model::processNode(std::shared_ptr model, aiNode* node, const aiScen } } -void Model::processMesh(std::shared_ptr model, aiMesh* mesh, const aiScene* scene) +void Model::processMesh(std::shared_ptr model, aiMesh* mesh, const aiScene* scene, aiMatrix4x4 parentTransform) { VERIFY(mesh->HasPositions(), "malformed model"); VERIFY(mesh->HasNormals(), "malformed model"); // Pre-allocate memory - model->m_vertices = std::vector(mesh->mNumVertices); + size_t startIndex = model->m_vertices.size(); + model->m_vertices.resize(startIndex + mesh->mNumVertices); for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D v = mesh->mVertices[i]; - model->m_vertices[i].position = { v.x, v.y, v.z }; + aiVector3D v = parentTransform * mesh->mVertices[i]; + model->m_vertices[startIndex + i].position = { v.x, v.y, v.z }; } // Size of vertices == size of normals for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D normal = mesh->mNormals[i]; - model->m_vertices[i].normal = { normal.x, normal.y, normal.x }; + aiVector3D normal = mesh->mNormals[startIndex + i]; + model->m_vertices[startIndex + i].normal = { normal.x, normal.y, normal.z }; } if (mesh->HasTextureCoords(0)) { // Size of vertices == size of texture coordinates for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { aiVector3D tc = mesh->mTextureCoords[0][i]; - model->m_vertices[i].textureCoordinates = { tc.x, tc.y }; + model->m_vertices[startIndex + i].textureCoordinates = { tc.x, tc.y }; } } // TODO: position in the texture atlas if (mesh->HasFaces()) { + // Pre-allocate memory + size_t startIndex2 = model->m_elements.size(); + model->m_elements.resize(startIndex2 + (mesh->mNumFaces * 3)); // assuming triangles + + size_t offset = 0; for (uint32_t i = 0; i < mesh->mNumFaces; ++i) { aiFace face = mesh->mFaces[i]; - for (uint32_t j = 0; j < face.mNumIndices; ++j) { - model->m_elements.push_back(face.mIndices[j]); + VERIFY(face.mNumIndices == 3, "unsupported face type: {}", face.mNumIndices); + for (uint32_t j = 0; j < face.mNumIndices; ++j, ++offset) { + // Indices are referenced relative to vertices[0], if there are multiple meshes, + // then the indices need to be offset by the total amount of vertices + model->m_elements[startIndex2 + (i * 3) + j] = startIndex + face.mIndices[j]; } } } - - ruc::debug("mesh: {:p}", mesh->mTextureCoordsNames); - // for (size_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - // ruc::debug("mesh: {}", mesh->mTextureCoordsNames[i]); - // } - - ruc::debug("has texture: {}", scene->HasTextures()); - - ruc::error("asset::model vert {}", model->m_vertices.size()); - ruc::error("asset::model elem {}", model->m_elements.size()); } } // namespace Inferno diff --git a/src/inferno/asset/model.h b/src/inferno/asset/model.h index 46cfd9b..301cefa 100644 --- a/src/inferno/asset/model.h +++ b/src/inferno/asset/model.h @@ -39,7 +39,7 @@ private: static void processScene(std::shared_ptr model, const aiScene* scene); static void processNode(std::shared_ptr model, aiNode* node, const aiScene* scene); - static void processMesh(std::shared_ptr model, aiMesh* mesh, const aiScene* scene); + static void processMesh(std::shared_ptr model, aiMesh* mesh, const aiScene* scene, aiMatrix4x4 parentTransform = aiMatrix4x4()); virtual bool isModel() const override { return true; } @@ -50,4 +50,11 @@ private: std::shared_ptr m_texture; }; +// clang-format off +template<> +inline bool Asset::fastIs() const { return isModel(); } +// clang-format on + } // namespace Inferno + +// TODO: figure out this weird thing: https://github.com/assimp/assimp/blob/master/BUILDBINARIES_EXAMPLE.bat#L6-L10 diff --git a/src/inferno/component/model-component.cpp b/src/inferno/component/model-component.cpp index 870c3c0..04d593d 100644 --- a/src/inferno/component/model-component.cpp +++ b/src/inferno/component/model-component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Riyyi + * Copyright (C) 2022 Riyyi * * SPDX-License-Identifier: MIT */ diff --git a/src/inferno/component/model-component.h b/src/inferno/component/model-component.h index ea4cf78..b7f1605 100644 --- a/src/inferno/component/model-component.h +++ b/src/inferno/component/model-component.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Riyyi + * Copyright (C) 2022 Riyyi * * SPDX-License-Identifier: MIT */ diff --git a/src/inferno/render/gltf.cpp b/src/inferno/render/gltf.cpp deleted file mode 100644 index 8de44ed..0000000 --- a/src/inferno/render/gltf.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2022 Riyyi - * - * SPDX-License-Identifier: MIT - */ - -#if 0 - #include // std::copy - #include // std::move - - #include "nlohmann/json.hpp" - #include "ruc/meta/assert.h" - - #include "inferno/io/file.h" - #include "inferno/io/gltffile.h" - #include "inferno/io/log.h" - #include "inferno/render/gltf.h" - #include "inferno/util/integer.h" - -namespace Inferno { - - Gltf::Gltf(const std::string& path) - : m_path(std::move(path)) - { - auto gltf = GltfFile::read(path); - VERIFY(gltf.first, "Gltf model invalid JSON content '{}'", path); - - json json = json::parse(gltf.first.get()); - - // Add binary data from .glb files - if (gltf.second) { - m_model.data.emplace(0, std::move(gltf.second)); - } - - // Properties - - // Asset - // --------------------------------- - - VERIFY(Json::hasProperty(json, "asset"), "GlTF model missing required property 'asset'"); - auto asset = json["asset"]; - VERIFY(asset.is_object(), "Gltf model invalid property type 'asset'"); - - parseAsset(&m_model.asset, asset); - - // Scene - // --------------------------------- - - if (Json::hasProperty(json, "scenes")) { - - auto scenes = json["scenes"]; - VERIFY(scenes.is_array(), "Gltf model invalid property type 'scenes'"); - - for (auto& [key, object] : scenes.items()) { - glTF::Scene scene; - parseScene(&scene, key, object); - m_model.scenes.emplace_back(std::move(scene)); - } - } - - // Node - // --------------------------------- - - if (Json::hasProperty(json, "nodes")) { - - auto nodes = json["nodes"]; - VERIFY(nodes.is_array(), "Gltf model invalid property type 'nodes'"); - - for (auto& [key, object] : nodes.items()) { - glTF::Node node; - parseNode(&node, key, object); - m_model.nodes.emplace_back(std::move(node)); - } - } - - // Mesh - // --------------------------------- - - if (Json::hasProperty(json, "meshes")) { - - auto meshes = json["meshes"]; - VERIFY(meshes.is_array(), "Gltf model invalid property type 'meshes'"); - - for (auto& [key, object] : meshes.items()) { - glTF::Mesh mesh; - parseMesh(&mesh, key, object); - m_model.meshes.emplace_back(std::move(mesh)); - } - } - - // Accessor - // --------------------------------- - - if (Json::hasProperty(json, "accessors")) { - - auto accessors = json["accessors"]; - VERIFY(accessors.is_array(), "Gltf model invalid property type 'accessors'"); - - for (auto& [key, object] : accessors.items()) { - glTF::Accessor accessor; - parseAccessor(&accessor, key, object); - m_model.accessors.emplace_back(std::move(accessor)); - } - } - - // Bufferview - // --------------------------------- - - if (Json::hasProperty(json, "bufferViews")) { - - auto bufferViews = json["bufferViews"]; - VERIFY(bufferViews.is_array(), "Gltf model invalid property type 'bufferViews'"); - - for (auto& [key, object] : bufferViews.items()) { - glTF::BufferView bufferView; - parseBufferView(&bufferView, key, object); - m_model.bufferViews.emplace_back(std::move(bufferView)); - } - } - - // Buffer - // --------------------------------- - - if (Json::hasProperty(json, "buffers")) { - - auto buffers = json["buffers"]; - VERIFY(buffers.is_array(), "Gltf model invalid property type 'buffers'"); - - for (auto& [key, object] : buffers.items()) { - glTF::Buffer buffer; - parseBuffer(&buffer, key, object, &m_model.data); - m_model.buffers.emplace_back(std::move(buffer)); - } - } - - } - - Gltf::~Gltf() - { - } - - void Gltf::parseAsset(glTF::Asset* asset, const json& object) - { - auto copyright = Json::parseStringProperty(object, "copyright", false); - - auto generator = Json::parseStringProperty(object, "generator", false); - - auto version = Json::parseStringProperty(object, "version", true); - VERIFY(version, "GlTF model missing required property 'version'"); - VERIFY(version.value().compare("2.0") == 0, "GlTF version unsupported '{}'", version.value()); - - auto minVersion = Json::parseStringProperty(object, "minVersion", false); - - if (copyright) asset->copyright = copyright.value(); - if (generator) asset->generator = generator.value(); - if (version) asset->version = version.value(); - if (minVersion) asset->minVersion = minVersion.value(); - } - - void Gltf::parseScene(glTF::Scene* scene, const std::string& key, const json& object) - { - auto nodes = Json::parseFloatArrayProperty(object, "nodes", false); - VERIFY(!nodes || nodes.value().size() > 0, "Gltf scene '{}' empty 'nodes' property", key); - - auto name = Json::parseStringProperty(object, "name", false); - - scene->name = name ? name.value() : key; - } - - void Gltf::parseNode(glTF::Node* node, const std::string& key, const json& object) - { - auto camera = Json::parseUnsignedProperty(object, "camera", false); - - auto children = Json::parseUnsignedArrayProperty(object, "children", false); - VERIFY(!children || children.value().size() > 0, "Gltf node '{}' empty property 'children'", key); - - auto skin = Json::parseUnsignedProperty(object, "skin", false); - - auto matrix = Json::parseFloatArrayProperty(object, "matrix", false); - VERIFY(!matrix || matrix.value().size() == 16, "Gltf node '{}' property 'matrix' invalid size", key); - - auto mesh = Json::parseUnsignedProperty(object, "mesh", false); - - auto rotation = Json::parseFloatArrayProperty(object, "rotation", false); - VERIFY(!rotation || rotation.value().size() == 4, "Gltf node '{}' property 'rotation' invalid size", key); - - auto scale = Json::parseFloatArrayProperty(object, "scale", false); - VERIFY(!scale || scale.value().size() == 3, "Gltf node '{}' property 'scale' invalid size", key); - - auto translation = Json::parseFloatArrayProperty(object, "translation", false); - VERIFY(!translation || translation.value().size() == 3, "Gltf node '{}' property 'translation' invalid size", key); - - auto weights = Json::parseFloatArrayProperty(object, "weights", false); - VERIFY(!weights || weights.value().size() > 0, "Gltf node '{}' empty property 'weights'", key); - - auto name = Json::parseStringProperty(object, "name", false); - - if (camera) node->camera = camera.value(); - if (children) node->children = children.value(); - if (skin) node->skin = skin.value(); - if (matrix) std::copy(matrix.value().begin(), matrix.value().end(), node->matrix.begin()); - if (mesh) node->mesh = mesh.value(); - if (rotation) std::copy(rotation.value().begin(), rotation.value().end(), node->rotation.begin()); - if (scale) std::copy(scale.value().begin(), scale.value().end(), node->scale.begin()); - if (translation) std::copy(translation.value().begin(), translation.value().end(), node->translation.begin()); - if (weights) node->weights = weights.value(); - node->name = name ? name.value() : key; - } - - void Gltf::parsePrimitive(glTF::Primitive* primitive, const std::string& key, const json& object) - { - auto attributes = Json::parseUnsignedObjectProperty(object, "attributes", true); - VERIFY(attributes && attributes.value().size() > 0, "Gltf primitive '{}' empty property 'attributes'", key); - - auto indices = Json::parseUnsignedProperty(object, "indices", false); - - auto material = Json::parseUnsignedProperty(object, "material", false); - - auto mode = Json::parseUnsignedProperty(object, "mode", false); - - if (Json::hasProperty(object, "targets")) { - - auto targets = object["targets"]; - VERIFY(targets.is_array(), "Gltf primitive '{}' property 'targets' invalid type", key); - - for (auto& targetObject : targets) { - - std::map target; - - for (auto& [key, propertyValue] : targetObject.items()) { - auto value = Json::getPropertyValue(propertyValue, json::value_t::number_unsigned); - if (value) target.emplace(std::move(key), value.value()); - } - - VERIFY(target.size() > 0, "Gltf primitive '{}' empty 'target' object", key); - primitive->targets.emplace_back(std::move(target)); - } - } - - if (attributes) primitive->attributes = attributes.value(); - if (indices) primitive->indices = indices.value(); - if (material) primitive->material = material.value(); - if (mode) primitive->mode = static_cast(mode.value()); - } - - void Gltf::parseMesh(glTF::Mesh* mesh, const std::string& key, const json& object) - { - VERIFY(Json::hasProperty(object, "primitives"), "Gltf mesh '{}' missing required property 'primitives'", key); - auto primitives = object["primitives"]; - VERIFY(primitives.is_array(), "Gltf mesh '{}' property 'primitives' invalid type", key); - - for (auto& primitiveObject : primitives) { - glTF::Primitive primitive; - parsePrimitive(&primitive, key, primitiveObject); - mesh->primitives.emplace_back(std::move(primitive)); - } - - auto weights = Json::parseFloatArrayProperty(object, "weights", false); - VERIFY(!weights || weights.value().size() > 0, "Gltf mesh '{}' empty property 'weights'", key); - - auto name = Json::parseStringProperty(object, "name", false); - - if (weights) mesh->weights = weights.value(); - mesh->name = name ? name.value() : key; - } - - void Gltf::parseAccessor(glTF::Accessor* accessor, const std::string& key, const json& object) - { - auto bufferView = Json::parseUnsignedProperty(object, "bufferView", false); - - auto byteOffset = Json::parseUnsignedProperty(object, "byteOffset", false); - - auto componentType = Json::parseUnsignedProperty(object, "componentType", true); - VERIFY(componentType, "Gltf accessor '{}' missing required property 'componentType'", key); - - auto normalized = Json::parseBoolProperty(object, "normalized", false); - - auto count = Json::parseUnsignedProperty(object, "count", true); - VERIFY(count, "Gltf accessor '{}' missing required property 'count'", key); - - auto type = Json::parseStringProperty(object, "type", true); - VERIFY(type, "Gltf accessor '{}' missing required property 'type'", key); - - auto max = Json::parseFloatArrayProperty(object, "max", false); - VERIFY(!max || max.value().size() > 0, "Gltf accessor '{}' empty property 'max'", key); - - auto min = Json::parseFloatArrayProperty(object, "min", false); - VERIFY(!min || min.value().size() > 0, "Gltf accessor '{}' empty property 'min'", key); - - auto name = Json::parseStringProperty(object, "name", false); - - if (bufferView) accessor->bufferView = bufferView.value(); - if (byteOffset) accessor->byteOffset = byteOffset.value(); - if (normalized) accessor->normalized = normalized.value(); - if (count) accessor->count = count.value(); - if (type) accessor->type = type.value(); - if (max) accessor->max = max.value(); - if (min) accessor->min = min.value(); - accessor->name = name ? name.value() : key; - } - - void Gltf::parseBufferView(glTF::BufferView* bufferView, const std::string& key, const json& object) - { - auto buffer = Json::parseUnsignedProperty(object, "buffer", false); - VERIFY(buffer, "Gltf bufferView '{}' missing required property 'buffer'", key); - - auto byteOffset = Json::parseUnsignedProperty(object, "byteOffset", false); - - auto byteLength = Json::parseUnsignedProperty(object, "byteLength", true); - VERIFY(byteLength, "Gltf bufferView '{}' missing required property 'byteLength'", key); - - auto byteStride = Json::parseUnsignedProperty(object, "byteStride", false); - - auto target = Json::parseUnsignedProperty(object, "target", false); - - auto name = Json::parseStringProperty(object, "name", false); - - if (buffer) bufferView->buffer = buffer.value(); - if (byteOffset) bufferView->byteOffset = byteOffset.value(); - if (byteLength) bufferView->byteLength = byteLength.value(); - if (byteStride) bufferView->byteStride = byteStride.value(); - if (target) bufferView->target = target.value(); - bufferView->name = name ? name.value() : key; - } - - void Gltf::parseBuffer(glTF::Buffer* buffer, const std::string& key, const json& object, std::map>* data) - { - auto uri = Json::parseStringProperty(object, "uri", false); - - // Load external binary data - if (uri) { - VERIFY(uri.value().find("data:", 0) == std::string::npos, "GltfFile embedded binary data is unsupported"); - data->emplace(std::stou(key), File::raw("assets/gltf/" + uri.value())); - } - - auto byteLength = Json::parseUnsignedProperty(object, "byteLength", true); - VERIFY(byteLength, "Gltf buffer '{}' missing required property 'byteLength'", key); - - auto name = Json::parseStringProperty(object, "name", false); - - if (uri) buffer->uri = uri.value(); - if (byteLength) buffer->byteLength = byteLength.value(); - buffer->name = name ? name.value() : key; - } - -} // namespace Inferno -#endif diff --git a/src/inferno/render/gltf.h b/src/inferno/render/gltf.h deleted file mode 100644 index 5d6da52..0000000 --- a/src/inferno/render/gltf.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2022 Riyyi - * - * SPDX-License-Identifier: MIT - */ - -#pragma once - -#if 0 - #include // uint32_t - #include // std::shared_ptr - #include // std::string - #include // std::unordered_map - #include // std::vector - - #include "ruc/singleton.h" - - #include "inferno/util/json.h" - - #define GLTF_TYPE_SCALAR 1 - #define GLTF_TYPE_VEC2 2 - #define GLTF_TYPE_VEC3 3 - #define GLTF_TYPE_VEC4 4 - #define GLTF_TYPE_MAT2 8 - #define GLTF_TYPE_MAT3 12 - #define GLTF_TYPE_MAT4 16 - - #define GLTF_COMPONENT_TYPE_BYTE 5120 - #define GLTF_COMPONENT_TYPE_UNSIGNED_BYTE 5121 - #define GLTF_COMPONENT_TYPE_SHORT 5122 - #define GLTF_COMPONENT_TYPE_UNSIGNED_SHORT 5123 - #define GLTF_COMPONENT_TYPE_INT 5124 - #define GLTF_COMPONENT_TYPE_UNSIGNED_INT 5125 - #define GLTF_COMPONENT_TYPE_FLOAT 5126 - - #define GLTF_TARGET_ARRAY_BUFFER 34962 - #define GLTF_TARGET_ELEMENT_ARRAY_BUFFER 34963 - -namespace Inferno { - - namespace glTF { - - // Type specifications - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#objects - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#asset - struct Asset { - std::string copyright; - std::string generator; - std::string version; // Required - std::string minVersion; - }; - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes - struct Scene { - std::vector nodes; - std::string name; - }; - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy - struct Node { - uint32_t camera; - std::vector children; - uint32_t skin; - std::array matrix { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; // Identity matrix - uint32_t mesh; - std::array rotation { 0, 0, 0, 1 }; - std::array scale { 1, 1, 1 }; - std::array translation { 0, 0, 0 }; - std::vector weights; - std::string name; - }; - - struct Primitive { - std::map attributes; // Required - uint32_t indices; - uint32_t material; - unsigned char mode { 4 }; - std::vector> targets; - }; - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes - struct Mesh { - std::vector primitives; // Required - std::vector weights; - std::string name; - }; - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#accessors - struct Accessor { - uint32_t bufferView; - uint32_t byteOffset { 0 }; - uint32_t componentType; // Required - bool normalized { false }; - uint32_t count; // Required - std::string type; // Required - std::vector max; - std::vector min; - std::string name; - }; - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#buffers-and-buffer-views - struct BufferView { - uint32_t buffer; // Required - uint32_t byteOffset { 0 }; - uint32_t byteLength; // Required - uint32_t byteStride; - uint32_t target; - std::string name; - }; - - struct Buffer { - std::string uri; - uint32_t byteLength; // Required - std::string name; - }; - - struct Model { - Asset asset; - - std::vector scenes; - std::vector nodes; - std::vector meshes; - std::vector accessors; - std::vector bufferViews; - std::vector buffers; - - std::map> data; - }; - - } // namespace glTF - -// ----------------------------------------- - - class Gltf { - public: - Gltf(const std::string& path); - virtual ~Gltf(); - - inline const glTF::Model& model() const { return m_model; } - - private: - static void parseAsset(glTF::Asset* asset, const json& object); - static void parseScene(glTF::Scene* scene, const std::string& key, const json& object); - static void parseNode(glTF::Node* node, const std::string& key, const json& object); - static void parsePrimitive(glTF::Primitive* primitive, const std::string& key, const json& object); - static void parseMesh(glTF::Mesh* mesh, const std::string& key, const json& object); - static void parseAccessor(glTF::Accessor* accessor, const std::string& key, const json& object); - static void parseBufferView(glTF::BufferView* bufferView, const std::string& key, const json& object); - static void parseBuffer(glTF::Buffer* buffer, const std::string& key, const json& object, std::map>* data); - - std::string m_path; - glTF::Model m_model; - }; - -// ----------------------------------------- - - class GltfManager final : ruc::Singleton { - public: - GltfManager(s) {} - virtual ~GltfManager() {} - - void add(const std::string& path, std::shared_ptr gltf); - std::shared_ptr load(const std::string& path); - std::shared_ptr get(const std::string& path); - bool exists(const std::string& path); - - void remove(const std::string& path); - void remove(std::shared_ptr gltf); - - private: - std::unordered_map> m_gltfList; - }; - -} // namespace Inferno -#endif diff --git a/src/inferno/render/render-command.cpp b/src/inferno/render/render-command.cpp index fdc1d28..8368e8f 100644 --- a/src/inferno/render/render-command.cpp +++ b/src/inferno/render/render-command.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: MIT */ -#include // std::shadred_ptr +#include // std::shared_ptr #include "glad/glad.h" #include "ruc/format/log.h" diff --git a/src/inferno/render/renderer.cpp b/src/inferno/render/renderer.cpp index a565e0a..4421f09 100644 --- a/src/inferno/render/renderer.cpp +++ b/src/inferno/render/renderer.cpp @@ -129,16 +129,16 @@ void Renderer::createElementBuffer() // Generate indices - uint32_t* indices = new uint32_t[maxElements]; + uint32_t* elements = new uint32_t[maxElements]; uint32_t offset = 0; for (uint32_t i = 0; i < maxElements; i += elementPerQuad) { - indices[i + 0] = offset + 0; - indices[i + 1] = offset + 1; - indices[i + 2] = offset + 2; - indices[i + 3] = offset + 2; - indices[i + 4] = offset + 3; - indices[i + 5] = offset + 0; + elements[i + 0] = offset + 0; + elements[i + 1] = offset + 1; + elements[i + 2] = offset + 2; + elements[i + 3] = offset + 2; + elements[i + 4] = offset + 3; + elements[i + 5] = offset + 0; offset += vertexPerQuad; } @@ -147,9 +147,9 @@ void Renderer::createElementBuffer() // --------------------------------- // Create index buffer - auto indexBuffer = std::make_shared(indices, sizeof(uint32_t) * maxElements); + auto indexBuffer = std::make_shared(elements, sizeof(uint32_t) * maxElements); m_vertexArray->setIndexBuffer(indexBuffer); - delete[] indices; + delete[] elements; } template @@ -271,7 +271,7 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i]; m_vertexBufferPtr->color = color[i]; m_vertexBufferPtr->textureCoordinates = textureCoordinates[i]; - m_vertexBufferPtr->textureIndex = (float)textureUnitIndex; + m_vertexBufferPtr->textureIndex = static_cast(textureUnitIndex); m_vertexBufferPtr++; } @@ -386,7 +386,7 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 for (uint32_t i = 0; i < vertexPerQuad * quadPerCube; i++) { m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i]; m_vertexBufferPtr->color = color[i % 4]; - m_vertexBufferPtr->textureIndex = (float)textureUnitIndex; + m_vertexBufferPtr->textureIndex = static_cast(textureUnitIndex); m_vertexBufferPtr++; } @@ -450,7 +450,7 @@ void RendererFont::drawSymbol(std::array& symbolQua m_vertexBufferPtr->quad.position = symbolQuad[i].quad.position; m_vertexBufferPtr->quad.color = symbolQuad[i].quad.color; m_vertexBufferPtr->quad.textureCoordinates = symbolQuad[i].quad.textureCoordinates; - m_vertexBufferPtr->quad.textureIndex = (float)textureUnitIndex; + m_vertexBufferPtr->quad.textureIndex = static_cast(textureUnitIndex); m_vertexBufferPtr->width = symbolQuad[i].width; m_vertexBufferPtr->edge = symbolQuad[i].edge; @@ -502,32 +502,38 @@ Renderer3D::Renderer3D(s) ruc::info("Renderer3D initialized"); } -void Renderer3D::drawModel(std::span vertices, std::span indices, const TransformComponent& transform, std::shared_ptr texture) +void Renderer3D::drawModel(std::span vertices, std::span elements, const TransformComponent& transform, std::shared_ptr texture) { + // ruc::error("drawModel"); + VERIFY(vertices.size() <= maxVertices, "model vertices too big for buffer"); - VERIFY(indices.size() <= maxElements, "model elements too big for buffer"); + VERIFY(elements.size() <= maxElements, "model elements too big for buffer"); // Create a new batch if the quad limit has been reached - if (m_vertexIndex + vertices.size() > maxVertices || m_elementIndex + indices.size() > maxElements) { + if (m_vertexIndex + vertices.size() > maxVertices || m_elementIndex + elements.size() > maxElements) { nextBatch(); } uint32_t textureUnitIndex = addTextureUnit(texture); // Add the vertices - for (auto vertex : vertices) { + for (const auto& vertex : vertices) { m_vertexBufferPtr->position = transform.transform * glm::vec4(vertex.position, 1.0f); m_vertexBufferPtr->normal = vertex.normal; m_vertexBufferPtr->textureCoordinates = vertex.textureCoordinates; - m_vertexBufferPtr->textureIndex = (float)textureUnitIndex; + m_vertexBufferPtr->textureIndex = static_cast(textureUnitIndex); m_vertexBufferPtr++; } - std::copy(indices.begin(), indices.end(), m_elementBufferPtr); - m_elementBufferPtr += indices.size(); + // Copy element indices to the element buffer + for (const auto& element : elements) { + // Indices are referenced relative to vertices[0], if there are multiple models in a batch, + // then the indices need to be offset by the total amount of vertices + *m_elementBufferPtr++ = element + m_vertexIndex; + } m_vertexIndex += vertices.size(); - m_elementIndex += indices.size(); + m_elementIndex += elements.size(); } void Renderer3D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) diff --git a/src/inferno/render/renderer.h b/src/inferno/render/renderer.h index 6b9e9b4..eecef79 100644 --- a/src/inferno/render/renderer.h +++ b/src/inferno/render/renderer.h @@ -62,6 +62,8 @@ struct Vertex { template class Renderer { public: + static constexpr const uint32_t vertexPerFace = 3; + static constexpr const uint32_t elementPerFace = 3; static constexpr const uint32_t vertexPerQuad = 4; static constexpr const uint32_t elementPerQuad = 6;