Working read, import, export, and write of gltf2 (pbr) material
authorDaniel Hritzkiv <daniel.hritzkiv@gmail.com>
Wed, 30 Aug 2017 21:25:11 +0000 (17:25 -0400)
committerDaniel Hritzkiv <daniel.hritzkiv@gmail.com>
Mon, 11 Sep 2017 14:50:38 +0000 (10:50 -0400)
code/glTF2Asset.h
code/glTF2Asset.inl
code/glTF2AssetWriter.inl
code/glTF2Exporter.cpp
code/glTF2Exporter.h
code/glTF2Importer.cpp

index 5d99735..509fef1 100644 (file)
@@ -133,7 +133,6 @@ namespace glTF2
     struct Light;
     struct Skin;
 
-
     // Vec/matrix types, as raw float arrays
     typedef float (vec3)[3];
     typedef float (vec4)[4];
@@ -671,19 +670,29 @@ namespace glTF2
         inline void SetData(uint8_t* data, size_t length, Asset& r);
     };
 
-    struct ColorProperty
+    struct TextureInfo
     {
-        union {
-            vec4, vec3
-        } color;
-    }
+        Ref<Texture> texture;
+        unsigned int index;
+        unsigned int texCoord = 0;
+    };
+
+    struct NormalTextureInfo : TextureInfo
+    {
+        float scale = 1;
+    };
+
+    struct OcclusionTextureInfo : TextureInfo
+    {
+        float strength = 1;
+    };
 
     //! Holds a material property that can be a texture or a color (fallback for glTF 1)
-    struct FallbackTexProperty
+    /*struct FallbackTexProperty
     {
         Ref<Texture> texture;
-        ColorProperty color;
-    };
+        vec4 color;
+    };*/
 
     //! The material appearance of a primitive.
     struct Material : public Object
@@ -702,26 +711,26 @@ namespace glTF2
         };
 
         //PBR metallic roughness properties
-        ColorProperty baseColor;
-        Ref<Texture> baseColorTexture;
-        Ref<Texture> metallicRoughnessTexture;
+        vec4 baseColorFactor;
+        TextureInfo baseColorTexture;
+        TextureInfo metallicRoughnessTexture;
         float metallicFactor;
         float roughnessFactor;
 
         //other basic material properties
-        Ref<Texture> normalTexture;
-        Ref<Texture> occlusionTexture;
-        Ref<Texture> emissiveTexture;
-        ColorProperty emissiveFactor;
+        NormalTextureInfo normalTexture;
+        OcclusionTextureInfo occlusionTexture;
+        TextureInfo emissiveTexture;
+        vec3 emissiveFactor;
         std::string alphaMode;
         float alphaCutoff;
         bool doubleSided;
 
         //fallback material properties (compatible with non-pbr defintions)
-        FallbackTexProperty diffuse;
-        FallbackTexProperty emissive;
+        /*FallbackTexProperty diffuse;
+        FallbackTexProperty emission;
         FallbackTexProperty specular;
-        Ref<Texture> normal;
+        Ref<Texture> normal;*/
 
         Technique technique;
 
index bf8cb5a..9485804 100644 (file)
@@ -128,6 +128,12 @@ namespace {
         return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
     }
 
+    inline Value* FindNumber(Value& val, const char* id)
+    {
+        Value::MemberIterator it = val.FindMember(id);
+        return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
+    }
+
     inline Value* FindUInt(Value& val, const char* id)
     {
         Value::MemberIterator it = val.FindMember(id);
@@ -225,7 +231,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
     }
 
     T* inst = new T();
-    inst->id = std::string(mDictId) + "[" + std::to_string(i) + "]";
+    inst->id = std::string(mDictId) + "_" + std::to_string(i);
     inst->oIndex = i;
     ReadMember(obj, "name", inst->name);
     inst->Read(obj, mAsset);
