浏览代码

Merge pull request #1015 from ascandal/feature/fix-glTF-validator-errors

Fix glTF validator errors
Kim Kulling 9 年之前
父节点
当前提交
f94b7287fc
共有 6 个文件被更改,包括 203 次插入23 次删除
  1. 16 0
      CHANGES
  2. 40 8
      code/glTFAsset.h
  3. 32 9
      code/glTFAsset.inl
  4. 34 5
      code/glTFAssetWriter.inl
  5. 80 1
      code/glTFExporter.cpp
  6. 1 0
      code/glTFExporter.h

+ 16 - 0
CHANGES

@@ -2,6 +2,22 @@
 CHANGELOG
 CHANGELOG
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
+3.2.1 (2016-10-01)
+
+FEATURES:
+  - Updated glTF exporter to meet 1.0 specification.
+
+FIXES/HOUSEKEEPING:
+  - Fixed glTF Validator errors for exported glTF format.
+
+ISSUES:
+  - Hard coded sampler setting for
+    - magFilter
+    - minFilter
+  - void* in ExportData for accessor max and min.
+
+
+
 3.2.0 (2015-11-03)
 3.2.0 (2015-11-03)
 
 
 FEATURES:
 FEATURES:

+ 40 - 8
code/glTFAsset.h

@@ -236,6 +236,32 @@ namespace glTF
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
     };
     };
 
 
+    //! Values for the Sampler::magFilter field
+    enum SamplerMagFilter
+    {
+        SamplerMagFilter_Nearest = 9728,
+        SamplerMagFilter_Linear = 9729
+    };
+
+    //! Values for the Sampler::minFilter field
+    enum SamplerMinFilter
+    {
+        SamplerMinFilter_Nearest = 9728,
+        SamplerMinFilter_Linear = 9729,
+        SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
+        SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
+        SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
+        SamplerMinFilter_Linear_Mipmap_Linear = 9987
+    };
+
+    //! Values for the Sampler::wrapS and Sampler::wrapT field
+    enum SamplerWrap
+    {
+        SamplerWrap_Clamp_To_Edge = 33071,
+        SamplerWrap_Mirrored_Repeat = 33648,
+        SamplerWrap_Repeat = 10497
+    };
+
     //! Values for the Texture::format and Texture::internalFormat fields
     //! Values for the Texture::format and Texture::internalFormat fields
     enum TextureFormat
     enum TextureFormat
     {
     {
@@ -377,8 +403,8 @@ namespace glTF
         ComponentType componentType; //!< The datatype of components in the attribute. (required)
         ComponentType componentType; //!< The datatype of components in the attribute. (required)
         unsigned int count;          //!< The number of attributes referenced by this accessor. (required)
         unsigned int count;          //!< The number of attributes referenced by this accessor. (required)
         AttribType::Value type;      //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
         AttribType::Value type;      //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
-        //std::vector<float> max;    //!< Maximum value of each component in this attribute.
-        //std::vector<float> min;    //!< Minimum value of each component in this attribute.
+        std::vector<float> max;      //!< Maximum value of each component in this attribute.
+        std::vector<float> min;      //!< Minimum value of each component in this attribute.
 
 
         unsigned int GetNumComponents();
         unsigned int GetNumComponents();
         unsigned int GetBytesPerComponent();
         unsigned int GetBytesPerComponent();
@@ -812,8 +838,14 @@ namespace glTF
 
 
     struct Sampler : public Object
     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)
+
         Sampler() {}
         Sampler() {}
         void Read(Value& obj, Asset& r);
         void Read(Value& obj, Asset& r);
+        void SetDefaults();
     };
     };
 
 
     struct Scene : public Object
     struct Scene : public Object
