summaryrefslogtreecommitdiff
path: root/assetFactory
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-02-15 02:26:06 +0000
committerDan Goodliffe <dan.goodliffe@octal.co.uk>2023-02-15 11:34:11 +0000
commit715d4879fdd096ac82367984fdb22117d48737a4 (patch)
tree576b0553b10795bb51384ba4c47269d4226bdca6 /assetFactory
parentAdd OpenMeshCore library (diff)
downloadilt-715d4879fdd096ac82367984fdb22117d48737a4.tar.bz2
ilt-715d4879fdd096ac82367984fdb22117d48737a4.tar.xz
ilt-715d4879fdd096ac82367984fdb22117d48737a4.zip
First cut of the model factory and the hardcoded Brush 47 model
Requires temporary change to the fragment shader to hardcode some visible colour to the model
Diffstat (limited to 'assetFactory')
-rw-r--r--assetFactory/assetFactoryConfig.h28
-rw-r--r--assetFactory/assetFactoryConfig_fwd.h8
-rw-r--r--assetFactory/cuboid.cpp29
-rw-r--r--assetFactory/cuboid.h8
-rw-r--r--assetFactory/cylinder.cpp43
-rw-r--r--assetFactory/cylinder.h8
-rw-r--r--assetFactory/faceController.cpp53
-rw-r--r--assetFactory/faceController.h20
-rw-r--r--assetFactory/factoryMesh.cpp27
-rw-r--r--assetFactory/factoryMesh.h14
-rw-r--r--assetFactory/modelFactory.cpp14
-rw-r--r--assetFactory/modelFactory.h12
-rw-r--r--assetFactory/mutation.cpp10
-rw-r--r--assetFactory/mutation.h14
-rw-r--r--assetFactory/object.cpp17
-rw-r--r--assetFactory/object.h15
-rw-r--r--assetFactory/plane.cpp15
-rw-r--r--assetFactory/plane.h8
-rw-r--r--assetFactory/shape.cpp17
-rw-r--r--assetFactory/shape.h25
-rw-r--r--assetFactory/use.cpp11
-rw-r--r--assetFactory/use.h17
22 files changed, 413 insertions, 0 deletions
diff --git a/assetFactory/assetFactoryConfig.h b/assetFactory/assetFactoryConfig.h
new file mode 100644
index 0000000..171b81a
--- /dev/null
+++ b/assetFactory/assetFactoryConfig.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "assetFactoryConfig_fwd.h"
+#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
+#include <OpenMesh/Core/Mesh/Traits.hh>
+#include <glm/geometric.hpp>
+#include <glm/vec3.hpp>
+
+namespace OpenMesh {
+ template<typename Scalar, int DIM> struct glmvec : public VectorT<Scalar, DIM> {
+ using VectorT<Scalar, DIM>::VectorT;
+ glmvec(const VectorT<Scalar, DIM> & v) : VectorT<Scalar, DIM> {v} { }
+ operator glm::vec<DIM, Scalar>() const
+ {
+ glm::vec<DIM, Scalar> out;
+ std::copy(this->begin(), this->end(), &out[0]);
+ return out;
+ }
+ };
+}
+
+struct ModelFactoryTraits : public OpenMesh::DefaultTraits {
+ FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
+ EdgeAttributes(OpenMesh::Attributes::Status);
+ VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
+ using Point = OpenMesh::glmvec<float, 3>;
+ using Normal = OpenMesh::glmvec<float, 3>;
+};
diff --git a/assetFactory/assetFactoryConfig_fwd.h b/assetFactory/assetFactoryConfig_fwd.h
new file mode 100644
index 0000000..28489ff
--- /dev/null
+++ b/assetFactory/assetFactoryConfig_fwd.h
@@ -0,0 +1,8 @@
+#pragma once
+
+namespace OpenMesh {
+ template<typename> class PolyMesh_ArrayKernelT;
+}
+struct ModelFactoryTraits;
+
+using ModelFactoryMesh = OpenMesh::PolyMesh_ArrayKernelT<ModelFactoryTraits>;
diff --git a/assetFactory/cuboid.cpp b/assetFactory/cuboid.cpp
new file mode 100644
index 0000000..90b2108
--- /dev/null
+++ b/assetFactory/cuboid.cpp
@@ -0,0 +1,29 @@
+#include "cuboid.h"
+#include "assetFactoryConfig.h"
+
+Cuboid::CreatedFaces
+Cuboid::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
+{
+ static constexpr std::array<glm::vec3, 8> VERTICES {{
+ // bottom
+ {n, n, z},
+ {n, y, z},
+ {y, y, z},
+ {y, n, z},
+ // top
+ {y, n, o},
+ {y, y, o},
+ {n, y, o},
+ {n, n, o},
+ }};
+
+ const auto vhs = addMutatedToMesh(mesh, VERTICES, mutation);
+ return {
+ {"top", mesh.add_face({vhs[4], vhs[5], vhs[6], vhs[7]})},
+ {"bottom", mesh.add_face({vhs[0], vhs[1], vhs[2], vhs[3]})},
+ {"left", mesh.add_face({vhs[0], vhs[7], vhs[6], vhs[1]})},
+ {"right", mesh.add_face({vhs[2], vhs[5], vhs[4], vhs[3]})},
+ {"front", mesh.add_face({vhs[0], vhs[3], vhs[4], vhs[7]})},
+ {"back", mesh.add_face({vhs[2], vhs[1], vhs[6], vhs[5]})},
+ };
+}
diff --git a/assetFactory/cuboid.h b/assetFactory/cuboid.h
new file mode 100644
index 0000000..5a4072a
--- /dev/null
+++ b/assetFactory/cuboid.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "shape.h"
+
+class Cuboid : public Shape {
+public:
+ CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const override;
+};
diff --git a/assetFactory/cylinder.cpp b/assetFactory/cylinder.cpp
new file mode 100644
index 0000000..66d456d
--- /dev/null
+++ b/assetFactory/cylinder.cpp
@@ -0,0 +1,43 @@
+#include "cylinder.h"
+#include "assetFactoryConfig.h"
+#include "maths.h"
+
+Cylinder::CreatedFaces
+Cylinder::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
+{
+ const glm::vec2 scale {std::accumulate(&mutation[0][0], &mutation[0][3], 0.f),
+ std::accumulate(&mutation[1][0], &mutation[1][3], 0.f)};
+ const unsigned int P = static_cast<unsigned int>(std::round(15.F * std::sqrt(glm::length(scale))));
+ std::vector<OpenMesh::VertexHandle> bottom(P), top(P);
+ std::generate_n(bottom.begin(), P, [a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
+ const auto xy = sincosf(a += step) * .5F;
+ const auto xyz = (xy ^ 0) % mutation;
+ return mesh.add_vertex({xyz.x, xyz.y, xyz.z});
+ });
+ std::generate_n(top.begin(), P, [a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
+ const auto xy = sincosf(a -= step) * .5F;
+ const auto xyz = (xy ^ 1) % mutation;
+ return mesh.add_vertex({xyz.x, xyz.y, xyz.z});
+ });
+ CreatedFaces surface;
+ std::generate_n(std::inserter(surface, surface.end()), P,
+ [a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
+ const auto xy1 = sincosf(a) * .5F;
+ const auto xy2 = sincosf(a -= step) * .5F;
+ const auto xyz1b = (xy1 ^ 0) % mutation;
+ const auto xyz2b = (xy2 ^ 0) % mutation;
+ const auto xyz1t = (xy1 ^ 1) % mutation;
+ const auto xyz2t = (xy2 ^ 1) % mutation;
+ return std::make_pair(std::string {"edge"},
+ mesh.add_face({
+ mesh.add_vertex({xyz1b.x, xyz1b.y, xyz1b.z}),
+ mesh.add_vertex({xyz2b.x, xyz2b.y, xyz2b.z}),
+ mesh.add_vertex({xyz2t.x, xyz2t.y, xyz2t.z}),
+ mesh.add_vertex({xyz1t.x, xyz1t.y, xyz1t.z}),
+ }));
+ });
+ surface.emplace("bottom", mesh.add_face(bottom));
+ surface.emplace("top", mesh.add_face(top));
+
+ return surface;
+}
diff --git a/assetFactory/cylinder.h b/assetFactory/cylinder.h
new file mode 100644
index 0000000..65ca5e5
--- /dev/null
+++ b/assetFactory/cylinder.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "shape.h"
+
+class Cylinder : public Shape {
+public:
+ CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const override;
+};
diff --git a/assetFactory/faceController.cpp b/assetFactory/faceController.cpp
new file mode 100644
index 0000000..bdef74b
--- /dev/null
+++ b/assetFactory/faceController.cpp
@@ -0,0 +1,53 @@
+#include "faceController.h"
+#include "assetFactoryConfig.h"
+#include "maths.h"
+
+void
+FaceController::apply(ModelFactoryMesh & mesh, const std::string & name, Shape::CreatedFaces & faces) const
+{
+ 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
+ const auto faceVertexRange = mesh.fv_range(cf.second);
+ // get points
+ const std::vector baseVertices(faceVertexRange.begin(), faceVertexRange.end());
+ std::vector<glm::vec3> points;
+ std::transform(
+ faceVertexRange.begin(), faceVertexRange.end(), std::back_inserter(points), [&mesh](auto && v) {
+ return mesh.point(v);
+ });
+ const auto vertexCount = points.size();
+ const auto centre
+ = std::accumulate(points.begin(), points.end(), glm::vec3 {}) / static_cast<float>(vertexCount);
+ if (type == "extrude") {
+ Shape::CreatedFaces newFaces;
+ // mutate points
+ std::for_each(points.begin(), points.end(), [&mutation, &centre](auto && p) {
+ p = centre + ((p - centre) % mutation);
+ });
+ // create new vertices
+ std::vector<OpenMesh::VertexHandle> vertices;
+ std::transform(points.begin(), points.end(), std::back_inserter(vertices), [&mesh](auto && p) {
+ 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;
+ newFaces.emplace("extrusion",
+ mesh.add_face({baseVertices[idx], baseVertices[next], vertices[next], vertices[idx]}));
+ }
+ newFaces.emplace(name, mesh.add_face(vertices));
+ for (const auto & [name, faceController] : faceControllers) {
+ faceController.apply(mesh, name, newFaces);
+ }
+ faces.merge(std::move(newFaces));
+ }
+ }
+ }
+}
diff --git a/assetFactory/faceController.h b/assetFactory/faceController.h
new file mode 100644
index 0000000..64c33f3
--- /dev/null
+++ b/assetFactory/faceController.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "assetFactoryConfig_fwd.h"
+#include "mutation.h"
+#include "shape.h"
+#include <map>
+#include <string>
+
+class FaceController : public Mutation {
+public:
+ using FaceControllers = std::map<std::string, FaceController>;
+
+ void apply(ModelFactoryMesh & mesh, 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
new file mode 100644
index 0000000..1b89d14
--- /dev/null
+++ b/assetFactory/factoryMesh.cpp
@@ -0,0 +1,27 @@
+#include "factoryMesh.h"
+#include "assetFactoryConfig.h"
+#include "collections.hpp"
+#include "gfx/models/vertex.hpp"
+#include <glm/ext/matrix_transform.hpp>
+
+Mesh::Ptr
+FactoryMesh::createMesh() const
+{
+ constexpr glm::vec2 NullUV {};
+
+ ModelFactoryMesh mesh;
+ for (const auto & use : uses) {
+ use->createMesh(mesh, glm::identity<Mutation::Matrix>());
+ }
+ mesh.garbage_collection();
+
+ mesh.triangulate();
+ mesh.update_face_normals();
+ std::vector<Vertex> vertices;
+ for (const auto & face : mesh.faces()) {
+ for (const auto & vertex : mesh.fv_range(face)) {
+ vertices.emplace_back(mesh.point(vertex), NullUV, mesh.property(mesh.face_normals_pph(), face));
+ }
+ }
+ return std::make_shared<Mesh>(vertices, vectorOfN(vertices.size()));
+}
diff --git a/assetFactory/factoryMesh.h b/assetFactory/factoryMesh.h
new file mode 100644
index 0000000..f850893
--- /dev/null
+++ b/assetFactory/factoryMesh.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "gfx/models/mesh.h"
+#include "stdTypeDefs.hpp"
+#include "use.h"
+
+class FactoryMesh : public StdTypeDefs<FactoryMesh> {
+public:
+ Mesh::Ptr createMesh() const;
+
+ std::string id;
+ glm::vec3 size;
+ Use::Collection uses;
+};
diff --git a/assetFactory/modelFactory.cpp b/assetFactory/modelFactory.cpp
new file mode 100644
index 0000000..3a89157
--- /dev/null
+++ b/assetFactory/modelFactory.cpp
@@ -0,0 +1,14 @@
+#include "modelFactory.h"
+#include "assetFactoryConfig.h"
+#include "cuboid.h"
+#include "cylinder.h"
+#include "plane.h"
+
+ModelFactory::ModelFactory() :
+ shapes {
+ {"plane", std::make_shared<Plane>()},
+ {"cuboid", std::make_shared<Cuboid>()},
+ {"cylinder", std::make_shared<Cylinder>()},
+ }
+{
+}
diff --git a/assetFactory/modelFactory.h b/assetFactory/modelFactory.h
new file mode 100644
index 0000000..f2b1b48
--- /dev/null
+++ b/assetFactory/modelFactory.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "shape.h"
+
+class ModelFactory {
+public:
+ using Shapes = std::map<std::string, Shape::CPtr, std::less<>>;
+
+ ModelFactory();
+
+ Shapes shapes;
+};
diff --git a/assetFactory/mutation.cpp b/assetFactory/mutation.cpp
new file mode 100644
index 0000000..21d2a24
--- /dev/null
+++ b/assetFactory/mutation.cpp
@@ -0,0 +1,10 @@
+#include "mutation.h"
+#include <glm/gtx/transform.hpp>
+#include <maths.h>
+
+Mutation::Matrix
+Mutation::getMatrix() const
+{
+ return glm::translate(glm::identity<Matrix>(), position) * rotate_ypr(rotation)
+ * glm::scale(glm::identity<Matrix>(), scale);
+}
diff --git a/assetFactory/mutation.h b/assetFactory/mutation.h
new file mode 100644
index 0000000..440fab0
--- /dev/null
+++ b/assetFactory/mutation.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <glm/mat4x4.hpp>
+#include <glm/vec3.hpp>
+
+struct Mutation {
+ using Matrix = glm::mat4;
+
+ Matrix getMatrix() const;
+
+ glm::vec3 position {};
+ glm::vec3 rotation {};
+ glm::vec3 scale {1};
+};
diff --git a/assetFactory/object.cpp b/assetFactory/object.cpp
new file mode 100644
index 0000000..8b70676
--- /dev/null
+++ b/assetFactory/object.cpp
@@ -0,0 +1,17 @@
+#include "object.h"
+#include <algorithm>
+
+Object::Object(std::string i) : id {std::move(i)} { }
+
+Object::CreatedFaces
+Object::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
+{
+ CreatedFaces faces;
+ for (const auto & use : uses) {
+ auto useFaces = use->createMesh(mesh, mutation);
+ std::transform(useFaces.begin(), useFaces.end(), std::inserter(faces, faces.end()), [this](auto && face) {
+ return std::make_pair(id + ":" + face.first, std::move(face.second));
+ });
+ }
+ return faces;
+}
diff --git a/assetFactory/object.h b/assetFactory/object.h
new file mode 100644
index 0000000..f48b78a
--- /dev/null
+++ b/assetFactory/object.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "shape.h"
+#include "stdTypeDefs.hpp"
+#include "use.h"
+
+class Object : public StdTypeDefs<Object>, public Shape {
+public:
+ Object(std::string i);
+
+ CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const;
+
+ Use::Collection uses;
+ std::string id;
+};
diff --git a/assetFactory/plane.cpp b/assetFactory/plane.cpp
new file mode 100644
index 0000000..1e522ad
--- /dev/null
+++ b/assetFactory/plane.cpp
@@ -0,0 +1,15 @@
+#include "plane.h"
+#include "assetFactoryConfig.h"
+
+Plane::CreatedFaces
+Plane::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
+{
+ static constexpr std::array<glm::vec3, 4> VERTICES {{
+ {n, n, z},
+ {y, n, z},
+ {y, y, z},
+ {n, y, z},
+ }};
+
+ return {{"plane", mesh.add_face(addMutatedToMesh(mesh, VERTICES, mutation))}};
+}
diff --git a/assetFactory/plane.h b/assetFactory/plane.h
new file mode 100644
index 0000000..5e93ee4
--- /dev/null
+++ b/assetFactory/plane.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "shape.h"
+
+class Plane : public Shape {
+public:
+ CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const override;
+};
diff --git a/assetFactory/shape.cpp b/assetFactory/shape.cpp
new file mode 100644
index 0000000..0994898
--- /dev/null
+++ b/assetFactory/shape.cpp
@@ -0,0 +1,17 @@
+#include "shape.h"
+#include "assetFactoryConfig.h"
+#include "gfx/models/vertex.hpp"
+#include "maths.h"
+#include "shape.h"
+
+std::vector<OpenMesh::VertexHandle>
+Shape::addMutatedToMesh(
+ ModelFactoryMesh & mesh, const std::span<const glm::vec3> vertices, const Mutation::Matrix & mutation)
+{
+ std::vector<OpenMesh::VertexHandle> vhs;
+ std::transform(vertices.begin(), vertices.end(), std::back_inserter(vhs), [&mesh, &mutation](const auto & v) {
+ const auto p = v % mutation;
+ return mesh.add_vertex({p.x, p.y, p.z});
+ });
+ return vhs;
+}
diff --git a/assetFactory/shape.h b/assetFactory/shape.h
new file mode 100644
index 0000000..9510538
--- /dev/null
+++ b/assetFactory/shape.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "assetFactoryConfig_fwd.h"
+#include "mutation.h"
+#include "stdTypeDefs.hpp"
+#include <OpenMesh/Core/Mesh/Handles.hh>
+#include <map>
+#include <span>
+#include <string>
+
+class Vertex;
+
+class Shape : public StdTypeDefs<Shape> {
+public:
+ using CreatedFaces = std::multimap<std::string, OpenMesh::FaceHandle>;
+
+ static constexpr float z {}, y {.5}, n {-y}, o {1};
+
+ virtual ~Shape() = default;
+
+ virtual CreatedFaces createMesh(ModelFactoryMesh &, const Mutation::Matrix & mutation) const = 0;
+
+ static std::vector<OpenMesh::VertexHandle> addMutatedToMesh(
+ ModelFactoryMesh & mesh, const std::span<const glm::vec3> vertices, const Mutation::Matrix & mutation);
+};
diff --git a/assetFactory/use.cpp b/assetFactory/use.cpp
new file mode 100644
index 0000000..d191329
--- /dev/null
+++ b/assetFactory/use.cpp
@@ -0,0 +1,11 @@
+#include "use.h"
+
+Shape::CreatedFaces
+Use::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
+{
+ auto faces = type->createMesh(mesh, mutation * getMatrix());
+ for (const auto & [name, faceController] : faceControllers) {
+ faceController.apply(mesh, name, faces);
+ }
+ return faces;
+}
diff --git a/assetFactory/use.h b/assetFactory/use.h
new file mode 100644
index 0000000..4bfce97
--- /dev/null
+++ b/assetFactory/use.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "assetFactoryConfig_fwd.h"
+#include "faceController.h"
+#include "shape.h"
+#include "stdTypeDefs.hpp"
+
+class Use : public StdTypeDefs<Use>, public Mutation {
+public:
+ using FaceControllers = std::map<std::string, FaceController>;
+
+ Shape::CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const;
+
+ Shape::CPtr type;
+ std::string colour;
+ FaceControllers faceControllers;
+};