@@ -706,15 +712,42 @@ inline void Texture::Read(Value& obj, Asset& r)
 }
 
 namespace {
-    inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out)
+    inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out)
+    {
+        if (Value* index = FindUInt(*prop, "index")) {
+            out.texture = r.textures.Retrieve(index->GetUint());
+        }
+
+        if (Value* texcoord = FindUInt(*prop, "texCoord")) {
+            out.texCoord = texcoord->GetUint();
+        }
+    }
+
+    inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out)
     {
-        //@TODO: update this format
         if (Value* prop = FindMember(vals, propName)) {
-            if (prop->IsUint()) {
-                out.texture = r.textures.Retrieve(prop->GetUint());
+            SetTextureProperties(r, prop, out);
+        }
+    }
+
+    inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out)
+    {
+        if (Value* prop = FindMember(vals, propName)) {
+            SetTextureProperties(r, prop, out);
+
+            if (Value* scale = FindNumber(*prop, "scale")) {
+                out.scale = scale->GetDouble();
             }
-            else {
-                ReadValue(*prop, out.color);
+        }
+    }
+
+    inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out)
+    {
+        if (Value* prop = FindMember(vals, propName)) {
+            SetTextureProperties(r, prop, out);
+
+            if (Value* strength = FindNumber(*prop, "strength")) {
+                out.strength = strength->GetDouble();
             }
         }
     }
@@ -724,33 +757,24 @@ inline void Material::Read(Value& material, Asset& r)
 {
     SetDefaults();
 
-    if (Value* values = FindObject(material, "values")) {
-
-
-        ReadMember(*values, "transparency", transparency);
-    }
-
     if (Value* values = FindObject(material, "pbrMetallicRoughness")) {
-        //pbr
-        ReadMaterialProperty(r, *values, "baseColorFactor", this->baseColor);
-        ReadMaterialProperty(r, *values, "baseColorTexture", this->baseColorTexture);
-
-        //non-pbr fallback
-        ReadMaterialProperty(r, *values, "baseColorFactor", this->diffuse);
-        ReadMaterialProperty(r, *values, "baseColorTexture", this->diffuse);
-
-        ReadMember(*values, "metallicFactor", metallicFactor);
+        ReadMember(*values, "baseColorFactor", this->baseColorFactor);
+        ReadTextureProperty(r, *values, "baseColorTexture", this->baseColorTexture);
+        ReadTextureProperty(r, *values, "metallicRoughnessTexture", this->metallicRoughnessTexture);
+        ReadMember(*values, "metallicFactor", this->metallicFactor);
+        ReadMember(*values, "roughnessFactor", this->roughnessFactor);
     }
 
-    ReadMaterialProperty(r, *values, "normalTexture", this->normalTexture);
-    ReadMaterialProperty(r, *values, "normalTexture", this->normal);
-    ReadMaterialProperty(r, *values, "occlusionTexture", this->occlusionTexture);
-    ReadMaterialProperty(r, *values, "emissiveTexture", this->emissiveTexture);
-    ReadMember(*values, "metallicFactor", emissiveFactor);
+    ReadTextureProperty(r, material, "normalTexture", this->normalTexture);
+    ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture);
+    ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture);
+    ReadMember(material, "emissiveFactor", this->emissiveFactor);
 
-    ReadMember(material, "doubleSided", doubleSided);
+    ReadMember(material, "doubleSided", this->doubleSided);
+    ReadMember(material, "alphaMode", this->alphaMode);
+    ReadMember(material, "alphaCutoff", this->alphaCutoff);
 