@@ -860,8 +892,8 @@ namespace glTF
     //! A texture and its sampler.
     //! A texture and its sampler.
     struct Texture : public Object
     struct Texture : public Object
     {
     {
-        //Ref<Sampler> source; //!< The ID of the sampler used by this texture. (required)
-        Ref<Image> source; //!< The ID of the image used by this texture. (required)
+        Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
+        Ref<Image> source;    //!< The ID of the image used by this texture. (required)
 
 
         //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
         //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
         //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
         //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
@@ -921,7 +953,7 @@ namespace glTF
     //! (Implemented in glTFAssetWriter.h)
     //! (Implemented in glTFAssetWriter.h)
     template<class T>
     template<class T>
     void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
     void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
-    
+
 
 
     //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
     //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
     //! It is the owner the loaded objects, so when it is destroyed it also deletes them
     //! It is the owner the loaded objects, so when it is destroyed it also deletes them
@@ -983,7 +1015,7 @@ namespace glTF
         int version; //!< The glTF format version (should be 1)
         int version; //!< The glTF format version (should be 1)
 
 
         void Read(Document& doc);
         void Read(Document& doc);
-        
+
         AssetMetadata()
         AssetMetadata()
             : premultipliedAlpha(false)
             : premultipliedAlpha(false)
             , version(0)
             , version(0)
@@ -1049,7 +1081,7 @@ namespace glTF
         LazyDict<Mesh>        meshes;
         LazyDict<Mesh>        meshes;
         LazyDict<Node>        nodes;
         LazyDict<Node>        nodes;
         //LazyDict<Program>   programs;
         //LazyDict<Program>   programs;
-        //LazyDict<Sampler>   samplers;
+        LazyDict<Sampler>     samplers;
         LazyDict<Scene>       scenes;
         LazyDict<Scene>       scenes;
         //LazyDict<Shader>    shaders;
         //LazyDict<Shader>    shaders;
         //LazyDict<Skin>      skins;
         //LazyDict<Skin>      skins;
@@ -1074,7 +1106,7 @@ namespace glTF
             , meshes        (*this, "meshes")
             , meshes        (*this, "meshes")
             , nodes         (*this, "nodes")
             , nodes         (*this, "nodes")
             //, programs    (*this, "programs")
             //, programs    (*this, "programs")
-            //, samplers    (*this, "samplers")
+            , samplers      (*this, "samplers")
             , scenes        (*this, "scenes")
             , scenes        (*this, "scenes")
             //, shaders     (*this, "shaders")
             //, shaders     (*this, "shaders")
             //, skins       (*this, "skins")
             //, skins       (*this, "skins")

+ 32 - 9
code/glTFAsset.inl

@@ -53,7 +53,7 @@ using namespace Assimp;
 namespace glTF {
 namespace glTF {
 
 
 namespace {
 namespace {
-    
+
     //
     //
     // JSON Value reading helpers
     // JSON Value reading helpers
     //
     //
@@ -62,7 +62,7 @@ namespace {
     struct ReadHelper { static bool Read(Value& val, T& out) {
     struct ReadHelper { static bool Read(Value& val, T& out) {
         return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
         return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
     }};
     }};
-    
+
     template<> struct ReadHelper<bool> { static bool Read(Value& val, bool& out) {
     template<> struct ReadHelper<bool> { static bool Read(Value& val, bool& out) {
         return val.IsBool() ? out = val.GetBool(), true : false;
         return val.IsBool() ? out = val.GetBool(), true : false;
     }};
     }};
@@ -70,7 +70,7 @@ namespace {
     template<> struct ReadHelper<float> { static bool Read(Value& val, float& out) {
     template<> struct ReadHelper<float> { static bool Read(Value& val, float& out) {
         return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
         return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
     }};
     }};
-    
+
     template<unsigned int N> struct ReadHelper<float[N]> { static bool Read(Value& val, float (&out)[N]) {
     template<unsigned int N> struct ReadHelper<float[N]> { static bool Read(Value& val, float (&out)[N]) {
         if (!val.IsArray() || val.Size() != N) return false;
         if (!val.IsArray() || val.Size() != N) return false;
         for (unsigned int i = 0; i < N; ++i) {
         for (unsigned int i = 0; i < N; ++i) {
@@ -312,7 +312,7 @@ inline void Buffer::Read(Value& obj, Asset& r)
             if (file) {
             if (file) {
                 bool ok = LoadFromStream(*file, byteLength);
                 bool ok = LoadFromStream(*file, byteLength);
                 delete file;
                 delete file;
-                
+
                 if (!ok)
                 if (!ok)
                     throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" );
                     throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" );
             }
             }
@@ -439,7 +439,7 @@ inline void BufferView::Read(Value& obj, Asset& r)
     if (bufferId) {
     if (bufferId) {
         buffer = r.buffers.Get(bufferId);
         buffer = r.buffers.Get(bufferId);
     }
     }
-        
+
     byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
     byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
     byteLength = MemberOrDefault(obj, "byteLength", 0u);
     byteLength = MemberOrDefault(obj, "byteLength", 0u);
 }
 }
@@ -599,7 +599,7 @@ inline Image::Image()
 
 
 inline void Image::Read(Value& obj, Asset& r)
 inline void Image::Read(Value& obj, Asset& r)
 {
 {
-    // Check for extensions first (to detect binary embedded data) 
+    // Check for extensions first (to detect binary embedded data)
     if (Value* extensions = FindObject(obj, "extensions")) {
     if (Value* extensions = FindObject(obj, "extensions")) {
         if (r.extensionsUsed.KHR_binary_glTF) {
         if (r.extensionsUsed.KHR_binary_glTF) {
             if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
             if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
@@ -665,12 +665,35 @@ inline void Image::SetData(uint8_t* data, size_t length, Asset& r)
     }
     }
 }
 }
 
 
+inline void Sampler::Read(Value& obj, Asset& r)
+{
+    SetDefaults();
+
+    ReadMember(obj, "magFilter", magFilter);
+    ReadMember(obj, "minFilter", minFilter);
+    ReadMember(obj, "wrapS", wrapS);
+    ReadMember(obj, "wrapT", wrapT);
+}
+
+inline void Sampler::SetDefaults()
+{
+    magFilter = SamplerMagFilter_Linear;
+    minFilter = SamplerMinFilter_Linear;
+    wrapS = SamplerWrap_Repeat;
+    wrapT = SamplerWrap_Repeat;
+}
+
 inline void Texture::Read(Value& obj, Asset& r)
 inline void Texture::Read(Value& obj, Asset& r)
 {
 {
     const char* sourcestr;
     const char* sourcestr;
     if (ReadMember(obj, "source", sourcestr)) {
     if (ReadMember(obj, "source", sourcestr)) {
         source = r.images.Get(sourcestr);
         source = r.images.Get(sourcestr);
     }
     }
+
+    const char* samplerstr;
+    if (ReadMember(obj, "sampler", samplerstr)) {
+        sampler = r.samplers.Get(samplerstr);
+    }
 }
 }
 
 
 namespace {
 namespace {
@@ -1132,7 +1155,7 @@ inline void Node::Read(Value& obj, Asset& r)
         }
         }
     }
     }
 
 
-    
+
     if (Value* matrix = FindArray(obj, "matrix")) {
     if (Value* matrix = FindArray(obj, "matrix")) {
         ReadValue(*matrix, this->matrix);
         ReadValue(*matrix, this->matrix);
     }
     }
@@ -1408,13 +1431,13 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
         id = buffer;
         id = buffer;
         it = mUsedIds.find(id);
         it = mUsedIds.find(id);
     }
     }
-    
+
     return id;
     return id;
 }
 }
 
 
 namespace Util {
 namespace Util {
 
 
-    inline 
+    inline
     bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
     bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
         if ( NULL == const_uri ) {
         if ( NULL == const_uri ) {
             return false;
             return false;

+ 34 - 5
code/glTFAssetWriter.inl

@@ -56,7 +56,16 @@ namespace glTF {
         inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
         inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
             val.SetArray();
             val.SetArray();
             val.Reserve(N, al);
             val.Reserve(N, al);
-			for (decltype(N) i = 0; i < N; ++i) {
+            for (decltype(N) i = 0; i < N; ++i) {
+                val.PushBack(r[i], al);
+            }
+            return val;
+        }
+
+        inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
+            val.SetArray();
+            val.Reserve(r.size(), al);
+            for (int i = 0; i < r.size(); ++i) {
                 val.PushBack(r[i], al);
                 val.PushBack(r[i], al);
             }
             }
             return val;
             return val;
@@ -85,6 +94,10 @@ namespace glTF {
         obj.AddMember("componentType", int(a.componentType), w.mAl);
         obj.AddMember("componentType", int(a.componentType), w.mAl);
         obj.AddMember("count", a.count, w.mAl);
         obj.AddMember("count", a.count, w.mAl);
         obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
         obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
+
+        Value vTmpMax, vTmpMin;
+        obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
+        obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
     }
     }
 
 
     inline void Write(Value& obj, Animation& a, AssetWriter& w)
     inline void Write(Value& obj, Animation& a, AssetWriter& w)
@@ -285,7 +298,7 @@ namespace glTF {
             }
             }
             primitives.PushBack(prim, w.mAl);
             primitives.PushBack(prim, w.mAl);
         }
         }
-    
+
         obj.AddMember("primitives", primitives, w.mAl);
         obj.AddMember("primitives", primitives, w.mAl);
     }
     }
 
 
@@ -323,7 +336,18 @@ namespace glTF {
 
 
     inline void Write(Value& obj, Sampler& b, AssetWriter& w)
     inline void Write(Value& obj, Sampler& b, AssetWriter& w)
     {
     {
-
+        if (b.wrapS) {
+            obj.AddMember("wrapS", b.wrapS, w.mAl);
+        }
+        if (b.wrapT) {
+            obj.AddMember("wrapT", b.wrapT, w.mAl);
+        }
+        if (b.magFilter) {
+            obj.AddMember("magFilter", b.magFilter, w.mAl);
+        }
+        if (b.minFilter) {
+            obj.AddMember("minFilter", b.minFilter, w.mAl);
+        }
     }
     }
 
 
     inline void Write(Value& scene, Scene& s, AssetWriter& w)
     inline void Write(Value& scene, Scene& s, AssetWriter& w)
@@ -351,6 +375,9 @@ namespace glTF {
         if (tex.source) {
         if (tex.source) {
             obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl);
             obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl);
         }
         }
+        if (tex.sampler) {
+            obj.AddMember("sampler", Value(tex.sampler->id, w.mAl).Move(), w.mAl);
+        }
     }
     }
 
 
     inline void Write(Value& obj, Light& b, AssetWriter& w)
     inline void Write(Value& obj, Light& b, AssetWriter& w)
@@ -487,13 +514,15 @@ namespace glTF {
         }
         }
     }
     }
 
 
-    
+
     inline void AssetWriter::WriteMetadata()
     inline void AssetWriter::WriteMetadata()
     {
     {
         Value asset;
         Value asset;
         asset.SetObject();
         asset.SetObject();
         {
         {
-            asset.AddMember("version", mAsset.asset.version, mAl);
+            char versionChar[10];
+            ai_snprintf(versionChar, sizeof(versionChar), "%d", mAsset.asset.version);
+            asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
 
 
             asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
             asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
         }
         }

+ 80 - 1
code/glTFExporter.cpp

@@ -193,6 +193,36 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     acc->count = count;
     acc->count = count;
     acc->type = typeOut;
     acc->type = typeOut;
 
 
+    // calculate min and max values
+    {
+        // Allocate and initialize with large values.
+        float float_MAX = 10000000000000;
+        for (int i = 0 ; i < numCompsOut ; i++) {
+            acc->min.push_back( float_MAX);
+            acc->max.push_back(-float_MAX);
+        }
+
+        // Search and set extreme values.
+        float valueTmp;
+        for (int i = 0 ; i < count       ; i++) {
+        for (int j = 0 ; j < numCompsOut ; j++) {
+
+            if (numCompsOut == 1) {
+              valueTmp = static_cast<unsigned short*>(data)[i];
+            } else {
+              valueTmp = static_cast<aiVector3D*>(data)[i][j];
+            }
+
+            if (valueTmp < acc->min[j]) {
+                acc->min[j] = valueTmp;
+            }
+            if (valueTmp > acc->max[j]) {
+                acc->max[j] = valueTmp;
+            }
+        }
+        }
+    }
+
     // copy the data
     // copy the data
     acc->WriteData(count, data, numCompsIn*bytesPerComp);
     acc->WriteData(count, data, numCompsIn*bytesPerComp);
 
 
@@ -205,6 +235,52 @@ namespace {
     }
     }
 }
 }
 
 
