From 715d4879fdd096ac82367984fdb22117d48737a4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 15 Feb 2023 02:26:06 +0000 Subject: 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 --- assetFactory/assetFactoryConfig.h | 28 ++++++++++++++++++ assetFactory/assetFactoryConfig_fwd.h | 8 ++++++ assetFactory/cuboid.cpp | 29 +++++++++++++++++++ assetFactory/cuboid.h | 8 ++++++ assetFactory/cylinder.cpp | 43 ++++++++++++++++++++++++++++ assetFactory/cylinder.h | 8 ++++++ assetFactory/faceController.cpp | 53 +++++++++++++++++++++++++++++++++++ assetFactory/faceController.h | 20 +++++++++++++ assetFactory/factoryMesh.cpp | 27 ++++++++++++++++++ assetFactory/factoryMesh.h | 14 +++++++++ assetFactory/modelFactory.cpp | 14 +++++++++ assetFactory/modelFactory.h | 12 ++++++++ assetFactory/mutation.cpp | 10 +++++++ assetFactory/mutation.h | 14 +++++++++ assetFactory/object.cpp | 17 +++++++++++ assetFactory/object.h | 15 ++++++++++ assetFactory/plane.cpp | 15 ++++++++++ assetFactory/plane.h | 8 ++++++ assetFactory/shape.cpp | 17 +++++++++++ assetFactory/shape.h | 25 +++++++++++++++++ assetFactory/use.cpp | 11 ++++++++ assetFactory/use.h | 17 +++++++++++ 22 files changed, 413 insertions(+) create mode 100644 assetFactory/assetFactoryConfig.h create mode 100644 assetFactory/assetFactoryConfig_fwd.h create mode 100644 assetFactory/cuboid.cpp create mode 100644 assetFactory/cuboid.h create mode 100644 assetFactory/cylinder.cpp create mode 100644 assetFactory/cylinder.h create mode 100644 assetFactory/faceController.cpp create mode 100644 assetFactory/faceController.h create mode 100644 assetFactory/factoryMesh.cpp create mode 100644 assetFactory/factoryMesh.h create mode 100644 assetFactory/modelFactory.cpp create mode 100644 assetFactory/modelFactory.h create mode 100644 assetFactory/mutation.cpp create mode 100644 assetFactory/mutation.h create mode 100644 assetFactory/object.cpp create mode 100644 assetFactory/object.h create mode 100644 assetFactory/plane.cpp create mode 100644 assetFactory/plane.h create mode 100644 assetFactory/shape.cpp create mode 100644 assetFactory/shape.h create mode 100644 assetFactory/use.cpp create mode 100644 assetFactory/use.h (limited to 'assetFactory') 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 +#include +#include +#include + +namespace OpenMesh { + template struct glmvec : public VectorT { + using VectorT::VectorT; + glmvec(const VectorT & v) : VectorT {v} { } + operator glm::vec() const + { + glm::vec 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; + using Normal = OpenMesh::glmvec; +}; 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 class PolyMesh_ArrayKernelT; +} +struct ModelFactoryTraits; + +using ModelFactoryMesh = OpenMesh::PolyMesh_ArrayKernelT; 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 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(std::round(15.F * std::sqrt(glm::length(scale)))); + std::vector bottom(P), top(P); + std::generate_n(bottom.begin(), P, [a = 0.f, step = two_pi / static_cast(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(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(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 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(vertexCount); + if (type == "extrude") { + Shape::CreatedFaces newFaces; + // mutate points + std::for_each(points.begin(), points.end(), [&mutation, ¢re](auto && p) { + p = centre + ((p - centre) % mutation); + }); + // create new vertices + std::vector 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 +#include + +class FaceController : public Mutation { +public: + using FaceControllers = std::map; + + 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 + +Mesh::Ptr +FactoryMesh::createMesh() const +{ + constexpr glm::vec2 NullUV {}; + + ModelFactoryMesh mesh; + for (const auto & use : uses) { + use->createMesh(mesh, glm::identity()); + } + mesh.garbage_collection(); + + mesh.triangulate(); + mesh.update_face_normals(); + std::vector 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(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 { +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()}, + {"cuboid", std::make_shared()}, + {"cylinder", std::make_shared()}, + } +{ +} 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>; + + 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 +#include + +Mutation::Matrix +Mutation::getMatrix() const +{ + return glm::translate(glm::identity(), position) * rotate_ypr(rotation) + * glm::scale(glm::identity(), 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 +#include + +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 + +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, 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 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 +Shape::addMutatedToMesh( + ModelFactoryMesh & mesh, const std::span vertices, const Mutation::Matrix & mutation) +{ + std::vector 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 +#include +#include +#include + +class Vertex; + +class Shape : public StdTypeDefs { +public: + using CreatedFaces = std::multimap; + + 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 addMutatedToMesh( + ModelFactoryMesh & mesh, const std::span 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, public Mutation { +public: + using FaceControllers = std::map; + + Shape::CreatedFaces createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const; + + Shape::CPtr type; + std::string colour; + FaceControllers faceControllers; +}; -- cgit v1.2.3