-    if (Value* extensions = FindObject(material, "extensions")) {
+    /* if (Value* extensions = FindObject(material, "extensions")) {
         if (r.extensionsUsed.KHR_materials_common) {
             if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
                 if (Value* tnq = FindString(*ext, "technique")) {
@@ -762,9 +786,9 @@ inline void Material::Read(Value& material, Asset& r)
                 }
 
                 if (Value* values = FindObject(*ext, "values")) {
-                    ReadMaterialProperty(r, *values, "ambient", this->ambient);
-                    ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
-                    ReadMaterialProperty(r, *values, "specular", this->specular);
+                    ReadTextureProperty(r, *values, "ambient", this->ambient);
+                    ReadTextureProperty(r, *values, "diffuse", this->diffuse);
+                    ReadTextureProperty(r, *values, "specular", this->specular);
 
                     ReadMember(*values, "doubleSided", doubleSided);
                     ReadMember(*values, "transparent", transparent);
@@ -773,25 +797,28 @@ inline void Material::Read(Value& material, Asset& r)
                 }
             }
         }
-    }
+    } */
 }
 
 namespace {
     void SetVector(vec4& v, float x, float y, float z, float w)
         { v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
+
+    void SetVector(vec3& v, float x, float y, float z)
+        { v[0] = x; v[1] = y; v[2] = z; }
 }
 
 inline void Material::SetDefaults()
 {
-    SetVector(ambient.color, 0, 0, 0, 1);
-    SetVector(diffuse.color, 0, 0, 0, 1);
-    SetVector(specular.color, 0, 0, 0, 1);
-    SetVector(emission.color, 0, 0, 0, 1);
-
+    //pbr materials
+    SetVector(baseColorFactor, 1, 1, 1, 1);
+    SetVector(emissiveFactor, 0, 0, 0);
+    metallicFactor = 1.0;
+    roughnessFactor = 1.0;
+
+    alphaMode = "OPAQUE";
+    alphaCutoff = 0.5;
     doubleSided = false;
-    transparent = false;
-    transparency = 1.0;
-    shininess = 0.0;
 
     technique = Technique_undefined;
 }
@@ -833,6 +860,10 @@ namespace {
 
 inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
 {
+    if (Value* name = FindMember(pJSON_Object, "name")) {
+        this->name = name->GetString();
+    }
+
        /****************** Mesh primitives ******************/
        if (Value* primitives = FindArray(pJSON_Object, "primitives")) {
         this->primitives.resize(primitives->Size());
@@ -1055,7 +1086,7 @@ inline void Node::Read(Value& obj, Asset& r)
 
     // TODO load "skeletons", "skin", "jointName"
 
-    if (Value* extensions = FindObject(obj, "extensions")) {
+    /*if (Value* extensions = FindObject(obj, "extensions")) {
         if (r.extensionsUsed.KHR_materials_common) {
 
             if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
@@ -1065,7 +1096,7 @@ inline void Node::Read(Value& obj, Asset& r)
             }
 
         }
-    }
+    }*/
 }
 
 inline void Scene::Read(Value& obj, Asset& r)
index ed8ee80..a939e38 100644 (file)
@@ -72,6 +72,12 @@ namespace glTF2 {
             return val;
         }
 
+        inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) {
+            val.SetDouble(r);
+
+            return val;
+        }
+
         template<class T>
         inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
             if (v.empty()) return;
@@ -196,51 +202,148 @@ namespace glTF2 {
     }
 
     namespace {
-        inline void WriteTex(Value& obj, Ref<Texture> texture, const char* propName, MemoryPoolAllocator<>& al)
+        inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
+        {
+            tex.SetObject();
+            tex.AddMember("index", t.texture->index, al);
+
+            if (t.texCoord != 0) {
+                tex.AddMember("texCoord", t.texCoord, al);
+            }
+        }
+
+        inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
         {
-            if (texture) {
+
+            if (t.texture) {
                 Value tex;
-                tex.SetObject();
-                tex.AddMember("index", texture->index, al);
+
+                SetTexBasic(t, tex, al);
+
                 obj.AddMember(StringRef(propName), tex, al);
             }
         }
 
-        inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al)
+        inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
         {
-            WriteTex(obj, prop.texture, propName, al);
-            if (!prop.texture) {
-                Value col;
-                obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al);
+
+            if (t.texture) {
+                Value tex;
+
+                SetTexBasic(t, tex, al);
+
+                if (t.scale != 1) {
+                    tex.AddMember("scale", t.scale, al);
+                }
+
+                obj.AddMember(StringRef(propName), tex, al);
             }
         }
+
+        inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
+        {
+
+            if (t.texture) {
+                Value tex;
+
+                SetTexBasic(t, tex, al);
+
+                if (t.strength != 1) {
+                    tex.AddMember("strength", t.strength, al);
+                }
+
+                obj.AddMember(StringRef(propName), tex, al);
+            }
+        }
+
+        template<size_t N>
+        inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
+        {
+            Value arr;
+            obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
+        }
+
+        template<size_t N>
+        inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, float(&defaultVal)[N], MemoryPoolAllocator<>& al)
+        {
+            if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
+                WriteVec(obj, prop, propName, al);
+            }
+        }
+
+        inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
+        {
+            Value num;
+            obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
+        }
     }
 
     inline void Write(Value& obj, Material& m, AssetWriter& w)
     {
-        if (m.transparent) {
-            obj.AddMember("alphaMode", "BLEND", w.mAl);
+        if (!m.name.empty()) {
+            obj.AddMember("name", m.name, w.mAl);
+        }
+
+        Value pbrMetallicRoughness;
+        pbrMetallicRoughness.SetObject();
+        {
+            WriteTex(pbrMetallicRoughness, m.baseColorTexture, "baseColorTexture", w.mAl);
+            WriteTex(pbrMetallicRoughness, m.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
+
+            //@TODO: define this as a constant?
+            vec4 defaultEmissiveFactor = {1, 1, 1, 1};
+            WriteVec(pbrMetallicRoughness, m.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl);
+
+            if (m.metallicFactor != 1) {
+                WriteFloat(pbrMetallicRoughness, m.metallicFactor, "metallicFactor", w.mAl);
+            }
+
+            if (m.roughnessFactor != 1) {
+                WriteFloat(pbrMetallicRoughness, m.roughnessFactor, "roughnessFactor", w.mAl);
+            }
         }
 
-        Value v;
+        if (pbrMetallicRoughness.MemberCount() > 0) {
+            obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
+        }
+
+        WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
+        WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
+        WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
+
+        //@TODO: define this as a constant?
+        vec3 defaultEmissiveFactor = {0, 0, 0};
+        WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);
+
+        if (m.alphaCutoff != 0.5) {
+            WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
+        }
+
+        if (m.alphaMode != "OPAQUE") {
+            obj.AddMember("alphaMode", m.alphaMode, w.mAl);
+        }
+
+        if (m.doubleSided) {
+            obj.AddMember("doubleSided", m.doubleSided, w.mAl);
+        }
+
+        /*Value v;
         v.SetObject();
         {
             if (m.transparent && !m.diffuse.texture) {
                 m.diffuse.color[3] = m.transparency;
             }
-            WriteColorOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl);
-            WriteColorOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl);
-            WriteColorOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl);
-            WriteColorOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl);
+            WriteVecOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl);
+            WriteVecOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl);
+            WriteVecOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl);
+            WriteVecOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl);
             v.AddMember("shininessFactor", m.shininess, w.mAl);
         }
         v.AddMember("type", "commonPhong", w.mAl);
         Value ext;
         ext.SetObject();
         ext.AddMember("KHR_materials_common", v, w.mAl);
-        obj.AddMember("extensions", ext, w.mAl);
-
-        WriteTex(obj, m.normal, "normalTexture", w.mAl);
+        obj.AddMember("extensions", ext, w.mAl);*/
     }
 
     namespace {
@@ -263,8 +366,6 @@ namespace glTF2 {
 
     inline void Write(Value& obj, Mesh& m, AssetWriter& w)
     {
-               /********************* Name **********************/
-               obj.AddMember("name", m.name, w.mAl);
 
                /**************** Mesh extensions ****************/
                if(m.Extension.size() > 0)
@@ -617,7 +718,7 @@ namespace glTF2 {
                 exts.PushBack(StringRef("KHR_binary_glTF"), mAl);
 
             // This is used to export common materials with GLTF 2.
-            exts.PushBack(StringRef("KHR_materials_common"), mAl);
+            //exts.PushBack(StringRef("KHR_materials_common"), mAl);
         }
 
         if (!exts.Empty())
index 68f2f44..f59c280 100644 (file)
@@ -234,12 +234,6 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     return acc;
 }
 
-namespace {
-    void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
-        if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
-    }
-}
-
 void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture)
 {
     std::string samplerId = mAsset->FindUniqueID("", "sampler");
@@ -286,11 +280,11 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture)
     texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear;
 }
 
-void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt)
+void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
 {
     aiString tex;
     if (mat->GetTextureCount(tt) > 0) {
-        if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) {
+        if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
             std::string path = tex.C_Str();
 
             if (path.size() > 0) {
@@ -332,15 +326,21 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
     }
 }
 
-void glTF2Exporter::GetMatColorOrTex(const aiMaterial* mat, TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
+void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
 {
     aiColor4D col;
     if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
-        prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a;
+        prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
     }
-    GetMatTex(mat, prop.texture, tt);
 }
 
+void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
+{
+    aiColor3D col;
+    if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
+        prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
+    }
+}
 
 void glTF2Exporter::ExportMaterials()
 {
@@ -348,7 +348,6 @@ void glTF2Exporter::ExportMaterials()
     for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
         const aiMaterial* mat = mScene->mMaterials[i];
 
-
         std::string name;
         if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
             name = aiName.C_Str();
@@ -357,15 +356,20 @@ void glTF2Exporter::ExportMaterials()
 
         Ref<Material> m = mAsset->materials.Create(name);
 
-        GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT);
-        GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE);
-        GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR);
-        GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE);
-        GetMatTex(mat, m->normal, aiTextureType_NORMALS);
+        GetMatTex(mat, m->baseColorTexture.texture, aiTextureType_DIFFUSE);
+        GetMatTex(mat, m->metallicRoughnessTexture.texture, aiTextureType_UNKNOWN, 0);//get unknown slot
+        GetMatTex(mat, m->emissiveTexture.texture, aiTextureType_EMISSIVE);
+        GetMatTex(mat, m->normalTexture.texture, aiTextureType_NORMALS);
+        GetMatTex(mat, m->occlusionTexture.texture, aiTextureType_LIGHTMAP);
 
