From a9c4fa84b5f48fccfc099d8c300144d5ba1807eb Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 3 Sep 2017 22:09:48 -0400 Subject: [PATCH] Sampler improvements; Add new LazyDict method Samplers are now imported into assimp internal format from textures; Samplers have defaults as per spec; Sampler enums are strongly typed with UNSET values; Samplers are exported properly; Sampler filters are exported as well; Samplers are re-used across textures on export Default sampler values are not written --- code/glTF2Asset.h | 25 ++++++----- code/glTF2Asset.inl | 28 +++++++----- code/glTF2AssetWriter.inl | 23 ++++++---- code/glTF2Exporter.cpp | 91 +++++++++++++++++++++++---------------- code/glTF2Exporter.h | 2 +- code/glTF2Importer.cpp | 21 +++++++++ 6 files changed, 123 insertions(+), 67 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 711e8231b..aabd462d8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -242,15 +242,17 @@ namespace glTF2 }; //! Values for the Sampler::magFilter field - enum SamplerMagFilter + enum class SamplerMagFilter: unsigned int { + UNSET = 0, SamplerMagFilter_Nearest = 9728, SamplerMagFilter_Linear = 9729 }; //! Values for the Sampler::minFilter field - enum SamplerMinFilter + enum class SamplerMinFilter: unsigned int { + UNSET = 0, SamplerMinFilter_Nearest = 9728, SamplerMinFilter_Linear = 9729, SamplerMinFilter_Nearest_Mipmap_Nearest = 9984, @@ -260,11 +262,12 @@ namespace glTF2 }; //! Values for the Sampler::wrapS and Sampler::wrapT field - enum SamplerWrap + enum class SamplerWrap: unsigned int { - SamplerWrap_Clamp_To_Edge = 33071, - SamplerWrap_Mirrored_Repeat = 33648, - SamplerWrap_Repeat = 10497 + UNSET = 0, + Clamp_To_Edge = 33071, + Mirrored_Repeat = 33648, + Repeat = 10497 }; //! Values for the Texture::format and Texture::internalFormat fields @@ -795,10 +798,10 @@ namespace glTF2 struct Sampler : public Object { - SamplerMagFilter magFilter; //!< The texture magnification filter. (required) - SamplerMinFilter minFilter; //!< The texture minification filter. (required) - SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required) - SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) + SamplerMagFilter magFilter; //!< The texture magnification filter. + SamplerMinFilter minFilter; //!< The texture minification filter. + SamplerWrap wrapS; //!< The texture wrapping in the S direction. + SamplerWrap wrapT; //!< The texture wrapping in the T direction. Sampler() { SetDefaults(); } void Read(Value& obj, Asset& r); @@ -955,6 +958,8 @@ namespace glTF2 Ref Get(unsigned int i); Ref Get(const char* id); + bool Has(const char* id); + Ref Create(const char* id); Ref Create(const std::string& id) { return Create(id.c_str()); } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index bebaeba53..5764c6ff6 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -244,7 +244,17 @@ Ref LazyDict::Get(const char* id) return Ref(mObjs, it->second); } - throw std::out_of_range("id \"" + std::string(id) + "\" Doesn't exist"); + return Create(id); +} + +template +bool LazyDict::Has(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + + return it != mObjsById.end(); } template @@ -697,6 +707,7 @@ inline void Sampler::Read(Value& obj, Asset& r) { SetDefaults(); + ReadMember(obj, "name", name); ReadMember(obj, "magFilter", magFilter); ReadMember(obj, "minFilter", minFilter); ReadMember(obj, "wrapS", wrapS); @@ -705,10 +716,11 @@ inline void Sampler::Read(Value& obj, Asset& r) inline void Sampler::SetDefaults() { - magFilter = SamplerMagFilter_Linear; - minFilter = SamplerMinFilter_Linear; - wrapS = SamplerWrap_Repeat; - wrapT = SamplerWrap_Repeat; + //only wrapping modes have defaults + wrapS = SamplerWrap::Repeat; + wrapT = SamplerWrap::Repeat; + magFilter = SamplerMagFilter::UNSET; + minFilter = SamplerMinFilter::UNSET; } inline void Texture::Read(Value& obj, Asset& r) @@ -883,7 +895,6 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. - //@TODO: update this int undPos = 0; Mesh::AccessorList* vec = 0; if (GetAttribVector(prim, attr, vec, undPos)) { @@ -943,7 +954,6 @@ inline void Node::Read(Value& obj, Asset& r) } } - if (Value* matrix = FindArray(obj, "matrix")) { ReadValue(*matrix, this->matrix); } @@ -978,7 +988,6 @@ inline void Scene::Read(Value& obj, Asset& r) } } - inline void AssetMetadata::Read(Document& doc) { // read the version, etc. @@ -1013,8 +1022,6 @@ inline void AssetMetadata::Read(Document& doc) } } - - // // Asset methods implementation // @@ -1142,7 +1149,6 @@ inline void Asset::SetAsBinary() } } - inline void Asset::ReadExtensionsUsed(Document& doc) { Value* extsUsed = FindArray(doc, "extensionsUsed"); diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 69d54d97b..f7943172e 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -467,17 +467,24 @@ namespace glTF2 { inline void Write(Value& obj, Sampler& b, AssetWriter& w) { - if (b.wrapS) { - obj.AddMember("wrapS", b.wrapS, w.mAl); + if (!b.name.empty()) { + obj.AddMember("name", b.name, w.mAl); } - if (b.wrapT) { - obj.AddMember("wrapT", b.wrapT, w.mAl); + + if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) { + obj.AddMember("wrapS", static_cast(b.wrapS), w.mAl); } - if (b.magFilter) { - obj.AddMember("magFilter", b.magFilter, w.mAl); + + if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) { + obj.AddMember("wrapT", static_cast(b.wrapT), w.mAl); } - if (b.minFilter) { - obj.AddMember("minFilter", b.minFilter, w.mAl); + + if (b.magFilter != SamplerMagFilter::UNSET) { + obj.AddMember("magFilter", static_cast(b.magFilter), w.mAl); + } + + if (b.minFilter != SamplerMinFilter::UNSET) { + obj.AddMember("minFilter", static_cast(b.minFilter), w.mAl); } } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9a2c1cd75..fec7236e3 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -223,50 +223,63 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu return acc; } -void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture) +inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map) { - std::string samplerId = mAsset->FindUniqueID("", "sampler"); - texture->sampler = mAsset->samplers.Create(samplerId); - - aiTextureMapMode mapU, mapV; - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); - - switch (mapU) { - case aiTextureMapMode_Wrap: - texture->sampler->wrapS = SamplerWrap_Repeat; - break; + switch (map) { case aiTextureMapMode_Clamp: - texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge; + wrap = SamplerWrap::Clamp_To_Edge; break; case aiTextureMapMode_Mirror: - texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat; + wrap = SamplerWrap::Mirrored_Repeat; break; - case aiTextureMapMode_Decal: - default: - texture->sampler->wrapS = SamplerWrap_Repeat; - break; - }; - - switch (mapV) { case aiTextureMapMode_Wrap: - texture->sampler->wrapT = SamplerWrap_Repeat; - break; - case aiTextureMapMode_Clamp: - texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge; - break; - case aiTextureMapMode_Mirror: - texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat; - break; case aiTextureMapMode_Decal: default: - texture->sampler->wrapT = SamplerWrap_Repeat; + wrap = SamplerWrap::Repeat; break; }; +} - // Hard coded Texture filtering options because I do not know where to find them in the aiMaterial. - texture->sampler->magFilter = SamplerMagFilter_Linear; - texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear; +void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, aiTextureType tt, unsigned int slot) +{ + aiString aId; + std::string id; + if (aiGetMaterialString(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), tt, slot, &aId) == AI_SUCCESS) { + id = aId.C_Str(); + } + + if (mAsset->samplers.Has(id.c_str())) { + texture->sampler = mAsset->samplers.Get(id.c_str()); + } else { + id = mAsset->FindUniqueID(id, "sampler"); + + texture->sampler = mAsset->samplers.Create(id.c_str()); + + aiTextureMapMode mapU, mapV; + SamplerMagFilter filterMag; + SamplerMinFilter filterMin; + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapS, mapU); + } + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapT, mapV); + } + + if (aiGetMaterialInteger(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), tt, slot, (int*)&filterMag) == AI_SUCCESS) { + texture->sampler->magFilter = filterMag; + } + + if (aiGetMaterialInteger(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), tt, slot, (int*)&filterMin) == AI_SUCCESS) { + texture->sampler->minFilter = filterMin; + } + + aiString name; + if (aiGetMaterialString(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), tt, slot, &name) == AI_SUCCESS) { + texture->sampler->name = name.C_Str(); + } + } } void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) @@ -324,7 +337,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe texture->source->uri = path; } - GetTexSampler(mat, texture); + GetTexSampler(mat, texture, tt, slot); } } } @@ -390,17 +403,23 @@ void glTF2Exporter::ExportMaterials() for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; + std::string id = "material_" + std::to_string(i); + + Ref m = mAsset->materials.Create(id); + std::string name; if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); } name = mAsset->FindUniqueID(name, "material"); - Ref m = mAsset->materials.Create(name); + m->name = name; GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_UNKNOWN, 0);//get unknown slot GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); + mat->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); + mat->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP); @@ -409,8 +428,6 @@ void glTF2Exporter::ExportMaterials() mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff); - mat->Get("$mat.gltf.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); - mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode); bool hasPbrSpecularGlossiness; diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 4b9fe0ce0..420c2afa6 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -108,7 +108,7 @@ namespace Assimp void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); - void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture); + void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture, aiTextureType tt, unsigned int slot); void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx); void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx); void GetMatTex(const aiMaterial* mat, glTF2::Ref& texture, aiTextureType tt, unsigned int slot); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 08145f5fe..86301a3f4 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -194,6 +194,27 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& const char *texCoordName = (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str(); mat->AddProperty(&prop.texCoord, 1, texCoordName, texType, texSlot); + + if (prop.texture->sampler) { + Ref sampler = prop.texture->sampler; + + aiString name(sampler->name); + aiString id(sampler->id); + + mat->AddProperty(&name, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), texType, texSlot); + mat->AddProperty(&id, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), texType, texSlot); + + mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); + + if (sampler->magFilter != SamplerMagFilter::UNSET) { + mat->AddProperty(&sampler->magFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), texType, texSlot); + } + + if (sampler->minFilter != SamplerMinFilter::UNSET) { + mat->AddProperty(&sampler->minFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), texType, texSlot); + } + } } }