diff options
-rw-r--r-- | assetFactory/assetFactoryConfig.h | 28 | ||||
-rw-r--r-- | assetFactory/assetFactoryConfig_fwd.h | 8 | ||||
-rw-r--r-- | assetFactory/cuboid.cpp | 29 | ||||
-rw-r--r-- | assetFactory/cuboid.h | 8 | ||||
-rw-r--r-- | assetFactory/cylinder.cpp | 43 | ||||
-rw-r--r-- | assetFactory/cylinder.h | 8 | ||||
-rw-r--r-- | assetFactory/faceController.cpp | 53 | ||||
-rw-r--r-- | assetFactory/faceController.h | 20 | ||||
-rw-r--r-- | assetFactory/factoryMesh.cpp | 27 | ||||
-rw-r--r-- | assetFactory/factoryMesh.h | 14 | ||||
-rw-r--r-- | assetFactory/modelFactory.cpp | 14 | ||||
-rw-r--r-- | assetFactory/modelFactory.h | 12 | ||||
-rw-r--r-- | assetFactory/mutation.cpp | 10 | ||||
-rw-r--r-- | assetFactory/mutation.h | 14 | ||||
-rw-r--r-- | assetFactory/object.cpp | 17 | ||||
-rw-r--r-- | assetFactory/object.h | 15 | ||||
-rw-r--r-- | assetFactory/plane.cpp | 15 | ||||
-rw-r--r-- | assetFactory/plane.h | 8 | ||||
-rw-r--r-- | assetFactory/shape.cpp | 17 | ||||
-rw-r--r-- | assetFactory/shape.h | 25 | ||||
-rw-r--r-- | assetFactory/use.cpp | 11 | ||||
-rw-r--r-- | assetFactory/use.h | 17 | ||||
-rw-r--r-- | test/Jamfile.jam | 1 | ||||
-rw-r--r-- | test/test-modelFactory.cpp | 150 |
24 files changed, 564 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, ¢re](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; +}; diff --git a/test/Jamfile.jam b/test/Jamfile.jam index cefad7b..d802975 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -52,5 +52,6 @@ run test-text.cpp ; run test-enumDetails.cpp ; run test-render.cpp : : : <library>test ; run test-glContextBhvr.cpp ; +run test-modelFactory.cpp : : : <library>test ; compile test-static-enumDetails.cpp ; compile test-static-stream_support.cpp ; diff --git a/test/test-modelFactory.cpp b/test/test-modelFactory.cpp new file mode 100644 index 0000000..39362f5 --- /dev/null +++ b/test/test-modelFactory.cpp @@ -0,0 +1,150 @@ +#define BOOST_TEST_MODULE test_model_factory + +#include "testHelpers.h" +#include "testRenderOutput.h" +#include <boost/test/data/test_case.hpp> +#include <boost/test/unit_test.hpp> + +#include "assetFactory/factoryMesh.h" +#include "assetFactory/modelFactory.h" +#include "assetFactory/object.h" +#include "gfx/gl/sceneRenderer.h" +#include "lib/collection.hpp" +#include "lib/location.hpp" +#include "testMainWindow.h" +#include "ui/applicationBase.h" + +BOOST_GLOBAL_FIXTURE(ApplicationBase); +BOOST_GLOBAL_FIXTURE(TestMainWindow); + +const std::filesystem::path TMP {"/tmp"}; +class FactoryFixture : public TestRenderOutputSize<glm::ivec2 {2048, 2048}>, public SceneProvider { +public: + FactoryFixture() : sceneRenderer {size, output} { } + ~FactoryFixture() + { + glDisable(GL_DEBUG_OUTPUT); + auto outpath = (TMP / boost::unit_test::framework::current_test_case().full_name()).replace_extension(".tga"); + std::filesystem::create_directories(outpath.parent_path()); + Texture::save(outImage, size, outpath.c_str()); + } + void + content(const SceneShader & shader) const override + { + shader.basic.use(Location {{0, 0, 0}, {0, 0, 0}}); + meshes.apply(&Mesh::Draw); + } + void + lights(const SceneShader & shader) const override + { + shader.pointLight.add({-3, 1, 5}, {1, 1, 1}, .1F); + } + void + environment(const SceneShader &, const SceneRenderer & sceneRenderer) const override + { + sceneRenderer.setAmbientLight({.2, .2, .2}); + sceneRenderer.setDirectionalLight({.3, .3, .3}, east + south + south + down, *this); + } + void + shadows(const ShadowMapper & mapper) const override + { + mapper.dynamicPoint.use(Location {{0, 0, 0}, {0, 0, 0}}); + meshes.apply(&Mesh::Draw); + } + void + render(float dist = 10.f) + { + sceneRenderer.camera.setView({dist, dist, dist}, south + west + down); + sceneRenderer.render(*this); + } + Collection<const Mesh> meshes; + +private: + SceneRenderer sceneRenderer; +}; + +BOOST_FIXTURE_TEST_SUITE(m, FactoryFixture); +BOOST_AUTO_TEST_CASE(brush47) +{ + ModelFactory modelFactory; + { + auto wheel = std::make_shared<Object>("wheel"); + { + auto wheelCylinder = wheel->uses.emplace_back(std::make_shared<Use>()); + wheelCylinder->type = modelFactory.shapes.at("cylinder"); + wheelCylinder->position = {0, 0, 0.571}; + wheelCylinder->scale = {1.142, 1.142, 0.07}; + wheelCylinder->rotation = {0, 0, half_pi}; + wheelCylinder->colour = "#2C3539"; + } + modelFactory.shapes.emplace(wheel->id, wheel); + } + { + auto axel = std::make_shared<Object>("axel"); + for (float x : {-1.f, 1.f}) { + auto wheel = axel->uses.emplace_back(std::make_shared<Use>()); + wheel->type = modelFactory.shapes.at("wheel"); + wheel->position = {x * 0.717f, 0, 0}; + wheel->rotation = {0, x == 1.f ? pi : 0.f, 0}; + } + modelFactory.shapes.emplace(axel->id, axel); + } + { + auto bogey = std::make_shared<Object>("bogey"); + for (float y : {-2.f, 0.f, 2.f}) { + auto axel = bogey->uses.emplace_back(std::make_shared<Use>()); + axel->type = modelFactory.shapes.at("axel"); + axel->position = {0, y, 0}; + } + modelFactory.shapes.emplace(bogey->id, bogey); + } + FactoryMesh::Collection factoryMeshes; + { + unsigned short b {0}; + for (float y : {-6.f, 6.f}) { + auto bogey = factoryMeshes.emplace_back(std::make_shared<FactoryMesh>()); + bogey->id = "bogey" + std::to_string(b); + auto bogeyUse = bogey->uses.emplace_back(std::make_shared<Use>()); + bogeyUse->type = modelFactory.shapes.at("bogey"); + bogeyUse->position = {0, y, 0}; + bogeyUse->rotation = {0, b * pi, 0}; + b++; + } + } + { + auto body = factoryMeshes.emplace_back(std::make_shared<FactoryMesh>()); + body->id = "body"; + body->size = {2.69f, 19.38f, 3.9f}; + { + auto bodyLower = body->uses.emplace_back(std::make_shared<Use>()); + bodyLower->type = modelFactory.shapes.at("cuboid"); + bodyLower->position = {0, 0, 1.2}; + bodyLower->scale = {2.69, 19.38, 1.5}; + bodyLower->colour = "#1111DD"; + bodyLower->faceControllers["bottom"].colour = "#2C3539"; + auto & bodyUpper = bodyLower->faceControllers["top"]; + bodyUpper.type = "extrude"; + bodyUpper.scale = {1, .95f, 1}; + bodyUpper.position = {0, 0, 1.0}; + auto & roof = bodyUpper.faceControllers["top"]; + roof.type = "extrude"; + roof.scale = {.6f, .9f, 0}; + roof.position = {0, 0, 0.2}; + roof.smooth = true; + } + { + auto batteryBox = body->uses.emplace_back(std::make_shared<Use>()); + batteryBox->type = modelFactory.shapes.at("cuboid"); + batteryBox->position = {0, 0, .2}; + batteryBox->scale = {2.6, 4.5, 1}; + batteryBox->colour = "#2C3539"; + } + } + std::transform(factoryMeshes.begin(), factoryMeshes.end(), std::back_inserter(meshes.objects), + [](const FactoryMesh::CPtr & factoryMesh) -> Mesh::Ptr { + return factoryMesh->createMesh(); + }); + + render(20); +} +BOOST_AUTO_TEST_SUITE_END(); |