-        m->transparent = mat->Get(AI_MATKEY_OPACITY, m->transparency) == aiReturn_SUCCESS && m->transparency != 1.0;
+        GetMatColor(mat, m->baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
+        GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
 
-        GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS);
+        mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
+        mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff);
+        mat->Get("$mat.gltf.metallicFactor", 0, 0, m->metallicFactor);
+        mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->roughnessFactor);
+        mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode);
     }
 }
 
@@ -566,13 +570,17 @@ void glTF2Exporter::ExportMeshes()
 
                        DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg);
             comp_allow = false;
-               }
+        }
+
+        std::string name = aim->mName.C_Str();
 
-        std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh");
+        std::string meshId = mAsset->FindUniqueID(name, "mesh");
         Ref<Mesh> m = mAsset->meshes.Create(meshId);
         m->primitives.resize(1);
         Mesh::Primitive& p = m->primitives.back();
 
+        m->name = name;
+
         p.material = mAsset->materials.Get(aim->mMaterialIndex);
 
                /******************* Vertices ********************/
index 17cc9cf..2ba0143 100644 (file)
@@ -66,8 +66,13 @@ namespace glTF2
 
     class Asset;
     struct TexProperty;
+    struct TextureInfo;
     struct Node;
     struct Texture;
+
+    // Vec/matrix types, as raw float arrays
+    typedef float (vec3)[3];
+    typedef float (vec4)[4];
 }
 
 namespace Assimp
