From 3e322495f22828409e584af6af4350a2d80c7154 Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Tue, 27 Sep 2016 11:38:17 -0700 Subject: [PATCH 1/6] asset.version from int to string --- code/glTFAssetWriter.inl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 119ebc937..71b47473b 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -282,7 +282,7 @@ namespace glTF { } primitives.PushBack(prim, w.mAl); } - + obj.AddMember("primitives", primitives, w.mAl); } @@ -484,13 +484,15 @@ namespace glTF { } } - + inline void AssetWriter::WriteMetadata() { Value asset; asset.SetObject(); { - asset.AddMember("version", mAsset.asset.version, mAl); + char versionChar[10]; + 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); } From e89e98291a3e92a866ac154460e17fb8b2b61661 Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Wed, 28 Sep 2016 14:47:15 -0700 Subject: [PATCH 2/6] calculate and write min and max attributes for accessors --- code/glTFAsset.h | 4 ++-- code/glTFAssetWriter.inl | 17 +++++++++++++++-- code/glTFExporter.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/code/glTFAsset.h b/code/glTFAsset.h index e34b05f5c..f105d6b6c 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -377,8 +377,8 @@ namespace glTF ComponentType componentType; //!< The datatype of components in the attribute. (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) - //std::vector max; //!< Maximum value of each component in this attribute. - //std::vector min; //!< Minimum value of each component in this attribute. + std::vector max; //!< Maximum value of each component in this attribute. + std::vector min; //!< Minimum value of each component in this attribute. unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 71b47473b..24c6c8c35 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -56,7 +56,16 @@ namespace glTF { inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) { val.SetArray(); 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 & r, MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(r.size(), al); + for (int i = 0; i < r.size(); ++i) { val.PushBack(r[i], al); } return val; @@ -85,6 +94,10 @@ namespace glTF { obj.AddMember("componentType", int(a.componentType), w.mAl); obj.AddMember("count", a.count, 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) @@ -491,7 +504,7 @@ namespace glTF { asset.SetObject(); { char versionChar[10]; - snprintf(versionChar, sizeof(versionChar), "%d", mAsset.asset.version); + 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); diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 708570577..2da709cee 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -193,6 +193,31 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu acc->count = count; 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++) { + + valueTmp = static_cast(data)[i][j]; + if (valueTmp < acc->min[j]) { + acc->min[j] = valueTmp; + } + if (valueTmp > acc->max[j]) { + acc->max[j] = valueTmp; + } + } + } + } + // copy the data acc->WriteData(count, data, numCompsIn*bytesPerComp); From f2e6f2f67f04a8c28bc9d025321ae8ac1460995c Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Wed, 28 Sep 2016 15:56:06 -0700 Subject: [PATCH 3/6] work around for indices array in ExportData --- code/glTFExporter.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 2da709cee..6bff38737 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -207,7 +207,12 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu for (int i = 0 ; i < count ; i++) { for (int j = 0 ; j < numCompsOut ; j++) { - valueTmp = static_cast(data)[i][j]; + if (numCompsOut == 1) { + valueTmp = static_cast(data)[i]; + } else { + valueTmp = static_cast(data)[i][j]; + } + if (valueTmp < acc->min[j]) { acc->min[j] = valueTmp; } From 7dd2e7011da1fba2d6f783dc4c7ff6ef4b79249f Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Wed, 28 Sep 2016 18:50:08 -0700 Subject: [PATCH 4/6] fixed issue with texcoordinate bufferview target --- code/glTFExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 6bff38737..83a2e0eee 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -397,7 +397,7 @@ void glTFExporter::ExportMeshes() if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array. - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, true); + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); if (tc) p.attributes.texcoord.push_back(tc); } } From 0619232aef234f5c0b34a35283ba7caaba9c0150 Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Fri, 30 Sep 2016 17:23:38 -0700 Subject: [PATCH 5/6] included samplers dictionary for textures --- code/glTFAsset.h | 44 +++++++++++++++++++++++++++++++----- code/glTFAsset.inl | 41 +++++++++++++++++++++++++-------- code/glTFAssetWriter.inl | 16 ++++++++++++- code/glTFExporter.cpp | 49 ++++++++++++++++++++++++++++++++++++++++ code/glTFExporter.h | 1 + 5 files changed, 135 insertions(+), 16 deletions(-) diff --git a/code/glTFAsset.h b/code/glTFAsset.h index f105d6b6c..78b456405 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -236,6 +236,32 @@ namespace glTF 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 enum TextureFormat { @@ -812,8 +838,14 @@ namespace glTF 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() {} void Read(Value& obj, Asset& r); + void SetDefaults(); }; struct Scene : public Object @@ -860,8 +892,8 @@ namespace glTF //! A texture and its sampler. struct Texture : public Object { - //Ref source; //!< The ID of the sampler used by this texture. (required) - Ref source; //!< The ID of the image used by this texture. (required) + Ref sampler; //!< The ID of the sampler used by this texture. (required) + Ref source; //!< The ID of the image used by this texture. (required) //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA) //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA) @@ -921,7 +953,7 @@ namespace glTF //! (Implemented in glTFAssetWriter.h) template void WriteLazyDict(LazyDict& d, AssetWriter& w); - + //! 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 @@ -983,7 +1015,7 @@ namespace glTF int version; //!< The glTF format version (should be 1) void Read(Document& doc); - + AssetMetadata() : premultipliedAlpha(false) , version(0) @@ -1049,7 +1081,7 @@ namespace glTF LazyDict meshes; LazyDict nodes; //LazyDict programs; - //LazyDict samplers; + LazyDict samplers; LazyDict scenes; //LazyDict shaders; //LazyDict skins; @@ -1074,7 +1106,7 @@ namespace glTF , meshes (*this, "meshes") , nodes (*this, "nodes") //, programs (*this, "programs") - //, samplers (*this, "samplers") + , samplers (*this, "samplers") , scenes (*this, "scenes") //, shaders (*this, "shaders") //, skins (*this, "skins") diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index b9f3fccd8..a7dbebde2 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -53,7 +53,7 @@ using namespace Assimp; namespace glTF { namespace { - + // // JSON Value reading helpers // @@ -62,7 +62,7 @@ namespace { struct ReadHelper { static bool Read(Value& val, T& out) { return val.IsInt() ? out = static_cast(val.GetInt()), true : false; }}; - + template<> struct ReadHelper { static bool Read(Value& val, bool& out) { return val.IsBool() ? out = val.GetBool(), true : false; }}; @@ -70,7 +70,7 @@ namespace { template<> struct ReadHelper { static bool Read(Value& val, float& out) { return val.IsNumber() ? out = static_cast(val.GetDouble()), true : false; }}; - + template struct ReadHelper { static bool Read(Value& val, float (&out)[N]) { if (!val.IsArray() || val.Size() != N) return false; for (unsigned int i = 0; i < N; ++i) { @@ -312,7 +312,7 @@ inline void Buffer::Read(Value& obj, Asset& r) if (file) { bool ok = LoadFromStream(*file, byteLength); delete file; - + if (!ok) 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) { buffer = r.buffers.Get(bufferId); } - + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); byteLength = MemberOrDefault(obj, "byteLength", 0u); } @@ -599,7 +599,7 @@ inline Image::Image() 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 (r.extensionsUsed.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) { const char* sourcestr; if (ReadMember(obj, "source", sourcestr)) { source = r.images.Get(sourcestr); } + + const char* samplerstr; + if (ReadMember(obj, "sampler", samplerstr)) { + sampler = r.samplers.Get(samplerstr); + } } namespace { @@ -1131,7 +1154,7 @@ inline void Node::Read(Value& obj, Asset& r) } } - + if (Value* matrix = FindArray(obj, "matrix")) { ReadValue(*matrix, this->matrix); } @@ -1407,13 +1430,13 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi id = buffer; it = mUsedIds.find(id); } - + return id; } namespace Util { - inline + inline bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) { if ( NULL == const_uri ) { return false; diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 24c6c8c35..c440ca116 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -333,7 +333,18 @@ namespace glTF { 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) @@ -361,6 +372,9 @@ namespace glTF { if (tex.source) { 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) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 83a2e0eee..0981a7a33 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -235,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) { aiString tex; @@ -274,6 +320,8 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr else { prop.texture->source->uri = path; } + + GetTexSampler(mat, prop); } } } @@ -284,6 +332,7 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr } } + void glTFExporter::ExportMaterials() { aiString aiName; diff --git a/code/glTFExporter.h b/code/glTFExporter.h index dfd0108b5..554bb17aa 100644 --- a/code/glTFExporter.h +++ b/code/glTFExporter.h @@ -94,6 +94,7 @@ namespace Assimp 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 ExportMetadata(); void ExportMaterials(); From c1c0808483c87fb8f55eeb762b67304451228d0f Mon Sep 17 00:00:00 2001 From: Angelo Scandaliato Date: Fri, 30 Sep 2016 18:09:18 -0700 Subject: [PATCH 6/6] update change log --- CHANGES | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGES b/CHANGES index 0ff79cbe1..0c734162b 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,22 @@ 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) FEATURES: