summaryrefslogtreecommitdiff
path: root/assetFactory/assimp.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-04-14 18:03:34 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-04-14 18:03:34 +0100
commit5776a36b454fac04617313da011d7aa2b0e834d3 (patch)
tree1eb96d07e9a17a51e5763f397fc003f762cd2e75 /assetFactory/assimp.cpp
parentMerge branch 'model-factory-textures' (diff)
parentAdd an asset template and use it to define all the foliage assets in the plan... (diff)
downloadilt-5776a36b454fac04617313da011d7aa2b0e834d3.tar.bz2
ilt-5776a36b454fac04617313da011d7aa2b0e834d3.tar.xz
ilt-5776a36b454fac04617313da011d7aa2b0e834d3.zip
Merge branch 'assimp'
Diffstat (limited to 'assetFactory/assimp.cpp')
-rw-r--r--assetFactory/assimp.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp
new file mode 100644
index 0000000..840c5a9
--- /dev/null
+++ b/assetFactory/assimp.cpp
@@ -0,0 +1,130 @@
+#include "assimp.h"
+#include "assetFactory.h"
+#include "collections.hpp"
+#include "ptr.hpp"
+#include "resource.h"
+#include <assimp/cimport.h>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <future>
+#include <stb/stb_image.h>
+
+template<typename T>
+glm::vec<3, T>
+operator*(const aiVector3t<T> & v)
+{
+ return {v.x, v.y, v.z};
+}
+
+template<typename T>
+glm::vec<2, T>
+operator!(const aiVector3t<T> & v)
+{
+ return {v.x, v.y};
+}
+
+#define AIRANGE(parent, member) \
+ std::span \
+ { \
+ (parent)->m##member, (parent)->mNum##member \
+ }
+
+using SceneCPtr = std::shared_ptr<const aiScene>;
+class AssImpNode : public Shape {
+public:
+ AssImpNode(SceneCPtr scene, const aiNode * node) : scene(std::move(scene)), node(node) { }
+
+ SceneCPtr scene;
+ const aiNode * node;
+
+ CreatedFaces
+ createMesh(ModelFactoryMesh & mesh, float) const
+ {
+ CreatedFaces faces;
+ addMesh(faces, mesh, node);
+ return faces;
+ }
+
+ void
+ addMesh(CreatedFaces & faces, ModelFactoryMesh & mesh, const aiNode * node) const
+ {
+ for (const auto & m : AIRANGE(node, Meshes)) {
+ addMesh(faces, mesh, scene->mMeshes[m]);
+ }
+ for (const auto & n : AIRANGE(node, Children)) {
+ addMesh(faces, mesh, n);
+ }
+ }
+
+ void
+ addMesh(CreatedFaces & faces, ModelFactoryMesh & mesh, const aiMesh * amesh) const
+ {
+ const auto vhs = AIRANGE(amesh, Vertices) * [&mesh](auto && v) {
+ return mesh.add_vertex(*v);
+ };
+ const auto & m = scene->mMaterials[amesh->mMaterialIndex]->GetName();
+
+ GLuint material {};
+ if (auto mf = Persistence::ParseBase::getShared<AssetFactory>("assetFactory")) {
+ material = mf->getMaterialIndex(m.C_Str());
+ }
+
+ for (const auto & f : AIRANGE(amesh, Faces)) {
+ const auto fvhs = AIRANGE(&f, Indices) * [&vhs](auto && i) {
+ return vhs[i];
+ };
+ const auto fh = faces.emplace(mesh.add_namedFace(amesh->mName.C_Str(), fvhs))->second;
+ if (amesh->HasTextureCoords(0)) {
+ for (auto idx = f.mIndices; const auto fheh : mesh.fh_range(fh)) {
+ const auto ouv = !amesh->mTextureCoords[0][*idx++];
+ mesh.set_texcoord2D(fheh, ouv);
+ mesh.property(mesh.materialFaceProperty, fh) = material;
+ }
+ }
+ }
+ }
+};
+
+static_assert(TextureOptions::MapMode::Repeat == static_cast<TextureOptions::MapMode>(aiTextureMapMode_Wrap));
+static_assert(TextureOptions::MapMode::Clamp == static_cast<TextureOptions::MapMode>(aiTextureMapMode_Clamp));
+static_assert(TextureOptions::MapMode::Decal == static_cast<TextureOptions::MapMode>(aiTextureMapMode_Decal));
+static_assert(TextureOptions::MapMode::Mirror == static_cast<TextureOptions::MapMode>(aiTextureMapMode_Mirror));
+
+void
+AssImp::postLoad()
+{
+ SceneCPtr scene {
+ aiImportFile(Resource::mapPath(path).c_str(), aiProcess_RemoveRedundantMaterials), &aiReleaseImport};
+ if (!scene) {
+ throw std::runtime_error("Failed to load asset library: " + path);
+ }
+ if (auto mf = Persistence::ParseBase::getShared<AssetFactory>("assetFactory")) {
+ const auto root = AIRANGE(scene->mRootNode, Children);
+ std::transform(
+ root.begin(), root.end(), std::inserter(mf->shapes, mf->shapes.end()), [&scene](const aiNode * m) {
+ return AssetFactory::Shapes::value_type {m->mName.C_Str(), std::make_shared<AssImpNode>(scene, m)};
+ });
+ const auto materials = AIRANGE(scene, Materials);
+ std::transform(materials.begin(), materials.end(),
+ std::inserter(mf->textureFragments, mf->textureFragments.end()), [&scene](const aiMaterial * m) {
+ aiString path;
+ m->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path);
+ auto texture = std::make_shared<TextureFragment>();
+ texture->id = m->GetName().C_Str();
+ texture->path = path.C_Str();
+ m->Get(AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0), texture->mapmodeU);
+ m->Get(AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0), texture->mapmodeV);
+ texture->image = Worker::addWork([t = scene->GetEmbeddedTexture(path.C_Str())]() {
+ return std::make_unique<Image>(
+ std::span {reinterpret_cast<unsigned char *>(t->pcData), t->mWidth}, STBI_rgb_alpha);
+ });
+ return AssetFactory::TextureFragments::value_type {texture->id, texture};
+ });
+ }
+}
+
+bool
+AssImp::persist(Persistence::PersistenceStore & store)
+{
+ return STORE_TYPE && STORE_MEMBER(path);
+}