@@ -102,8 +107,9 @@ namespace Assimp
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
 
         void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture);
-        void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt);
-        void GetMatColorOrTex(const aiMaterial* mat, glTF2::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
+        void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
+        void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
+        void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
         void ExportMetadata();
         void ExportMaterials();
         void ExportMeshes();
index bd4f426..25cb391 100644 (file)
@@ -141,6 +141,11 @@ static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
     out.r = v[0]; out.g = v[1]; out.b = v[2];
 }
 
+static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
+{
+    out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
+}
+
 static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
 {
     out.x = v[0]; out.y = v[1]; out.z = v[2];
@@ -159,30 +164,58 @@ static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
     o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
 }
 
-inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TexProperty prop, aiMaterial* mat,
-    aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx)
+inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
 {
-    if (prop.texture) {
-        if (prop.texture->source) {
-            aiString uri(prop.texture->source->uri);
-
-            int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
-            if (texIdx != -1) { // embedded
-                // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
-                uri.data[0] = '*';
-                uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
-            }
+    aiColor4D col;
+    CopyValue(prop, col);
+    mat->AddProperty(&col, 1, pKey, type, idx);
+}
+
+inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
+{
+    vec4 prop4;
 
+    prop4[0] = prop[0];
+    prop4[1] = prop[1];
+    prop4[2] = prop[2];
+    prop4[3] = 1;
+
+    return SetMaterialColorProperty(r, prop4, mat, pKey, type, idx);
+}
+
+inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, int texSlot)
+{
+    if (prop.texture && prop.texture->source) {
+        aiString uri(prop.texture->source->uri);
+
+        int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
+        if (texIdx != -1) { // embedded
+            // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
+            uri.data[0] = '*';
+            uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
+        }
+
+        if (texSlot < 0) {
             mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
         }
-    }
-    else {
-        aiColor4D col;
-        CopyValue(prop.color, col);
-        mat->AddProperty(&col, 1, pKey, type, idx);
+        else {
+            mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType,
+                texSlot));
+        }
     }
 }
 
