summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-02-24 19:30:30 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2023-02-24 19:30:30 +0000
commit7d0decccaac3aa564b549d91a36279e7aca0814e (patch)
tree749ceff26556ed201a055b8d8a70636b50c562f7
parentSupport for model colours mixed with textures (diff)
downloadilt-7d0decccaac3aa564b549d91a36279e7aca0814e.tar.bz2
ilt-7d0decccaac3aa564b549d91a36279e7aca0814e.tar.xz
ilt-7d0decccaac3aa564b549d91a36279e7aca0814e.zip
Support for recursive colouring of asset factory faces
Updates colours in sample model.
-rw-r--r--assetFactory/faceController.cpp29
-rw-r--r--assetFactory/faceController.h7
-rw-r--r--assetFactory/factoryMesh.cpp4
-rw-r--r--assetFactory/modelFactoryMesh.h3
-rw-r--r--assetFactory/style.cpp59
-rw-r--r--assetFactory/style.h22
-rw-r--r--assetFactory/use.cpp5
-rw-r--r--assetFactory/use.h4
-rw-r--r--res/brush47.xml16
9 files changed, 124 insertions, 25 deletions
diff --git a/assetFactory/faceController.cpp b/assetFactory/faceController.cpp
index 499f7e4..9f057da 100644
--- a/assetFactory/faceController.cpp
+++ b/assetFactory/faceController.cpp
@@ -1,14 +1,19 @@
#include "faceController.h"
+#include "collections.hpp"
#include "maths.h"
#include "modelFactoryMesh.h"
void
-FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::CreatedFaces & faces) const
+FaceController::apply(ModelFactoryMesh & mesh, const StyleStack & parents, const std::string & name,
+ Shape::CreatedFaces & faces) const
{
+ const auto controlledFacesRange = faces.equal_range(name);
+ const std::vector controlledFaces(controlledFacesRange.first, controlledFacesRange.second);
+ if (controlledFaces.empty()) {
+ throw std::runtime_error("Named face(s) do not exist: " + name);
+ }
if (!type.empty()) {
const auto mutation = getMatrix();
- const auto controlledFacesRange = faces.equal_range(name);
- const std::vector controlledFaces(controlledFacesRange.first, controlledFacesRange.second);
faces.erase(name);
for (const auto & cf : controlledFaces) {
// get face vertices
@@ -23,9 +28,6 @@ FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::
const auto vertexCount = points.size();
const auto centre
= std::accumulate(points.begin(), points.end(), glm::vec3 {}) / static_cast<float>(vertexCount);
- if (smooth) {
- mesh.property(mesh.smoothFaceProperty, cf.second) = true;
- }
if (type == "extrude") {
Shape::CreatedFaces newFaces;
// mutate points
@@ -38,7 +40,6 @@ FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::
return mesh.add_vertex({p.x, p.y, p.z});
});
// create new faces
-
mesh.delete_face(cf.second);
for (size_t idx {}; idx < vertexCount; ++idx) {
const auto next = (idx + 1) % vertexCount;
@@ -51,11 +52,21 @@ FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::
mesh.property(mesh.smoothFaceProperty, face) = true;
}
}
+ applyStyle(mesh, parents + this, newFaces);
for (const auto & [name, faceController] : faceControllers) {
- faceController->apply(mesh, name, newFaces);
+ faceController->apply(mesh, parents + this, name, newFaces);
}
faces.merge(std::move(newFaces));
}
+ else {
+ mesh.property(mesh.smoothFaceProperty, cf.second) = smooth;
+ applyStyle(mesh, parents + this, cf.second);
+ }
+ }
+ }
+ else {
+ for (const auto & cf : controlledFaces) {
+ applyStyle(mesh, parents + this, cf.second);
}
}
}
@@ -63,7 +74,7 @@ FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::
bool
FaceController::persist(Persistence::PersistenceStore & store)
{
- return STORE_TYPE && STORE_MEMBER(id) && STORE_MEMBER(colour) && STORE_MEMBER(type) && STORE_MEMBER(smooth)
+ return STORE_TYPE && STORE_MEMBER(id) && Style::persist(store) && STORE_MEMBER(type) && STORE_MEMBER(smooth)
&& STORE_MEMBER(scale) && STORE_MEMBER(position) && STORE_MEMBER(rotation)
&& STORE_NAME_HELPER("face", faceControllers, Persistence::MapByMember<FaceControllers>);
}
diff --git a/assetFactory/faceController.h b/assetFactory/faceController.h
index 296210d..0618388 100644
--- a/assetFactory/faceController.h
+++ b/assetFactory/faceController.h
@@ -4,17 +4,18 @@
#include "mutation.h"
#include "persistence.h"
#include "shape.h"
+#include "style.h"
#include <map>
#include <string>
-class FaceController : public Mutation, public Persistence::Persistable {
+class FaceController : public Mutation, public Style, public Persistence::Persistable {
public:
using FaceControllers = std::map<std::string, std::unique_ptr<FaceController>>;
- void apply(ModelFactoryMesh & mesh, const std::string & name, Shape::CreatedFaces & faces) const;
+ void apply(ModelFactoryMesh & mesh, const Style::StyleStack & parents, const std::string & name,
+ Shape::CreatedFaces & faces) const;
std::string id;
- std::string colour;
std::string type;
bool smooth {false};
FaceControllers faceControllers;
diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp
index 0fb72ad..0cfed85 100644
--- a/assetFactory/factoryMesh.cpp
+++ b/assetFactory/factoryMesh.cpp
@@ -21,10 +21,12 @@ FactoryMesh::createMesh() const
std::vector<Vertex> vertices;
for (const auto & face : mesh.faces()) {
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,
smooth ? mesh.property(mesh.vertex_normals_pph(), vertex)
- : mesh.property(mesh.face_normals_pph(), face));
+ : mesh.property(mesh.face_normals_pph(), face),
+ colour);
}
}
return std::make_shared<Mesh>(vertices, vectorOfN(vertices.size()));
diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h
index d0ffc26..7d222f5 100644
--- a/assetFactory/modelFactoryMesh.h
+++ b/assetFactory/modelFactoryMesh.h
@@ -20,11 +20,12 @@ namespace OpenMesh {
}
struct ModelFactoryTraits : public OpenMesh::DefaultTraits {
- FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
+ FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status | OpenMesh::Attributes::Color);
EdgeAttributes(OpenMesh::Attributes::Status);
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
using Point = OpenMesh::glmvec<float, 3>;
using Normal = OpenMesh::glmvec<float, 3>;
+ using Color = OpenMesh::glmvec<float, 4>;
};
struct ModelFactoryMesh : public OpenMesh::PolyMesh_ArrayKernelT<ModelFactoryTraits> {
diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp
new file mode 100644
index 0000000..099d81a
--- /dev/null
+++ b/assetFactory/style.cpp
@@ -0,0 +1,59 @@
+#include "style.h"
+
+ModelFactoryMesh::Color
+Style::parseColour(const std::string_view & in)
+{
+ if (in.empty()) {
+ return {};
+ }
+ if (in[0] == '#') {
+ ModelFactoryMesh::Color out {0, 0, 0, 1};
+ std::generate_n(out.begin(), (in.length() - 1) / 2, [in = in.data() + 1]() mutable {
+ uint8_t channel;
+ std::from_chars(in, in + 2, channel, 16);
+ in += 2;
+ return static_cast<float>(channel) / 256.F;
+ });
+ return out;
+ }
+ return {};
+}
+
+void
+Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const Shape::CreatedFaces & faces) const
+{
+ if (const auto effectiveColour = getProperty(parents, &Style::colour); !effectiveColour.empty()) {
+ const auto parsedColour = parseColour(effectiveColour);
+ for (const auto & face : faces) {
+ mesh.set_color(face.second, parsedColour);
+ }
+ }
+}
+
+void
+Style::applyStyle(ModelFactoryMesh & mesh, const StyleStack & parents, const ModelFactoryMesh::FaceHandle & face) const
+{
+ if (const auto effectiveColour = getProperty(parents, &Style::colour); !effectiveColour.empty()) {
+ const auto parsedColour = parseColour(effectiveColour);
+ mesh.set_color(face, parsedColour);
+ }
+}
+
+std::string_view
+Style::getProperty(const StyleStack & parents, std::string Style::*member)
+{
+ if (const auto itr = std::find_if(parents.rbegin(), parents.rend(),
+ [&member](auto && s) {
+ return !(s->*member).empty();
+ });
+ itr != parents.rend()) {
+ return (*itr)->*member;
+ }
+ return {};
+}
+
+bool
+Style::persist(Persistence::PersistenceStore & store)
+{
+ return STORE_MEMBER(colour);
+}
diff --git a/assetFactory/style.h b/assetFactory/style.h
new file mode 100644
index 0000000..0c7ad5a
--- /dev/null
+++ b/assetFactory/style.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "modelFactoryMesh.h"
+#include "persistence.h"
+#include "shape.h"
+#include <string>
+
+class Style {
+public:
+ using StyleStack = std::vector<const Style *>;
+
+ static ModelFactoryMesh::Color parseColour(const std::string_view &);
+ void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const Shape::CreatedFaces &) const;
+ void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const ModelFactoryMesh::FaceHandle &) const;
+
+ static std::string_view getProperty(const StyleStack & parents, std::string Style::*member);
+
+ std::string colour;
+
+protected:
+ bool persist(Persistence::PersistenceStore & store);
+};
diff --git a/assetFactory/use.cpp b/assetFactory/use.cpp
index 1f28332..a6fac5c 100644
--- a/assetFactory/use.cpp
+++ b/assetFactory/use.cpp
@@ -5,8 +5,9 @@ Shape::CreatedFaces
Use::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
{
auto faces = type->createMesh(mesh, mutation * getMatrix());
+ applyStyle(mesh, {this}, faces);
for (const auto & [name, faceController] : faceControllers) {
- faceController->apply(mesh, name, faces);
+ faceController->apply(mesh, {this}, name, faces);
}
return faces;
}
@@ -27,6 +28,6 @@ bool
Use::persist(Persistence::PersistenceStore & store)
{
return STORE_TYPE && STORE_HELPER(type, Lookup) && STORE_MEMBER(position) && STORE_MEMBER(scale)
- && STORE_MEMBER(rotation) && STORE_MEMBER(colour)
+ && STORE_MEMBER(rotation) && Style::persist(store)
&& STORE_NAME_HELPER("face", faceControllers, Persistence::MapByMember<FaceControllers>);
}
diff --git a/assetFactory/use.h b/assetFactory/use.h
index 853af23..5b61eca 100644
--- a/assetFactory/use.h
+++ b/assetFactory/use.h
@@ -5,15 +5,15 @@
#include "persistence.h"
#include "shape.h"
#include "stdTypeDefs.hpp"
+#include "style.h"
-class Use : public StdTypeDefs<Use>, public Mutation, public Persistence::Persistable {
+class Use : public StdTypeDefs<Use>, public Mutation, public Style, public Persistence::Persistable {
public:
using FaceControllers = std::map<std::string, std::unique_ptr<FaceController>>;
Shape::CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const;
Shape::CPtr type;
- std::string colour;
FaceControllers faceControllers;
private:
diff --git a/res/brush47.xml b/res/brush47.xml
index 9fd4fe2..fe3d114 100644
--- a/res/brush47.xml
+++ b/res/brush47.xml
@@ -14,19 +14,21 @@
</object>
<asset id="brush-47" name="Brush 47">
<mesh id="body" size="2.69,19.38,3.9">
- <use type="cuboid" position="0,0,1.2" scale="2.69,19.38,1.5" colour="#1111dd">
- <face id="bottom" colour="#2C3539"/>
- <face id="top" type="extrude" scale="1,0.95,1" position="0,0,1.0">
- <face id="top" type="extrude" scale="0.6,0.9,0" position="0,0,0.2" smooth="true"/>
+ <use type="cuboid" position="0,0,1.2" scale="2.69,19.38,1.5" colour="#2c4f5a">
+ <face id="bottom" colour="#2c3539"/>
+ <face id="front" colour="#fbc32f"/>
+ <face id="back" colour="#fbc32f"/>
+ <face id="top" type="extrude" scale="1,0.95,1" position="0,0,0.8">
+ <face id="top" type="extrude" scale="0.5,0.8,0" position="0,0,0.4" smooth="true" colour="#aeb0b0"/>
</face>
</use>
- <use type="cuboid" position="0,0,0.2" scale="2.6,4.5,1" colour="#2C3539"/>
+ <use type="cuboid" position="0,0,0.2" scale="2.6,4.5,1" colour="#413b3a"/>
</mesh>
<mesh id="bogie1">
- <use type="bogie" position="0,6,0"/>
+ <use type="bogie" position="0,6,0" colour="#413b3a"/>
</mesh>
<mesh id="bogie2">
- <use type="bogie" position="0,-6,0" rotation="0,3.14159,0"/>
+ <use type="bogie" position="0,-6,0" rotation="0,3.14159,0" colour="#413b3a"/>
</mesh>
</asset>
</ilt>