Sampler improvements; Add new LazyDict method
authorDaniel Hritzkiv <daniel.hritzkiv@gmail.com>
Mon, 4 Sep 2017 02:09:48 +0000 (22:09 -0400)
committerDaniel Hritzkiv <daniel.hritzkiv@gmail.com>
Mon, 11 Sep 2017 15:02:12 +0000 (11:02 -0400)
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
code/glTF2Asset.inl
code/glTF2AssetWriter.inl
code/glTF2Exporter.cpp
code/glTF2Exporter.h
code/glTF2Importer.cpp

index 711e823..aabd462 100644 (file)
@@ -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<T> Get(unsigned int i);
         Ref<T> Get(const char* id);
 
+        bool Has(const char* id);
+
         Ref<T> Create(const char* id);
         Ref<T> Create(const std::string& id)
             { return Create(id.c_str()); }
index bebaeba..5764c6f 100644 (file)
@@ -244,7 +244,17 @@ Ref<T> LazyDict<T>::Get(const char* id)
         return Ref<T>(mObjs, it->second);
     }
 
-    throw std::out_of_range("id \"" + std::string(id) + "\" Doesn't exist");
+    return Create(id);
+}
+
+template<class T>
+bool LazyDict<T>::Has(const char* id)
+{
+    id = T::TranslateId(mAsset, id);
+
+    typename IdDict::iterator it = mObjsById.find(id);
+
+    return it != mObjsById.end();
 }
 
 template<class T>
@@ -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");
index 69d54d9..f794317 100644 (file)
@@ -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<unsigned int>(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<unsigned int>(b.wrapT), w.mAl);
         }
-        if (b.minFilter) {
-            obj.AddMember("minFilter", b.minFilter, w.mAl);
+
+        if (b.magFilter != SamplerMagFilter::UNSET) {
+            obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl);
+        }
+
+        if (b.minFilter != SamplerMinFilter::UNSET) {
+            obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl);
         }
     }
 
index 9a2c1cd..fec7236 100644 (file)
@@ -223,50 +223,63 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     return acc;
 }
 
-void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> 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;
     };
+}
+
+void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> 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();
+    }
 
-    // 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;
+    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>& 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<Material> 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<Material> 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;
index 4b9fe0c..420c2af 100644 (file)
@@ -108,7 +108,7 @@ namespace Assimp
 
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
 
-        void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture);
+        void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> 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<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
index 08145f5..86301a3 100644 (file)
@@ -194,6 +194,27 @@ inline void SetMaterialTextureProperty(std::vector<int>& 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> 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);
+            }
+        }
     }
 }