+//import textures that are only supported in pbr contexts
+inline void SetMaterialPBRTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, unsigned int texSlot)
+{
+    return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, aiTextureType_UNKNOWN, texSlot);
+}
+
+inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType)
+{
+    return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, texType, -1);
+}
+
 void glTF2Importer::ImportMaterials(glTF2::Asset& r)
 {
     mScene->mNumMaterials = unsigned(r.materials.Size());
@@ -193,18 +226,23 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r)
 
         Material& mat = r.materials[i];
 
-        /*if (!mat.name.empty())*/ {
-            aiString str(mat.id /*mat.name*/);
-            aimat->AddProperty(&str, AI_MATKEY_NAME);
-        }
+        aiString str(mat.id);
+        aimat->AddProperty(&str, AI_MATKEY_NAME);
 
-        SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
-        SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
-        SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
+        SetMaterialColorProperty(r, mat.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
+        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.baseColorTexture, aimat, aiTextureType_DIFFUSE);
+        SetMaterialPBRTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, 0);
+        aimat->AddProperty(&mat.metallicFactor, 1, "$mat.gltf.metallicFactor");
+        aimat->AddProperty(&mat.roughnessFactor, 1, "$mat.gltf.roughnessFactor");
 
-        if (mat.shininess > 0.f) {
-            aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);
-        }
+        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
+        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
+        SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
+        SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
+
+        aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
+        aimat->AddProperty(&mat.alphaMode, 1, "$mat.gltf.alphaMode");
+        aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff");
     }
 }
 
@@ -295,7 +333,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
             aiMesh* aim = new aiMesh();
             meshes.push_back(aim);
 
-            aim->mName = mesh.id;
+            aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
+
             if (mesh.primitives.size() > 1) {
                 size_t& len = aim->mName.length;
                 aim->mName.data[len] = '-';