From 0ee9b8c6036899f95dfd54f151cb60a03645f87a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 12 Mar 2023 01:05:18 +0000 Subject: Support loading texture references into faces --- assetFactory/style.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index fc5c34e..5303d96 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -42,5 +42,5 @@ Style::persist(Persistence::PersistenceStore & store) } }; - return STORE_HELPER(colour, ColourParser); + return STORE_HELPER(colour, ColourParser) && STORE_MEMBER(texture) && STORE_MEMBER(textureRotation); } -- cgit v1.2.3 From 0d5b57f31e17b8e46979d8c29b5a3205fbdbd44b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 12 Mar 2023 01:29:38 +0000 Subject: Dedupe looking up the style stack for colour --- assetFactory/style.cpp | 20 ++++++++++---------- assetFactory/style.h | 2 ++ 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index 5303d96..fa585ac 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -4,11 +4,7 @@ void Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Shape::CreatedFaces & faces) const { - if (const auto effectiveColour = getProperty(parents, &Style::colour, - [](auto && style) { - return style->colour.a > 0; - }); - effectiveColour.has_value()) { + if (const auto effectiveColour = getColour(parents); effectiveColour.has_value()) { for (const auto & face : faces) { mesh.set_color(face.second, effectiveColour->get()); } @@ -18,15 +14,19 @@ Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Sha void Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const ModelFactoryMesh::FaceHandle & face) const { - if (const auto effectiveColour = getProperty(parents, &Style::colour, - [](auto && style) { - return style->colour.a > 0; - }); - effectiveColour.has_value()) { + if (const auto effectiveColour = getColour(parents); effectiveColour.has_value()) { mesh.set_color(face, effectiveColour->get()); } } +std::optional> +Style::getColour(const StyleStack & parents) +{ + return getProperty(parents, &Style::colour, [](auto && style) { + return style->colour.a > 0; + }); +} + bool Style::persist(Persistence::PersistenceStore & store) { diff --git a/assetFactory/style.h b/assetFactory/style.h index 84e5dab..8c64276 100644 --- a/assetFactory/style.h +++ b/assetFactory/style.h @@ -27,6 +27,8 @@ public: return {}; } + static std::optional> getColour(const StyleStack & parents); + ColourAlpha colour {}; std::string texture; std::string textureRotation; // Multiples of 90deg, no int/enum support -- cgit v1.2.3 From 7bf24d23a7db872f7bd13060da9817a9ee5f816c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 12 Mar 2023 01:36:50 +0000 Subject: Dedupe applying style to a face --- assetFactory/style.cpp | 17 +++++++++++------ assetFactory/style.h | 4 +++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index fa585ac..b5ddcf1 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -4,22 +4,27 @@ void Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Shape::CreatedFaces & faces) const { - if (const auto effectiveColour = getColour(parents); effectiveColour.has_value()) { - for (const auto & face : faces) { - mesh.set_color(face.second, effectiveColour->get()); - } + for (const auto & face : faces) { + applyStyle(mesh, face.second, getColour(parents)); } } void Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const ModelFactoryMesh::FaceHandle & face) const { - if (const auto effectiveColour = getColour(parents); effectiveColour.has_value()) { + applyStyle(mesh, face, getColour(parents)); +} + +void +Style::applyStyle( + ModelFactoryMesh & mesh, const ModelFactoryMesh::FaceHandle & face, EffectiveColour effectiveColour) const +{ + if (effectiveColour.has_value()) { mesh.set_color(face, effectiveColour->get()); } } -std::optional> +Style::EffectiveColour Style::getColour(const StyleStack & parents) { return getProperty(parents, &Style::colour, [](auto && style) { diff --git a/assetFactory/style.h b/assetFactory/style.h index 8c64276..f3bc707 100644 --- a/assetFactory/style.h +++ b/assetFactory/style.h @@ -12,6 +12,7 @@ public: using StyleStack = std::vector; using Colour = glm::vec3; using ColourAlpha = glm::vec4; + using EffectiveColour = std::optional>; void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const Shape::CreatedFaces &) const; void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const ModelFactoryMesh::FaceHandle &) const; @@ -27,7 +28,7 @@ public: return {}; } - static std::optional> getColour(const StyleStack & parents); + static EffectiveColour getColour(const StyleStack & parents); ColourAlpha colour {}; std::string texture; @@ -35,4 +36,5 @@ public: protected: bool persist(Persistence::PersistenceStore & store); + void applyStyle(ModelFactoryMesh &, const ModelFactoryMesh::FaceHandle &, EffectiveColour) const; }; -- cgit v1.2.3 From 3fea21a2d8f2aa67fd212837fe7e09e4f29ad515 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 14 Mar 2023 19:16:57 +0000 Subject: Support creating a super texture from fragments Currently makes wild assumptions about vertices and doesn't actually populate the texture, it's just grey --- assetFactory/asset.cpp | 10 ++++++ assetFactory/asset.h | 6 ++++ assetFactory/assetFactory.cpp | 62 +++++++++++++++++++++++++++++++++++++- assetFactory/assetFactory.h | 10 ++++++ assetFactory/factoryMesh.cpp | 6 ++-- assetFactory/modelFactoryMesh.h | 4 ++- assetFactory/style.cpp | 17 +++++++++-- game/vehicles/railVehicleClass.cpp | 6 ++++ game/vehicles/railVehicleClass.h | 1 + 9 files changed, 114 insertions(+), 8 deletions(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/asset.cpp b/assetFactory/asset.cpp index 3ab2f1c..e3f5feb 100644 --- a/assetFactory/asset.cpp +++ b/assetFactory/asset.cpp @@ -1,4 +1,5 @@ #include "asset.h" +#include "assetFactory.h" bool Asset::persist(Persistence::PersistenceStore & store) @@ -6,6 +7,15 @@ Asset::persist(Persistence::PersistenceStore & store) return STORE_MEMBER(id) && STORE_MEMBER(name); } +Asset::TexturePtr +Asset::getTexture() const +{ + if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { + return mf->getTexture(); + } + return nullptr; +} + Asset::MeshConstruct::MeshConstruct(Mesh::Ptr & m) : Persistence::SelectionPtrBase {fmesh}, out {m} { } diff --git a/assetFactory/asset.h b/assetFactory/asset.h index e3318e4..30f40cd 100644 --- a/assetFactory/asset.h +++ b/assetFactory/asset.h @@ -4,12 +4,18 @@ #include "persistence.h" #include +class Texture; + class Asset : public Persistence::Persistable, public StdTypeDefs { public: + using TexturePtr = std::shared_ptr; + std::string id; std::string name; protected: + TexturePtr getTexture() const; + struct MeshConstruct : public Persistence::SelectionPtrBase { using Persistence::SelectionPtrBase::setValue; diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp index de13579..276c258 100644 --- a/assetFactory/assetFactory.cpp +++ b/assetFactory/assetFactory.cpp @@ -2,11 +2,16 @@ #include "collections.hpp" #include "cuboid.h" #include "cylinder.h" +#include "filesystem.h" +#include "gfx/image.h" +#include "gfx/models/texture.h" #include "modelFactoryMesh_fwd.h" #include "object.h" #include "plane.h" +#include "resource.h" #include "saxParse-persistence.h" -#include +#include "texturePacker.h" +#include AssetFactory::AssetFactory() : shapes { @@ -76,6 +81,61 @@ 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 +{ + createTexutre(); + const auto & fragmentUV = textureFragmentPositions.at(id); + return { + fragmentUV.xy(), + fragmentUV.zy(), + fragmentUV.zw(), + fragmentUV.xw(), + }; +} + +Asset::TexturePtr +AssetFactory::getTexture() const +{ + createTexutre(); + return texture; +} + +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}; + }); + const auto [layout, outSize] = TexturePacker {imageSizes}.pack(); + // * create texture + std::vector textureData(TexturePacker::area(outSize), {127, 127, 127, 255}); + std::transform(textureFragments.begin(), textureFragments.end(), + std::inserter(textureFragmentPositions, textureFragmentPositions.end()), + [position = layout.begin(), size = imageSizes.begin(), outSize = outSize](const auto & tf) mutable { + const glm::vec4 positionFraction { + static_cast(position->x) / static_cast(outSize.x), + static_cast(position->y) / static_cast(outSize.y), + static_cast(position->x + size->x) / static_cast(outSize.x), + static_cast(position->y + size->y) / static_cast(outSize.y), + }; + position++; + size++; + return decltype(textureFragmentPositions)::value_type {tf.first, positionFraction}; + }); + texture = std::make_shared(outSize.x, outSize.y, textureData.data()); + } +} + bool AssetFactory::persist(Persistence::PersistenceStore & store) { diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h index 3d52f7f..52692c4 100644 --- a/assetFactory/assetFactory.h +++ b/assetFactory/assetFactory.h @@ -6,6 +6,8 @@ #include "textureFragment.h" #include +class Texture; + class AssetFactory : public Persistence::Persistable { public: using Shapes = std::map>; @@ -14,10 +16,13 @@ public: using Colour = glm::vec3; using ColourAlpha = glm::vec4; using Colours = std::map>; + using TextureFragmentCoords = std::array; 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]] Asset::TexturePtr getTexture() const; Shapes shapes; Assets assets; @@ -30,4 +35,9 @@ public: private: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; + + void createTexutre() const; + + mutable Asset::TexturePtr texture; + mutable std::map> textureFragmentPositions; }; diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp index 1665b90..c47e80e 100644 --- a/assetFactory/factoryMesh.cpp +++ b/assetFactory/factoryMesh.cpp @@ -2,13 +2,10 @@ #include "collections.hpp" #include "gfx/models/vertex.hpp" #include "modelFactoryMesh.h" -#include Mesh::Ptr FactoryMesh::createMesh() const { - constexpr glm::vec2 NullUV {}; - ModelFactoryMesh mesh; for (const auto & use : uses) { use->createMesh(mesh, 1); @@ -23,7 +20,8 @@ FactoryMesh::createMesh() const const auto smooth = mesh.property(mesh.smoothFaceProperty, face); const auto colour = mesh.color(face); for (const auto & vertex : mesh.fv_range(face)) { - vertices.emplace_back(mesh.point(vertex), NullUV, + const auto textureUV = mesh.texcoord2D(vertex); + vertices.emplace_back(mesh.point(vertex), textureUV, smooth ? mesh.property(mesh.vertex_normals_pph(), vertex) : mesh.property(mesh.face_normals_pph(), face), colour); diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h index 149ff1a..493ce1b 100644 --- a/assetFactory/modelFactoryMesh.h +++ b/assetFactory/modelFactoryMesh.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -34,10 +35,11 @@ namespace OpenMesh { struct ModelFactoryTraits : public OpenMesh::DefaultTraits { FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status | OpenMesh::Attributes::Color); EdgeAttributes(OpenMesh::Attributes::Status); - VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); + VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status | OpenMesh::Attributes::TexCoord2D); using Point = glm::vec3; using Normal = glm::vec3; using Color = glm::vec4; + using TexCoord2D = glm::vec2; }; struct ModelFactoryMesh : public OpenMesh::PolyMesh_ArrayKernelT { diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index b5ddcf1..8aecc71 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -19,8 +19,21 @@ void Style::applyStyle( ModelFactoryMesh & mesh, const ModelFactoryMesh::FaceHandle & face, EffectiveColour effectiveColour) const { - if (effectiveColour.has_value()) { - mesh.set_color(face, effectiveColour->get()); + if (texture.empty()) { + if (effectiveColour.has_value()) { + mesh.set_color(face, effectiveColour->get()); + } + } + else { + mesh.set_color(face, {}); + if (auto mf = Persistence::ParseBase::getShared("assetFactory")) { + auto coords = mf->getTextureCoords(texture); + auto coord = coords.begin(); + // Wild assumption that face is a quad and the texture should apply linearly + for (const auto & vh : mesh.fv_range(face)) { + mesh.set_texcoord2D(vh, *coord++); + } + } } } diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index 41ef5e9..4e9263c 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -49,6 +49,12 @@ RailVehicleClass::persist(Persistence::PersistenceStore & store) && STORE_HELPER(bodyMesh, Asset::MeshConstruct) && Asset::persist(store); } +void +RailVehicleClass::postLoad() +{ + texture = getTexture(); +} + void RailVehicleClass::render( const SceneShader & shader, const Location & location, const std::array & bl) const diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h index a2222fb..61ec4ec 100644 --- a/game/vehicles/railVehicleClass.h +++ b/game/vehicles/railVehicleClass.h @@ -30,6 +30,7 @@ public: protected: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; + void postLoad() override; private: RailVehicleClass(std::unique_ptr obj, std::shared_ptr); -- cgit v1.2.3 From 51f0f60bd24a3d7ed77cf713f846bc49c2f1aed5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 18 Mar 2023 02:44:00 +0000 Subject: Use halfedge for texture coordinates More unique than vertex as it is also per face, allowing for a different texture on adjacent faces --- assetFactory/factoryMesh.cpp | 9 +++++---- assetFactory/modelFactoryMesh.h | 3 ++- assetFactory/style.cpp | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp index 59b390f..6cca388 100644 --- a/assetFactory/factoryMesh.cpp +++ b/assetFactory/factoryMesh.cpp @@ -18,16 +18,17 @@ FactoryMesh::createMesh() const for (const auto & face : mesh.faces()) { const auto smooth = mesh.property(mesh.smoothFaceProperty, face); const auto colour = mesh.color(face); - auto vrange = mesh.fv_range(face); + auto hrange = mesh.fh_range(face); const unsigned int start = static_cast(vertices.size()); - for (const auto & vertex : vrange) { - const auto textureUV = mesh.texcoord2D(vertex); + for (const auto & heh : hrange) { + const auto & vertex = mesh.to_vertex_handle(heh); + const auto textureUV = mesh.texcoord2D(heh); vertices.emplace_back(mesh.point(vertex), textureUV, smooth ? mesh.property(mesh.vertex_normals_pph(), vertex) : mesh.property(mesh.face_normals_pph(), face), colour); } - const auto vcount = std::distance(vrange.begin(), vrange.end()); + const auto vcount = std::distance(hrange.begin(), hrange.end()); for (unsigned int i = 2; i < vcount; i++) { indices.push_back(start); indices.push_back(start + i - 1); diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h index 493ce1b..a862dc1 100644 --- a/assetFactory/modelFactoryMesh.h +++ b/assetFactory/modelFactoryMesh.h @@ -35,7 +35,8 @@ namespace OpenMesh { struct ModelFactoryTraits : public OpenMesh::DefaultTraits { FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status | OpenMesh::Attributes::Color); EdgeAttributes(OpenMesh::Attributes::Status); - VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status | OpenMesh::Attributes::TexCoord2D); + VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); + HalfedgeAttributes(OpenMesh::Attributes::TexCoord2D); using Point = glm::vec3; using Normal = glm::vec3; using Color = glm::vec4; diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index 8aecc71..d1d4adc 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -30,8 +30,8 @@ Style::applyStyle( auto coords = mf->getTextureCoords(texture); auto coord = coords.begin(); // Wild assumption that face is a quad and the texture should apply linearly - for (const auto & vh : mesh.fv_range(face)) { - mesh.set_texcoord2D(vh, *coord++); + for (const auto & heh : mesh.fh_range(face)) { + mesh.set_texcoord2D(heh, *coord++); } } } -- cgit v1.2.3 From 2508112e2853e1a6c012b19c7232aa09f98d3969 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 20 Mar 2023 23:30:21 +0000 Subject: Move smooth property into Style and make it optional This allows it to cascade down as faces are created and also be overridden as required --- assetFactory/faceController.cpp | 8 ++------ assetFactory/faceController.h | 1 - assetFactory/style.cpp | 6 +++++- assetFactory/style.h | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'assetFactory/style.cpp') diff --git a/assetFactory/faceController.cpp b/assetFactory/faceController.cpp index bafbee2..2367f8d 100644 --- a/assetFactory/faceController.cpp +++ b/assetFactory/faceController.cpp @@ -48,12 +48,10 @@ FaceController::applySingle(ModelFactoryMesh & mesh, const StyleStack & parents, faces.merge(std::move(newFaces)); } else { - mesh.property(mesh.smoothFaceProperty, faceHandle) = smooth; applyStyle(mesh, parents + this, faceHandle); } } for (const auto & [faceName, faceHandle] : controlledFaces) { - mesh.property(mesh.smoothFaceProperty, faceHandle) = smooth; applyStyle(mesh, parents + this, faceHandle); } } @@ -89,9 +87,8 @@ FaceController::extrude(ModelFactoryMesh & mesh, const std::string & faceName, O auto & newFaceName = mesh.property(mesh.nameFaceProperty, newFace); newFaceName = getAdjacentFaceName(mesh, ofrange, newFace); newFaces.emplace(newFaceName, newFace); - mesh.property(mesh.smoothFaceProperty, newFace) = smooth; } - mesh.property(mesh.smoothFaceProperty, newFaces.emplace(faceName, mesh.add_face(vertices))->second) = smooth; + newFaces.emplace(faceName, mesh.add_face(vertices)); return newFaces; } @@ -99,7 +96,6 @@ FaceController::extrude(ModelFactoryMesh & mesh, const std::string & faceName, O bool FaceController::persist(Persistence::PersistenceStore & store) { - return STORE_TYPE && STORE_MEMBER(id) && Style::persist(store) && STORE_MEMBER(type) && STORE_MEMBER(smooth) - && Mutation::persist(store) + return STORE_TYPE && STORE_MEMBER(id) && Style::persist(store) && STORE_MEMBER(type) && Mutation::persist(store) && STORE_NAME_HELPER("face", faceControllers, Persistence::MapByMember); } diff --git a/assetFactory/faceController.h b/assetFactory/faceController.h index 962a516..851292a 100644 --- a/assetFactory/faceController.h +++ b/assetFactory/faceController.h @@ -17,7 +17,6 @@ public: std::string id; std::string type; - bool smooth {false}; FaceControllers faceControllers; private: diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index d1d4adc..12346a6 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -19,6 +19,9 @@ void Style::applyStyle( ModelFactoryMesh & mesh, const ModelFactoryMesh::FaceHandle & face, EffectiveColour effectiveColour) const { + if (smooth.has_value()) { + mesh.property(mesh.smoothFaceProperty, face) = smooth.value(); + } if (texture.empty()) { if (effectiveColour.has_value()) { mesh.set_color(face, effectiveColour->get()); @@ -60,5 +63,6 @@ Style::persist(Persistence::PersistenceStore & store) } }; - return STORE_HELPER(colour, ColourParser) && STORE_MEMBER(texture) && STORE_MEMBER(textureRotation); + return STORE_HELPER(colour, ColourParser) && STORE_MEMBER(smooth) && STORE_MEMBER(texture) + && STORE_MEMBER(textureRotation); } diff --git a/assetFactory/style.h b/assetFactory/style.h index f3bc707..d931f98 100644 --- a/assetFactory/style.h +++ b/assetFactory/style.h @@ -31,6 +31,7 @@ public: static EffectiveColour getColour(const StyleStack & parents); ColourAlpha colour {}; + std::optional smooth; std::string texture; std::string textureRotation; // Multiples of 90deg, no int/enum support -- cgit v1.2.3