+void glTFExporter::GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop)
+{
+    std::string samplerId = mAsset->FindUniqueID("", "sampler");
+    prop.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:
+            prop.texture->sampler->wrapS = SamplerWrap_Repeat;
+            break;
+        case aiTextureMapMode_Clamp:
+            prop.texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge;
+            break;
+        case aiTextureMapMode_Mirror:
+            prop.texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat;
+            break;
+        case aiTextureMapMode_Decal:
+        default:
+            prop.texture->sampler->wrapS = SamplerWrap_Repeat;
+            break;
+    };
+
+    switch (mapV) {
+        case aiTextureMapMode_Wrap:
+            prop.texture->sampler->wrapT = SamplerWrap_Repeat;
+            break;
+        case aiTextureMapMode_Clamp:
+            prop.texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge;
+            break;
+        case aiTextureMapMode_Mirror:
+            prop.texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat;
+            break;
+        case aiTextureMapMode_Decal:
+        default:
+            prop.texture->sampler->wrapT = SamplerWrap_Repeat;
+            break;
+    };
+
+    // Hard coded Texture filtering options because I do not know where to find them in the aiMaterial.
+    prop.texture->sampler->magFilter = SamplerMagFilter_Linear;
+    prop.texture->sampler->minFilter = SamplerMinFilter_Linear;
+}
+
 void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
 void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
 {
 {
     aiString tex;
     aiString tex;
@@ -244,6 +320,8 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
                     else {
                     else {
                         prop.texture->source->uri = path;
                         prop.texture->source->uri = path;
                     }
                     }
+
+                    GetTexSampler(mat, prop);
                 }
                 }
             }
             }
         }
         }
@@ -254,6 +332,7 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
     }
     }
 }
 }
 
 
+
 void glTFExporter::ExportMaterials()
 void glTFExporter::ExportMaterials()
 {
 {
     aiString aiName;
     aiString aiName;
@@ -369,7 +448,7 @@ void glTFExporter::ExportMeshes()
 
 
 				if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
 				if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
 
 
-				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, true);
+				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
 				if (tc) p.attributes.texcoord.push_back(tc);
 				if (tc) p.attributes.texcoord.push_back(tc);
 			}
 			}
 		}
 		}

+ 1 - 0
code/glTFExporter.h

@@ -94,6 +94,7 @@ namespace Assimp
 
 
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
         void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
 
 
+        void GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop);
         void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
         void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
         void ExportMetadata();
         void ExportMetadata();
         void ExportMaterials();
         void ExportMaterials();