From f5a213f621f012e8e4ea541cad409e3cfa1ccaa6 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 10 Apr 2023 01:59:11 +0100 Subject: One OpenMesh instance per top level Use in createMesh --- assetFactory/factoryMesh.cpp | 60 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp index 8869efd..4922936 100644 --- a/assetFactory/factoryMesh.cpp +++ b/assetFactory/factoryMesh.cpp @@ -6,43 +6,45 @@ Mesh::Ptr FactoryMesh::createMesh() const { - ModelFactoryMesh mesh; + std::vector vertices; + std::vector indices; + for (const auto & use : uses) { + ModelFactoryMesh mesh; use->createMesh(mesh, 1); - } - mesh.update_face_normals(); - mesh.update_vertex_normals(); - std::vector vertices; - std::vector indices; - for (const auto & face : mesh.faces()) { - const auto & smooth = mesh.property(mesh.smoothFaceProperty, face); - const auto & colour = mesh.color(face); + mesh.update_face_normals(); + mesh.update_vertex_normals(); + for (const auto & face : mesh.faces()) { + const auto & smooth = mesh.property(mesh.smoothFaceProperty, face); + const auto & colour = mesh.color(face); - std::vector faceIndices; - for (const auto & heh : mesh.fh_range(face)) { - const auto & vertex = mesh.to_vertex_handle(heh); - const auto & textureUV = mesh.texcoord2D(heh); - const auto & point = mesh.point(vertex); - const auto & normal = smooth ? mesh.property(mesh.vertex_normals_pph(), vertex) - : mesh.property(mesh.face_normals_pph(), face); - Vertex outVertex {point, textureUV, normal, colour}; - if (const auto existingItr = std::find(vertices.rbegin(), vertices.rend(), outVertex); - existingItr != vertices.rend()) { - faceIndices.push_back(static_cast(std::distance(existingItr, vertices.rend()) - 1)); - } - else { - faceIndices.push_back(static_cast(vertices.size())); - vertices.emplace_back(outVertex); + std::vector faceIndices; + for (const auto & heh : mesh.fh_range(face)) { + const auto & vertex = mesh.to_vertex_handle(heh); + const auto & textureUV = mesh.texcoord2D(heh); + const auto & point = mesh.point(vertex); + const auto & normal = smooth ? mesh.property(mesh.vertex_normals_pph(), vertex) + : mesh.property(mesh.face_normals_pph(), face); + Vertex outVertex {point, textureUV, normal, colour}; + if (const auto existingItr = std::find(vertices.rbegin(), vertices.rend(), outVertex); + existingItr != vertices.rend()) { + faceIndices.push_back(static_cast(std::distance(existingItr, vertices.rend()) - 1)); + } + else { + faceIndices.push_back(static_cast(vertices.size())); + vertices.emplace_back(outVertex); + } } - } - for (unsigned int i = 2; i < faceIndices.size(); i++) { - indices.push_back(faceIndices[0]); - indices.push_back(faceIndices[i - 1]); - indices.push_back(faceIndices[i]); + for (unsigned int i = 2; i < faceIndices.size(); i++) { + indices.push_back(faceIndices[0]); + indices.push_back(faceIndices[i - 1]); + indices.push_back(faceIndices[i]); + } } } + return std::make_shared(vertices, indices); } -- cgit v1.2.3 From 989b10986f1626d1a50fceb8a33174108c03da93 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 10 Apr 2023 14:46:18 +0100 Subject: Load texture fragment images as we go, make the image a member --- assetFactory/assetFactory.cpp | 19 ++++++------------- assetFactory/textureFragment.cpp | 8 ++++++++ assetFactory/textureFragment.h | 3 +++ 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index ed1af58..ec0e19f 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -11,7 +11,6 @@ #include "resource.h" #include "saxParse-persistence.h" #include "texturePacker.h" -#include AssetFactory::AssetFactory() : shapes { @@ -105,30 +104,24 @@ void AssetFactory::createTexutre() const { if (!textureFragments.empty() && (!texture || textureFragmentPositions.empty())) { - // * load images - std::vector> images; - std::transform( - textureFragments.begin(), textureFragments.end(), std::back_inserter(images), [](const auto & tf) { - return std::make_unique(Resource::mapPath(tf.second->path), STBI_rgb_alpha); - }); // * layout images std::vector imageSizes; - std::transform(images.begin(), images.end(), std::back_inserter(imageSizes), [](const auto & image) { - return TexturePacker::Image {image->width, image->height}; + std::transform( + textureFragments.begin(), textureFragments.end(), std::back_inserter(imageSizes), [](const auto & tf) { + return TexturePacker::Image {tf.second->image->width, tf.second->image->height}; }); const auto [layout, outSize] = TexturePacker {imageSizes}.pack(); // * create texture texture = std::make_shared(outSize.x, outSize.y, TextureOptions {.wrap = GL_CLAMP_TO_EDGE}); std::transform(textureFragments.begin(), textureFragments.end(), std::inserter(textureFragmentPositions, textureFragmentPositions.end()), - [position = layout.begin(), image = images.begin(), size = imageSizes.begin(), - outSize = glm::vec2 {outSize}](const auto & tf) mutable { + [position = layout.begin(), size = imageSizes.begin(), outSize = glm::vec2 {outSize}]( + const auto & tf) mutable { const auto positionFraction = glm::vec4 {*position, *position + *size} / outSize.xyxy(); glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast(position->x), static_cast(position->y), static_cast(size->x), static_cast(size->y), GL_RGBA, GL_UNSIGNED_BYTE, - image->get()->data.data()); + tf.second->image->data.data()); position++; - image++; size++; return decltype(textureFragmentPositions)::value_type {tf.first, positionFraction}; }); diff --git a/assetFactory/textureFragment.cpp b/assetFactory/textureFragment.cpp index 72107a5..d153688 100644 --- a/assetFactory/textureFragment.cpp +++ b/assetFactory/textureFragment.cpp @@ -1,7 +1,15 @@ #include "textureFragment.h" +#include "resource.h" +#include bool TextureFragment::persist(Persistence::PersistenceStore & store) { return STORE_TYPE && STORE_MEMBER(id) && STORE_MEMBER(path); } + +void +TextureFragment::postLoad() +{ + image = std::make_unique(Resource::mapPath(path), STBI_rgb_alpha); +} diff --git a/assetFactory/textureFragment.h b/assetFactory/textureFragment.h index 52f2591..d03affd 100644 --- a/assetFactory/textureFragment.h +++ b/assetFactory/textureFragment.h @@ -1,5 +1,6 @@ #pragma once +#include "gfx/image.h" #include "persistence.h" #include "stdTypeDefs.hpp" @@ -7,8 +8,10 @@ class TextureFragment : public Persistence::Persistable, public StdTypeDefs image; private: friend Persistence::SelectionPtrBase; bool persist(Persistence::PersistenceStore & store) override; + void postLoad() override; }; -- cgit v1.2.3 From b25bc3cc32c5a9057c66ad282fa1cdfe0ed6094a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 10 Apr 2023 18:45:13 +0100 Subject: First cut loading assets using assimp This is far from perfect, specifically the created texture atlas is not compatibile with wrapping texture UVs --- assetFactory/assetFactory.cpp | 5 +- assetFactory/assetFactory.h | 3 ++ assetFactory/assimp.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++ assetFactory/assimp.h | 14 +++++ 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 assetFactory/assimp.cpp create mode 100644 assetFactory/assimp.h (limited to 'assetFactory') diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index ec0e19f..917edfe 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -109,7 +109,7 @@ AssetFactory::createTexutre() const std::transform( textureFragments.begin(), textureFragments.end(), std::back_inserter(imageSizes), [](const auto & tf) { return TexturePacker::Image {tf.second->image->width, tf.second->image->height}; - }); + }); const auto [layout, outSize] = TexturePacker {imageSizes}.pack(); // * create texture texture = std::make_shared(outSize.x, outSize.y, TextureOptions {.wrap = GL_CLAMP_TO_EDGE}); @@ -134,7 +134,8 @@ AssetFactory::persist(Persistence::PersistenceStore & store) using MapObjects = Persistence::MapByMember>; using MapAssets = Persistence::MapByMember; using MapTextureFragments = Persistence::MapByMember; + using MapAssImp = Persistence::MapByMember, &AssImp::path>; return STORE_TYPE && STORE_NAME_HELPER("object", shapes, MapObjects) && STORE_NAME_HELPER("textureFragment", textureFragments, MapTextureFragments) - && STORE_NAME_HELPER("asset", assets, MapAssets); + && STORE_NAME_HELPER("assimp", assimps, MapAssImp) && STORE_NAME_HELPER("asset", assets, MapAssets); } diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h index 52692c4..7843d44 100644 --- a/assetFactory/assetFactory.h +++ b/assetFactory/assetFactory.h @@ -1,6 +1,7 @@ #pragma once #include "asset.h" +#include "assimp.h" #include "persistence.h" #include "shape.h" #include "textureFragment.h" @@ -12,6 +13,7 @@ class AssetFactory : public Persistence::Persistable { public: using Shapes = std::map>; using Assets = std::map>; + using AssImps = std::map>; using TextureFragments = std::map>; using Colour = glm::vec3; using ColourAlpha = glm::vec4; @@ -26,6 +28,7 @@ public: Shapes shapes; Assets assets; + AssImps assimps; Colours colours; TextureFragments textureFragments; diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp new file mode 100644 index 0000000..55090f4 --- /dev/null +++ b/assetFactory/assimp.cpp @@ -0,0 +1,119 @@ +#include "assimp.h" +#include "assetFactory.h" +#include "collections.hpp" +#include "ptr.hpp" +#include "resource.h" +#include +#include +#include +#include + +template +glm::vec<3, T> +operator*(const aiVector3t & v) +{ + return {v.x, v.y, v.z}; +} + +template +glm::vec<2, T> +operator!(const aiVector3t & v) +{ + return {v.x, v.y}; +} + +#define AIRANGE(parent, member) \ + std::span \ + { \ + (parent)->m##member, (parent)->mNum##member \ + } + +using ScemeCPtr = std::shared_ptr; +class AssImpNode : public Shape { +public: + AssImpNode(ScemeCPtr scene, const aiNode * node) : scene(std::move(scene)), node(node) { } + + ScemeCPtr scene; + const aiNode * node; + + CreatedFaces + createMesh(ModelFactoryMesh & mesh, float) const + { + CreatedFaces faces; + addMesh(faces, mesh, node); + return faces; + } + + void + addMesh(CreatedFaces & faces, ModelFactoryMesh & mesh, const aiNode * node) const + { + for (const auto & m : AIRANGE(node, Meshes)) { + addMesh(faces, mesh, scene->mMeshes[m]); + } + for (const auto & n : AIRANGE(node, Children)) { + addMesh(faces, mesh, n); + } + } + + void + addMesh(CreatedFaces & faces, ModelFactoryMesh & mesh, const aiMesh * amesh) const + { + const auto vhs = AIRANGE(amesh, Vertices) * [&mesh](auto && v) { + return mesh.add_vertex(*v); + }; + const auto & m = *scene->mMaterials[amesh->mMaterialIndex]; + + AssetFactory::TextureFragmentCoords tfc; + if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { + aiString path; + m.Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); + tfc = mf->getTextureCoords(path.C_Str()); + } + + for (const auto & f : AIRANGE(amesh, Faces)) { + const auto fvhs = AIRANGE(&f, Indices) * [&vhs](auto && i) { + return vhs[i]; + }; + const auto fh = faces.emplace(mesh.add_namedFace(amesh->mName.C_Str(), fvhs))->second; + if (amesh->HasTextureCoords(0)) { + for (auto idx = f.mIndices; const auto fheh : mesh.fh_range(fh)) { + const auto ouv = !amesh->mTextureCoords[0][*idx++]; + const auto uv = glm::mix(tfc[0], tfc[2], ouv); + mesh.set_texcoord2D(fheh, uv); + } + } + } + } +}; + +void +AssImp::postLoad() +{ + ScemeCPtr scene { + aiImportFile(Resource::mapPath(path).c_str(), aiProcess_RemoveRedundantMaterials), &aiReleaseImport}; + if (!scene) { + throw std::runtime_error("Failed to load asset library: " + path); + } + if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { + const auto root = AIRANGE(scene->mRootNode, Children); + std::transform( + root.begin(), root.end(), std::inserter(mf->shapes, mf->shapes.end()), [&scene](const aiNode * m) { + return AssetFactory::Shapes::value_type {m->mName.C_Str(), std::make_shared(scene, m)}; + }); + const auto textures = AIRANGE(scene, Textures); + std::transform(textures.begin(), textures.end(), + std::inserter(mf->textureFragments, mf->textureFragments.end()), [](const aiTexture * t) { + auto texture = std::make_shared(); + texture->id = texture->path = t->mFilename.C_Str(); + texture->image = std::make_unique( + std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); + return AssetFactory::TextureFragments::value_type {texture->id, texture}; + }); + } +} + +bool +AssImp::persist(Persistence::PersistenceStore & store) +{ + return STORE_TYPE && STORE_MEMBER(path); +} diff --git a/assetFactory/assimp.h b/assetFactory/assimp.h new file mode 100644 index 0000000..55b551d --- /dev/null +++ b/assetFactory/assimp.h @@ -0,0 +1,14 @@ +#pragma once + +#include "persistence.h" + +class AssImp : public Persistence::Persistable { +public: + using Ptr = std::shared_ptr; + + void postLoad() override; + + bool persist(Persistence::PersistenceStore & store) override; + + std::string path; +}; -- cgit v1.2.3 From 3cd6bc2d9eebbdd575164816110717241d9e22db Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 10 Apr 2023 19:48:07 +0100 Subject: Load assimp textures in parallel --- assetFactory/assimp.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index 55090f4..0c6cb86 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include template @@ -101,12 +102,18 @@ AssImp::postLoad() return AssetFactory::Shapes::value_type {m->mName.C_Str(), std::make_shared(scene, m)}; }); const auto textures = AIRANGE(scene, Textures); - std::transform(textures.begin(), textures.end(), - std::inserter(mf->textureFragments, mf->textureFragments.end()), [](const aiTexture * t) { - auto texture = std::make_shared(); - texture->id = texture->path = t->mFilename.C_Str(); - texture->image = std::make_unique( - std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); + auto textureFutures = textures * [](const aiTexture * t) { + return std::async(std::launch::async, [t]() { + auto texture = std::make_shared(); + texture->id = texture->path = t->mFilename.C_Str(); + texture->image = std::make_unique( + std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); + return texture; + }); + }; + std::transform(textureFutures.begin(), textureFutures.end(), + std::inserter(mf->textureFragments, mf->textureFragments.end()), [](auto && textureFuture) { + auto texture = textureFuture.get(); return AssetFactory::TextureFragments::value_type {texture->id, texture}; }); } -- cgit v1.2.3 From 1b97b7b4cb126c8b60ac1acbd7e72274f0ddf21f Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 13 Apr 2023 02:20:50 +0100 Subject: Use texture atlas for asset factory --- assetFactory/asset.h | 4 ++-- assetFactory/assetFactory.cpp | 26 ++++++++------------------ assetFactory/assetFactory.h | 4 ++-- assetFactory/assimp.cpp | 8 ++++---- assetFactory/factoryMesh.cpp | 3 ++- assetFactory/modelFactoryMesh.cpp | 1 + assetFactory/modelFactoryMesh.h | 2 ++ assetFactory/style.cpp | 9 ++++++++- 8 files changed, 29 insertions(+), 28 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/asset.h b/assetFactory/asset.h index 30f40cd..dba4974 100644 --- a/assetFactory/asset.h +++ b/assetFactory/asset.h @@ -4,11 +4,11 @@ #include "persistence.h" #include -class Texture; +class TextureAtlas; class Asset : public Persistence::Persistable, public StdTypeDefs { public: - using TexturePtr = std::shared_ptr; + using TexturePtr = std::shared_ptr; std::string id; std::string name; diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index 917edfe..46b4642 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -80,17 +80,11 @@ AssetFactory::parseColour(std::string_view in) const throw std::runtime_error("No such asset factory colour"); } -AssetFactory::TextureFragmentCoords -AssetFactory::getTextureCoords(std::string_view id) const +GLuint +AssetFactory::getMaterialIndex(std::string_view id) const { createTexutre(); - const auto & fragmentUV = textureFragmentPositions.at(id); - return { - fragmentUV.xy(), - fragmentUV.zy(), - fragmentUV.zw(), - fragmentUV.xw(), - }; + return textureFragmentPositions.at(id); } Asset::TexturePtr @@ -103,7 +97,7 @@ AssetFactory::getTexture() const void AssetFactory::createTexutre() const { - if (!textureFragments.empty() && (!texture || textureFragmentPositions.empty())) { + if (!textureFragments.empty() && !texture) { // * layout images std::vector imageSizes; std::transform( @@ -112,18 +106,14 @@ AssetFactory::createTexutre() const }); const auto [layout, outSize] = TexturePacker {imageSizes}.pack(); // * create texture - texture = std::make_shared(outSize.x, outSize.y, TextureOptions {.wrap = GL_CLAMP_TO_EDGE}); + texture = std::make_shared(outSize.x, outSize.y, layout.size()); std::transform(textureFragments.begin(), textureFragments.end(), std::inserter(textureFragmentPositions, textureFragmentPositions.end()), - [position = layout.begin(), size = imageSizes.begin(), outSize = glm::vec2 {outSize}]( - const auto & tf) mutable { - const auto positionFraction = glm::vec4 {*position, *position + *size} / outSize.xyxy(); - glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast(position->x), static_cast(position->y), - static_cast(size->x), static_cast(size->y), GL_RGBA, GL_UNSIGNED_BYTE, - tf.second->image->data.data()); + [position = layout.begin(), size = imageSizes.begin(), this](const auto & tf) mutable { + const auto m = texture->add(*position, *size, tf.second->image->data.data()); position++; size++; - return decltype(textureFragmentPositions)::value_type {tf.first, positionFraction}; + return decltype(textureFragmentPositions)::value_type {tf.first, m}; }); } } diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h index 7843d44..9e5d205 100644 --- a/assetFactory/assetFactory.h +++ b/assetFactory/assetFactory.h @@ -23,7 +23,7 @@ public: AssetFactory(); [[nodiscard]] static std::shared_ptr loadXML(const std::filesystem::path &); [[nodiscard]] ColourAlpha parseColour(std::string_view) const; - [[nodiscard]] TextureFragmentCoords getTextureCoords(std::string_view) const; + [[nodiscard]] GLuint getMaterialIndex(std::string_view) const; [[nodiscard]] Asset::TexturePtr getTexture() const; Shapes shapes; @@ -42,5 +42,5 @@ private: void createTexutre() const; mutable Asset::TexturePtr texture; - mutable std::map> textureFragmentPositions; + mutable std::map> textureFragmentPositions; }; diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index 0c6cb86..dd82105 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -64,11 +64,11 @@ public: }; const auto & m = *scene->mMaterials[amesh->mMaterialIndex]; - AssetFactory::TextureFragmentCoords tfc; + GLuint material {}; if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { aiString path; m.Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); - tfc = mf->getTextureCoords(path.C_Str()); + material = mf->getMaterialIndex(path.C_Str()); } for (const auto & f : AIRANGE(amesh, Faces)) { @@ -79,8 +79,8 @@ public: if (amesh->HasTextureCoords(0)) { for (auto idx = f.mIndices; const auto fheh : mesh.fh_range(fh)) { const auto ouv = !amesh->mTextureCoords[0][*idx++]; - const auto uv = glm::mix(tfc[0], tfc[2], ouv); - mesh.set_texcoord2D(fheh, uv); + mesh.set_texcoord2D(fheh, ouv); + mesh.property(mesh.materialFaceProperty, fh) = material; } } } diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp index 4922936..f7bc7c8 100644 --- a/assetFactory/factoryMesh.cpp +++ b/assetFactory/factoryMesh.cpp @@ -18,6 +18,7 @@ FactoryMesh::createMesh() const for (const auto & face : mesh.faces()) { const auto & smooth = mesh.property(mesh.smoothFaceProperty, face); const auto & colour = mesh.color(face); + const auto & material = mesh.property(mesh.materialFaceProperty, face); std::vector faceIndices; for (const auto & heh : mesh.fh_range(face)) { @@ -26,7 +27,7 @@ FactoryMesh::createMesh() const const auto & point = mesh.point(vertex); const auto & normal = smooth ? mesh.property(mesh.vertex_normals_pph(), vertex) : mesh.property(mesh.face_normals_pph(), face); - Vertex outVertex {point, textureUV, normal, colour}; + Vertex outVertex {point, textureUV, normal, colour, material}; if (const auto existingItr = std::find(vertices.rbegin(), vertices.rend(), outVertex); existingItr != vertices.rend()) { faceIndices.push_back(static_cast(std::distance(existingItr, vertices.rend()) - 1)); diff --git a/assetFactory/modelFactoryMesh.cpp b/assetFactory/modelFactoryMesh.cpp index e640502..3d4b5f3 100644 --- a/assetFactory/modelFactoryMesh.cpp +++ b/assetFactory/modelFactoryMesh.cpp @@ -3,6 +3,7 @@ ModelFactoryMesh::ModelFactoryMesh() { add_property(smoothFaceProperty); + add_property(materialFaceProperty); add_property(nameFaceProperty); add_property(nameAdjFaceProperty); } diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h index 8ac2edd..4eac7ee 100644 --- a/assetFactory/modelFactoryMesh.h +++ b/assetFactory/modelFactoryMesh.h @@ -1,6 +1,7 @@ #pragma once #include "modelFactoryMesh_fwd.h" +#include #include #include #include @@ -47,6 +48,7 @@ struct ModelFactoryMesh : public OpenMesh::PolyMesh_ArrayKernelT smoothFaceProperty; + OpenMesh::FPropHandleT materialFaceProperty; OpenMesh::FPropHandleT nameFaceProperty; OpenMesh::HPropHandleT nameAdjFaceProperty; diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index 12346a6..ea67fc2 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -30,7 +30,14 @@ Style::applyStyle( else { mesh.set_color(face, {}); if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { - auto coords = mf->getTextureCoords(texture); + const auto material = mf->getMaterialIndex(texture); + mesh.property(mesh.materialFaceProperty, face) = material; + static constexpr std::array coords {{ + {0.f, 0.f}, + {1.f, 0.f}, + {1.f, 1.f}, + {0.f, 1.f}, + }}; auto coord = coords.begin(); // Wild assumption that face is a quad and the texture should apply linearly for (const auto & heh : mesh.fh_range(face)) { -- cgit v1.2.3 From c51c4c0ca3b19e47d6e75ce4be247a28d412a04c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 13 Apr 2023 20:03:13 +0100 Subject: Fix typo in name SceneCPtr --- assetFactory/assimp.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index dd82105..878e7e7 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -29,12 +29,12 @@ operator!(const aiVector3t & v) (parent)->m##member, (parent)->mNum##member \ } -using ScemeCPtr = std::shared_ptr; +using SceneCPtr = std::shared_ptr; class AssImpNode : public Shape { public: - AssImpNode(ScemeCPtr scene, const aiNode * node) : scene(std::move(scene)), node(node) { } + AssImpNode(SceneCPtr scene, const aiNode * node) : scene(std::move(scene)), node(node) { } - ScemeCPtr scene; + SceneCPtr scene; const aiNode * node; CreatedFaces @@ -90,7 +90,7 @@ public: void AssImp::postLoad() { - ScemeCPtr scene { + SceneCPtr scene { aiImportFile(Resource::mapPath(path).c_str(), aiProcess_RemoveRedundantMaterials), &aiReleaseImport}; if (!scene) { throw std::runtime_error("Failed to load asset library: " + path); -- cgit v1.2.3 From 79506d6072ad7482ace521cc3a60671e78fd1597 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 01:04:38 +0100 Subject: Reduce texture size determined by packer if non-pot sizes are supported --- assetFactory/texturePacker.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'assetFactory') diff --git a/assetFactory/texturePacker.cpp b/assetFactory/texturePacker.cpp index 68a6010..30f1c37 100644 --- a/assetFactory/texturePacker.cpp +++ b/assetFactory/texturePacker.cpp @@ -1,7 +1,9 @@ #include "texturePacker.h" #include "collections.hpp" +#include #include #include +#include #include #include #include @@ -55,6 +57,17 @@ TexturePacker::pack(Size size) const } } } + if (GLEW_ARB_texture_non_power_of_two) { + // Crop the size back to minimum size + size = std::transform_reduce( + result.begin(), result.end(), inputImages.begin(), Size {}, + [](auto && max, auto && limit) { + return glm::max(max, limit); + }, + [](auto && pos, auto && size) { + return pos + size; + }); + } return {result, size}; } -- cgit v1.2.3 From 2b3df2889369aa22b6a1c782bb7fed658720c341 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 01:06:31 +0100 Subject: Have texture packer search harder for a solution, stopping at the reported texture size limit --- assetFactory/texturePacker.cpp | 16 ++++++++++++---- assetFactory/texturePacker.h | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/texturePacker.cpp b/assetFactory/texturePacker.cpp index 30f1c37..fcc935f 100644 --- a/assetFactory/texturePacker.cpp +++ b/assetFactory/texturePacker.cpp @@ -14,6 +14,9 @@ TexturePacker::TexturePacker(std::span in) : std::sort(sortedIndexes.rbegin(), sortedIndexes.rend(), [this](const auto a, const auto b) { return area(inputImages[a]) < area(inputImages[b]); }); + int mts; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts); + maxTextureSize = static_cast(mts); } TexturePacker::Result @@ -25,6 +28,9 @@ TexturePacker::pack() const TexturePacker::Result TexturePacker::pack(Size size) const { + if (size.x > maxTextureSize || size.y > maxTextureSize) { + return {}; + } using Spaces = std::set; Spaces spaces {{{}, size}}; @@ -49,12 +55,14 @@ TexturePacker::pack(Size size) const } } else { - if (size.x < size.y) { - return pack({size.x * 2, size.y}); + const auto x = pack({size.x * 2, size.y}), y = pack({size.x, size.y * 2}); + if (!x.first.empty() && (y.first.empty() || area(x.second) < area(y.second))) { + return x; } - else { - return pack({size.x, size.y * 2}); + else if (!y.first.empty()) { + return y; } + return {}; } } if (GLEW_ARB_texture_non_power_of_two) { diff --git a/assetFactory/texturePacker.h b/assetFactory/texturePacker.h index ca0d67a..a1b270b 100644 --- a/assetFactory/texturePacker.h +++ b/assetFactory/texturePacker.h @@ -38,4 +38,5 @@ public: private: std::span inputImages; std::vector sortedIndexes; + unsigned int maxTextureSize; }; -- cgit v1.2.3 From 1cdd7753d37bcf8f626298c3df97a02cc73f266c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 14:48:59 +0100 Subject: Load texture images in Worker --- assetFactory/assetFactory.cpp | 18 +++++++++++------- assetFactory/assimp.cpp | 20 ++++++++------------ assetFactory/textureFragment.cpp | 4 +++- assetFactory/textureFragment.h | 3 ++- 4 files changed, 24 insertions(+), 21 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index 46b4642..e27e575 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -99,21 +99,25 @@ AssetFactory::createTexutre() const { if (!textureFragments.empty() && !texture) { // * layout images - std::vector imageSizes; + std::map> images; std::transform( - textureFragments.begin(), textureFragments.end(), std::back_inserter(imageSizes), [](const auto & tf) { - return TexturePacker::Image {tf.second->image->width, tf.second->image->height}; + textureFragments.begin(), textureFragments.end(), std::inserter(images, images.end()), [](auto && tf) { + return decltype(images)::value_type {tf.first, tf.second->image->get()}; }); + std::vector imageSizes; + std::transform(images.begin(), images.end(), std::back_inserter(imageSizes), [](const auto & i) { + return TexturePacker::Image {i.second->width, i.second->height}; + }); const auto [layout, outSize] = TexturePacker {imageSizes}.pack(); // * create texture texture = std::make_shared(outSize.x, outSize.y, layout.size()); - std::transform(textureFragments.begin(), textureFragments.end(), + std::transform(images.begin(), images.end(), std::inserter(textureFragmentPositions, textureFragmentPositions.end()), - [position = layout.begin(), size = imageSizes.begin(), this](const auto & tf) mutable { - const auto m = texture->add(*position, *size, tf.second->image->data.data()); + [position = layout.begin(), size = imageSizes.begin(), this](const auto & i) mutable { + const auto m = texture->add(*position, *size, i.second->data.data()); position++; size++; - return decltype(textureFragmentPositions)::value_type {tf.first, m}; + return decltype(textureFragmentPositions)::value_type {i.first, m}; }); } } diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index 878e7e7..bab052e 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -102,18 +102,14 @@ AssImp::postLoad() return AssetFactory::Shapes::value_type {m->mName.C_Str(), std::make_shared(scene, m)}; }); const auto textures = AIRANGE(scene, Textures); - auto textureFutures = textures * [](const aiTexture * t) { - return std::async(std::launch::async, [t]() { - auto texture = std::make_shared(); - texture->id = texture->path = t->mFilename.C_Str(); - texture->image = std::make_unique( - std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); - return texture; - }); - }; - std::transform(textureFutures.begin(), textureFutures.end(), - std::inserter(mf->textureFragments, mf->textureFragments.end()), [](auto && textureFuture) { - auto texture = textureFuture.get(); + std::transform(textures.begin(), textures.end(), + std::inserter(mf->textureFragments, mf->textureFragments.end()), [](auto && t) { + auto texture = std::make_shared(); + texture->id = texture->path = t->mFilename.C_Str(); + texture->image = Worker::addWork([t]() { + return std::make_unique( + std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); + }); return AssetFactory::TextureFragments::value_type {texture->id, texture}; }); } diff --git a/assetFactory/textureFragment.cpp b/assetFactory/textureFragment.cpp index d153688..0a4ec1d 100644 --- a/assetFactory/textureFragment.cpp +++ b/assetFactory/textureFragment.cpp @@ -11,5 +11,7 @@ TextureFragment::persist(Persistence::PersistenceStore & store) void TextureFragment::postLoad() { - image = std::make_unique(Resource::mapPath(path), STBI_rgb_alpha); + image = Worker::addWork([this]() { + return std::make_unique(Resource::mapPath(path), STBI_rgb_alpha); + }); } diff --git a/assetFactory/textureFragment.h b/assetFactory/textureFragment.h index d03affd..75fe96e 100644 --- a/assetFactory/textureFragment.h +++ b/assetFactory/textureFragment.h @@ -3,12 +3,13 @@ #include "gfx/image.h" #include "persistence.h" #include "stdTypeDefs.hpp" +#include "worker.h" class TextureFragment : public Persistence::Persistable, public StdTypeDefs { public: std::string id; std::string path; - std::unique_ptr image; + Worker::WorkPtrT> image; private: friend Persistence::SelectionPtrBase; -- cgit v1.2.3 From 3e97b30a194907cede7a230e618f82ffb516b329 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 15:25:38 +0100 Subject: Create texture fragments from materials --- assetFactory/assimp.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index bab052e..9a49717 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -62,13 +62,11 @@ public: const auto vhs = AIRANGE(amesh, Vertices) * [&mesh](auto && v) { return mesh.add_vertex(*v); }; - const auto & m = *scene->mMaterials[amesh->mMaterialIndex]; + const auto & m = scene->mMaterials[amesh->mMaterialIndex]->GetName(); GLuint material {}; if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { - aiString path; - m.Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); - material = mf->getMaterialIndex(path.C_Str()); + material = mf->getMaterialIndex(m.C_Str()); } for (const auto & f : AIRANGE(amesh, Faces)) { @@ -101,12 +99,15 @@ AssImp::postLoad() root.begin(), root.end(), std::inserter(mf->shapes, mf->shapes.end()), [&scene](const aiNode * m) { return AssetFactory::Shapes::value_type {m->mName.C_Str(), std::make_shared(scene, m)}; }); - const auto textures = AIRANGE(scene, Textures); - std::transform(textures.begin(), textures.end(), - std::inserter(mf->textureFragments, mf->textureFragments.end()), [](auto && t) { + const auto materials = AIRANGE(scene, Materials); + std::transform(materials.begin(), materials.end(), + std::inserter(mf->textureFragments, mf->textureFragments.end()), [&scene](const aiMaterial * m) { + aiString path; + m->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); auto texture = std::make_shared(); - texture->id = texture->path = t->mFilename.C_Str(); - texture->image = Worker::addWork([t]() { + texture->id = m->GetName().C_Str(); + texture->path = path.C_Str(); + texture->image = Worker::addWork([t = scene->GetEmbeddedTexture(path.C_Str())]() { return std::make_unique( std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); }); -- cgit v1.2.3 From 32a2da41e0946c1d6d364b7763d1829bfa8b74db Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 16:36:22 +0100 Subject: Configure texture fragment mapmode from material --- assetFactory/assimp.cpp | 7 +++++++ assetFactory/textureFragment.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'assetFactory') diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index 9a49717..840c5a9 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -85,6 +85,11 @@ public: } }; +static_assert(TextureOptions::MapMode::Repeat == static_cast(aiTextureMapMode_Wrap)); +static_assert(TextureOptions::MapMode::Clamp == static_cast(aiTextureMapMode_Clamp)); +static_assert(TextureOptions::MapMode::Decal == static_cast(aiTextureMapMode_Decal)); +static_assert(TextureOptions::MapMode::Mirror == static_cast(aiTextureMapMode_Mirror)); + void AssImp::postLoad() { @@ -107,6 +112,8 @@ AssImp::postLoad() auto texture = std::make_shared(); texture->id = m->GetName().C_Str(); texture->path = path.C_Str(); + m->Get(AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0), texture->mapmodeU); + m->Get(AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0), texture->mapmodeV); texture->image = Worker::addWork([t = scene->GetEmbeddedTexture(path.C_Str())]() { return std::make_unique( std::span {reinterpret_cast(t->pcData), t->mWidth}, STBI_rgb_alpha); diff --git a/assetFactory/textureFragment.h b/assetFactory/textureFragment.h index 75fe96e..e6f07f3 100644 --- a/assetFactory/textureFragment.h +++ b/assetFactory/textureFragment.h @@ -1,6 +1,7 @@ #pragma once #include "gfx/image.h" +#include "gfx/models/texture.h" #include "persistence.h" #include "stdTypeDefs.hpp" #include "worker.h" @@ -9,6 +10,7 @@ class TextureFragment : public Persistence::Persistable, public StdTypeDefs> image; private: -- cgit v1.2.3 From 70c3268225bbb985079ec6715ae598dce5605a4e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 16:38:05 +0100 Subject: Pass texture fragment mapmode to texture atlas --- assetFactory/assetFactory.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'assetFactory') diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index e27e575..05f0634 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -99,10 +99,10 @@ AssetFactory::createTexutre() const { if (!textureFragments.empty() && !texture) { // * layout images - std::map> images; + std::map> images; std::transform( textureFragments.begin(), textureFragments.end(), std::inserter(images, images.end()), [](auto && tf) { - return decltype(images)::value_type {tf.first, tf.second->image->get()}; + return decltype(images)::value_type {tf.second.get(), tf.second->image->get()}; }); std::vector imageSizes; std::transform(images.begin(), images.end(), std::back_inserter(imageSizes), [](const auto & i) { @@ -114,10 +114,14 @@ AssetFactory::createTexutre() const std::transform(images.begin(), images.end(), std::inserter(textureFragmentPositions, textureFragmentPositions.end()), [position = layout.begin(), size = imageSizes.begin(), this](const auto & i) mutable { - const auto m = texture->add(*position, *size, i.second->data.data()); + const auto m = texture->add(*position, *size, i.second->data.data(), + { + .wrapU = i.first->mapmodeU, + .wrapV = i.first->mapmodeV, + }); position++; size++; - return decltype(textureFragmentPositions)::value_type {i.first, m}; + return decltype(textureFragmentPositions)::value_type {i.first->id, m}; }); } } -- cgit v1.2.3 From 47cd9d863fb09acb82d2428f881d61242f8ab437 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 17:33:02 +0100 Subject: Load all assets in red dir with asset factory --- assetFactory/assetFactory.cpp | 13 +++++++++++++ assetFactory/assetFactory.h | 1 + 2 files changed, 14 insertions(+) (limited to 'assetFactory') diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index 05f0634..af0cd54 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -11,6 +11,7 @@ #include "resource.h" #include "saxParse-persistence.h" #include "texturePacker.h" +#include AssetFactory::AssetFactory() : shapes { @@ -29,6 +30,18 @@ AssetFactory::loadXML(const std::filesystem::path & filename) return Persistence::SAXParsePersistence {}.loadState>(file); } +AssetFactory::Assets +AssetFactory::loadAll(const std::filesystem::path & root) +{ + return std::accumulate(std::filesystem::recursive_directory_iterator {root}, + std::filesystem::recursive_directory_iterator {}, Assets {}, [](auto && out, auto && path) { + if (path.path().extension() == ".xml") { + out.merge(loadXML(path)->assets); + } + return std::move(out); + }); +} + AssetFactory::Colours AssetFactory::parseX11RGB(const char * path) { diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h index 9e5d205..e449ce2 100644 --- a/assetFactory/assetFactory.h +++ b/assetFactory/assetFactory.h @@ -22,6 +22,7 @@ public: AssetFactory(); [[nodiscard]] static std::shared_ptr loadXML(const std::filesystem::path &); + [[nodiscard]] static Assets loadAll(const std::filesystem::path &); [[nodiscard]] ColourAlpha parseColour(std::string_view) const; [[nodiscard]] GLuint getMaterialIndex(std::string_view) const; [[nodiscard]] Asset::TexturePtr getTexture() const; -- cgit v1.2.3