From 5366105ed2ed2b135cb78cec7580029ca65e62c6 Mon Sep 17 00:00:00 2001 From: Jack Diver Date: Thu, 28 Mar 2019 14:30:22 +0000 Subject: [PATCH] Removing STL headers from filameshio (#1050) * Removed STL headers from filameshio/MeshReader.h modified the samples to work the same, and made an effort to remedy the jsbindings although I'm not experienced with them. * Fixed assignment operators for MaterialRegistry * Fixed formating for MeshReader Material Registry * Forgot one format * Forgot another format --- .../include/filameshio/MeshReader.h | 44 ++++++- libs/filameshio/src/MeshReader.cpp | 109 ++++++++++++++++-- samples/sample_cloth.cpp | 18 +-- samples/sample_normal_map.cpp | 18 +-- web/filament-js/jsbindings.cpp | 23 +++- 5 files changed, 181 insertions(+), 31 deletions(-) diff --git a/libs/filameshio/include/filameshio/MeshReader.h b/libs/filameshio/include/filameshio/MeshReader.h index a5927e83c4..054a49ccb7 100644 --- a/libs/filameshio/include/filameshio/MeshReader.h +++ b/libs/filameshio/include/filameshio/MeshReader.h @@ -18,10 +18,7 @@ #define TNT_FILAMENT_FILAMESHIO_MESHREADER_H #include -#include - -#include -#include +#include namespace filament { class Engine; @@ -30,8 +27,13 @@ namespace filament { class MaterialInstance; } +namespace utils { + class Path; +} + namespace filamesh { + /** * This API can be used to read meshes stored in the "filamesh" format produced * by the command line tool of the same name. This file format is documented in @@ -40,7 +42,39 @@ namespace filamesh { class MeshReader { public: using Callback = void(*)(void* buffer, size_t size, void* user); - using MaterialRegistry = std::map; + + // Class to track material instances + class MaterialRegistry { + public: + MaterialRegistry(); + MaterialRegistry(const MaterialRegistry& rhs); + MaterialRegistry& operator=(const MaterialRegistry& rhs); + ~MaterialRegistry(); + MaterialRegistry(MaterialRegistry&&); + MaterialRegistry& operator=(MaterialRegistry&&); + + filament::MaterialInstance* getMaterialInstance(const utils::CString& name); + + void registerMaterialInstance(const utils::CString& name, + filament::MaterialInstance* materialInstance); + + void unregisterMaterialInstance(const utils::CString& name); + + void unregisterAll(); + + std::size_t numRegistered() const noexcept; + + void getRegisteredMaterials(filament::MaterialInstance** materialList, + utils::CString* materialNameList) const; + + void getRegisteredMaterials(filament::MaterialInstance** materialList) const; + + void getRegisteredMaterialNames(utils::CString* materialNameList) const; + + private: + struct MaterialRegistryImpl; + MaterialRegistryImpl* mImpl; + }; struct Mesh { utils::Entity renderable; diff --git a/libs/filameshio/src/MeshReader.cpp b/libs/filameshio/src/MeshReader.cpp index 9679ccbc7a..16c27af65f 100644 --- a/libs/filameshio/src/MeshReader.cpp +++ b/libs/filameshio/src/MeshReader.cpp @@ -32,6 +32,8 @@ #include #include +#include +#include #include #if !defined(WIN32) @@ -46,6 +48,99 @@ using namespace filament::math; #define DEFAULT_MATERIAL "DefaultMaterial" +//------------------------------------------------------------------------------ +//-------------------------Begin Material Registry------------------------------ +//------------------------------------------------------------------------------ + +struct MeshReader::MaterialRegistry::MaterialRegistryImpl { + std::map materialMap; +}; + +// Create the implementation +MeshReader::MaterialRegistry::MaterialRegistry() + : mImpl(new MaterialRegistryImpl) { +} +// Deep copy the implementation +MeshReader::MaterialRegistry::MaterialRegistry(const MaterialRegistry& rhs) + : mImpl(new MaterialRegistryImpl(*rhs.mImpl)) { +} +MeshReader::MaterialRegistry& MeshReader::MaterialRegistry::operator=(const MaterialRegistry& rhs) { + *mImpl = *rhs.mImpl; + return *this; +} +// Delete the implementation +MeshReader::MaterialRegistry::~MaterialRegistry() { + delete mImpl; +} + +// Default move construction +MeshReader::MaterialRegistry::MaterialRegistry(MaterialRegistry&&) = default; + +MeshReader::MaterialRegistry& MeshReader::MaterialRegistry::operator=(MaterialRegistry&& rhs) { + *mImpl = std::move(*rhs.mImpl); + return *this; +} + +filament::MaterialInstance* MeshReader::MaterialRegistry::getMaterialInstance( + const utils::CString& name) { + // Try to find the requested material + auto miter = mImpl->materialMap.find(name); + // If it exists, return it + if (miter != mImpl->materialMap.end()) { + return miter->second; + } + // If it doesn't exist, give a dummy value + return nullptr; +} + +void MeshReader::MaterialRegistry::registerMaterialInstance(const utils::CString& name, + filament::MaterialInstance* materialInstance) { + // Add the material to our map + mImpl->materialMap[name] = materialInstance; +} + +void MeshReader::MaterialRegistry::unregisterMaterialInstance(const utils::CString& name) { + auto miter = mImpl->materialMap.find(name); + // Remove it from the map if it existed + if (miter != mImpl->materialMap.end()) { + mImpl->materialMap.erase(miter); + } +} +void MeshReader::MaterialRegistry::unregisterAll() { + mImpl->materialMap.clear(); +} + +std::size_t MeshReader::MaterialRegistry::numRegistered() const noexcept { + return mImpl->materialMap.size(); +} + +void MeshReader::MaterialRegistry::getRegisteredMaterials(filament::MaterialInstance** materialList, + utils::CString* materialNameList) const { + for (const auto& materialPair : mImpl->materialMap) { + (*materialNameList++) = materialPair.first; + (*materialList++) = materialPair.second; + } +} + +void MeshReader::MaterialRegistry::getRegisteredMaterials( + filament::MaterialInstance** materialList) const { + for (const auto& materialPair : mImpl->materialMap) { + (*materialList++) = materialPair.second; + } +} + +void MeshReader::MaterialRegistry::getRegisteredMaterialNames( + utils::CString* materialNameList) const { + for (const auto& materialPair : mImpl->materialMap) { + (*materialNameList++) = materialPair.first; + } +} + +//------------------------------------------------------------------------------ +//---------------------------End Material Registry------------------------------ +//------------------------------------------------------------------------------ + + static size_t fileSize(int fd) { size_t filesize; filesize = (size_t) lseek(fd, 0, SEEK_END); @@ -87,7 +182,7 @@ MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine, void const* data, Callback destructor, void* user, MaterialInstance* defaultMaterial) { MaterialRegistry reg; - reg[DEFAULT_MATERIAL] = defaultMaterial; + reg.registerMaterialInstance(utils::CString(DEFAULT_MATERIAL), defaultMaterial); return loadMeshFromBuffer(engine, data, destructor, user, reg); } @@ -249,18 +344,18 @@ MeshReader::Mesh MeshReader::loadMeshFromBuffer(filament::Engine* engine, RenderableManager::Builder builder(header->parts); builder.boundingBox(header->aabb); - const auto defaultmi = materials.at(DEFAULT_MATERIAL); + const auto defaultmi = materials.getMaterialInstance(utils::CString(DEFAULT_MATERIAL)); for (size_t i = 0; i < header->parts; i++) { builder.geometry(i, RenderableManager::PrimitiveType::TRIANGLES, mesh.vertexBuffer, mesh.indexBuffer, parts[i].offset, parts[i].minIndex, parts[i].maxIndex, parts[i].indexCount); - const auto& materialName = partsMaterial[i]; - const auto miter = materials.find(materialName); - if (miter == materials.end()) { + const utils::CString materialName(partsMaterial[i].c_str(), partsMaterial[i].size()); + const auto mat = materials.getMaterialInstance(materialName); + if (mat == nullptr) { builder.material(i, defaultmi); - materials[materialName] = defaultmi; + materials.registerMaterialInstance(materialName, defaultmi); } else { - builder.material(i, miter->second); + builder.material(i, mat); } } builder.build(*engine, mesh.renderable); diff --git a/samples/sample_cloth.cpp b/samples/sample_cloth.cpp index 9408b19e46..cb34955a8a 100644 --- a/samples/sample_cloth.cpp +++ b/samples/sample_cloth.cpp @@ -53,7 +53,7 @@ using namespace utils; static std::vector g_filenames; -static std::map g_materialInstances; +static MeshReader::MaterialRegistry g_materialInstances; static std::vector g_meshes; static const Material* g_material; static Entity g_light; @@ -127,9 +127,12 @@ static void cleanup(Engine* engine, View* view, Scene* scene) { for (auto map : g_maps) { engine->destroy(map.second); } - for (auto material : g_materialInstances) { - engine->destroy(material.second); + std::vector materialList(g_materialInstances.numRegistered()); + g_materialInstances.getRegisteredMaterials(materialList.data()); + for (auto material : materialList) { + engine->destroy(material); } + g_materialInstances.unregisterAll(); engine->destroy(g_material); EntityManager& em = EntityManager::get(); for (auto mesh : g_meshes) { @@ -207,14 +210,15 @@ static void setup(Engine* engine, View* view, Scene* scene) { g_material = Material::Builder().package(pkg.getData(), pkg.getSize()) .build(*engine); - g_materialInstances["DefaultMaterial"] = g_material->createInstance(); + const utils::CString defaultMaterialName("DefaultMaterial"); + g_materialInstances.registerMaterialInstance(defaultMaterialName, g_material->createInstance()); TextureSampler sampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); sampler.setAnisotropy(8.0f); - g_materialInstances["DefaultMaterial"]->setParameter("normalMap", normal, sampler); - g_materialInstances["DefaultMaterial"]->setParameter("basecolorMap", basecolor, sampler); - g_materialInstances["DefaultMaterial"]->setParameter("roughnessMap", roughness, sampler); + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter("normalMap", normal, sampler); + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter("basecolorMap", basecolor, sampler); + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter("roughnessMap", roughness, sampler); auto& tcm = engine->getTransformManager(); for (const auto& filename : g_filenames) { diff --git a/samples/sample_normal_map.cpp b/samples/sample_normal_map.cpp index 1dce38a267..51c9cfcbea 100644 --- a/samples/sample_normal_map.cpp +++ b/samples/sample_normal_map.cpp @@ -52,7 +52,7 @@ using namespace utils; static std::vector g_filenames; -static std::map g_materialInstances; +static MeshReader::MaterialRegistry g_materialInstances; static std::vector g_meshes; static const Material* g_material; static Entity g_light; @@ -150,9 +150,12 @@ static int handleCommandLineArgments(int argc, char* argv[], Config* config) { static void cleanup(Engine* engine, View*, Scene*) { engine->destroy(g_normalMap); engine->destroy(g_clearCoatNormalMap); - for (auto material : g_materialInstances) { - engine->destroy(material.second); + std::vector materialList(g_materialInstances.numRegistered()); + g_materialInstances.getRegisteredMaterials(materialList.data()); + for (auto material : materialList) { + engine->destroy(material); } + g_materialInstances.unregisterAll(); engine->destroy(g_material); EntityManager& em = EntityManager::get(); for (auto mesh : g_meshes) { @@ -297,21 +300,22 @@ static void setup(Engine* engine, View*, Scene* scene) { g_material = Material::Builder().package(pkg.getData(), pkg.getSize()) .build(*engine); - g_materialInstances["DefaultMaterial"] = g_material->createInstance(); + const utils::CString defaultMaterialName("DefaultMaterial"); + g_materialInstances.registerMaterialInstance(defaultMaterialName, g_material->createInstance()); TextureSampler sampler(TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR, TextureSampler::MagFilter::LINEAR, TextureSampler::WrapMode::REPEAT); sampler.setAnisotropy(8.0f); if (hasNormalMap) { - g_materialInstances["DefaultMaterial"]->setParameter("normalMap", g_normalMap, sampler); + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter("normalMap", g_normalMap, sampler); } if (hasClearCoatNormalMap) { - g_materialInstances["DefaultMaterial"]->setParameter( + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter( "clearCoatNormalMap", g_clearCoatNormalMap, sampler); } if (hasBaseColorMap) { - g_materialInstances["DefaultMaterial"]->setParameter( + g_materialInstances.getMaterialInstance(defaultMaterialName)->setParameter( "baseColorMap", g_baseColorMap, sampler); } diff --git a/web/filament-js/jsbindings.cpp b/web/filament-js/jsbindings.cpp index 323f402f44..322f90f546 100644 --- a/web/filament-js/jsbindings.cpp +++ b/web/filament-js/jsbindings.cpp @@ -1061,12 +1061,25 @@ register_vector("RegistryKeys"); class_("MeshReader$MaterialRegistry") .constructor<>() .function("size", &MeshReader::MaterialRegistry::size) - .function("get", internal::MapAccess::get) - .function("set", internal::MapAccess::set) + .function("get", EMBIND_LAMBDA(val, (MeshReader::MaterialRegistry* self, std::string k), { + const utils::CString name(k.c_str(), k.size()); + auto i = self->getMaterialInstance(name); + if (i == nullptr) { + return val::undefined(); + } else { + return val(i); + } + }), allow_raw_pointers()) + .function("set", EMBIND_LAMBDA(void, (MeshReader::MaterialRegistry* self, std::string k, filament::MaterialInstance* v), { + const utils::CString name(k.c_str(), k.size()); + self->registerMaterialInstance(name, v); + }), allow_raw_pointers()) .function("keys", EMBIND_LAMBDA(std::vector, (MeshReader::MaterialRegistry* self), { - std::vector result; - for (const auto& pair : *self) { - result.emplace_back(pair.first); + std::vector names(self->numRegistered()); + self->getMaterialNames(names.data()); + std::vector result(self->numRegistered()); + for (const auto& name : names) { + result.emplace_back(name.c_str()); } return result; }), allow_raw_pointers());