浏览代码

Merge branch 'master' into master

Kim Kulling 3 年之前
父节点
当前提交
72da1e6d7b

+ 56 - 107
code/AssetLib/glTF/glTFAsset.h

@@ -260,20 +260,9 @@ public:
         VEC4,
         MAT2,
         MAT3,
-        MAT4 };
-
-private:
-    static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
-
-    struct Info {
-        const char *name;
-        unsigned int numComponents;
+        MAT4 
     };
 
-    template <int N>
-    struct data { static const Info infos[NUM_VALUES]; };
-
-public:
     inline static Value FromString(const char *str) {
         for (size_t i = 0; i < NUM_VALUES; ++i) {
             if (strcmp(data<0>::infos[i].name, str) == 0) {
@@ -290,40 +279,31 @@ public:
     inline static unsigned int GetNumComponents(Value type) {
         return data<0>::infos[static_cast<size_t>(type)].numComponents;
     }
+
+private:
+    static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
+    struct Info {
+        const char *name;
+        unsigned int numComponents;
+    };
+
+    template <int N>
+    struct data { 
+        static const Info infos[NUM_VALUES]; 
+    };
 };
 
 // must match the order of the AttribTypeTraits::Value enum!
 template <int N>
-const AttribType::Info
-        AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
-            { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
-        };
-
-/*
-    //! A reference to one top-level object, which is valid
-    //! until the Asset instance is destroyed
-    template<class T>
-    class Ref
-    {
-        std::vector<T*>* vector;
-        unsigned int index;
-
-    public:
-        Ref() : vector(0), index(0) {}
-        Ref(std::vector<T*>& vec, unsigned int idx) : vector(&vec), index(idx) {}
-
-        inline unsigned int GetIndex() const
-            { return index; }
-
-        operator bool() const
-            { return vector != 0; }
-
-        T* operator->()
-            { return (*vector)[index]; }
-
-        T& operator*()
-            { return *((*vector)[index]); }
-    };*/
+const AttribType::Info AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
+    { "SCALAR", 1 },
+    { "VEC2", 2 }, 
+    { "VEC3", 3 }, 
+    { "VEC4", 4 }, 
+    { "MAT2", 4 }, 
+    { "MAT3", 9 }, 
+    { "MAT4", 16 }
+};
 
 //! Base class for all glTF top-level objects
 struct Object {
@@ -333,6 +313,7 @@ struct Object {
     //! Objects marked as special are not exported (used to emulate the binary body buffer)
     virtual bool IsSpecial() const { return false; }
 
+    Object() = default;
     virtual ~Object() {}
 
     //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
@@ -401,21 +382,19 @@ struct Accessor : public Object {
         return Indexer(*this);
     }
 
-    Accessor() {}
+    Accessor() = default;
     void Read(Value &obj, Asset &r);
 };
 
 //! A buffer points to binary geometry, animation, or skins.
 struct Buffer : public Object {
     /********************* Types *********************/
-public:
     enum Type {
         Type_arraybuffer,
         Type_text
     };
 
-    /// \struct SEncodedRegion
-    /// Descriptor of encoded region in "bufferView".
+    /// @brief  Descriptor of encoded region in "bufferView".
     struct SEncodedRegion {
         const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
         const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
@@ -423,8 +402,7 @@ public:
         const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
         const std::string ID; ///< ID of the region.
 
-        /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
-        /// Constructor.
+        /// @brief Constructor.
         /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
         /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
         /// \param [in] pDecodedData - pointer to decoded data array.
@@ -433,16 +411,13 @@ public:
         SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
                 Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
 
-        /// \fn ~SEncodedRegion()
         /// Destructor.
         ~SEncodedRegion() { delete[] DecodedData; }
     };
 
     /******************* Variables *******************/
 
-    //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
     size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
-    //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
 
     Type type;
 
@@ -486,7 +461,6 @@ public:
 
     bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
 
-    /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
     /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
     /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
     /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
@@ -495,12 +469,10 @@ public:
     /// \param [in] pID - ID of the region.
     void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
 
-    /// \fn void EncodedRegion_SetCurrent(const std::string& pID)
     /// Select current encoded region by ID. \sa EncodedRegion_Current.
     /// \param [in] pID - ID of the region.
     void EncodedRegion_SetCurrent(const std::string &pID);
 
-    /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
     /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
     /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
     /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
@@ -558,37 +530,29 @@ struct Camera : public Object {
         } ortographic;
     };
 
-    Camera() {}
+    Camera() = default;
     void Read(Value &obj, Asset &r);
 };
 
 //! Image data used to create a texture.
 struct Image : public Object {
     std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
-
     Ref<BufferView> bufferView;
-
     std::string mimeType;
-
     int width, height;
 
-private:
-    std::unique_ptr<uint8_t[]> mData;
-    size_t mDataLength;
-
 public:
     Image();
     void Read(Value &obj, Asset &r);
-
     inline bool HasData() const { return mDataLength > 0; }
-
     inline size_t GetDataLength() const { return mDataLength; }
-
     inline const uint8_t *GetData() const { return mData.get(); }
-
     inline uint8_t *StealData();
-
     inline void SetData(uint8_t *data, size_t length, Asset &r);
+
+private:
+    std::unique_ptr<uint8_t[]> mData;
+    size_t mDataLength;
 };
 
 //! Holds a material property that can be a texture or a color
@@ -671,6 +635,7 @@ struct Mesh : public Object {
     };
 
 #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+
     /// \struct SCompression_Open3DGC
     /// Compression of mesh data using Open3DGC algorithm.
     struct SCompression_Open3DGC : public SExtension {
@@ -703,7 +668,6 @@ struct Mesh : public Object {
 
     Mesh() {}
 
-    /// \fn ~Mesh()
     /// Destructor.
     ~Mesh() {
         for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) {
@@ -711,15 +675,13 @@ struct Mesh : public Object {
         };
     }
 
-    /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
-    /// Get mesh data from JSON-object and place them to root asset.
+    /// @brief Get mesh data from JSON-object and place them to root asset.
     /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
     /// \param [out] pAsset_Root - reference to root asset where data will be stored.
     void Read(Value &pJSON_Object, Asset &pAsset_Root);
 
 #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
-    /// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
-    /// Decode part of "buffer" which encoded with Open3DGC algorithm.
+    /// @brief Decode part of "buffer" which encoded with Open3DGC algorithm.
     /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
     /// \param [out] pAsset_Root - reference to root assed where data will be stored.
     void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root);
@@ -759,7 +721,7 @@ struct Sampler : public Object {
     SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
     SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
 
-    Sampler() {}
+    Sampler() = default;
     void Read(Value &obj, Asset &r);
     void SetDefaults();
 };
@@ -767,12 +729,12 @@ struct Sampler : public Object {
 struct Scene : public Object {
     std::vector<Ref<Node>> nodes;
 
-    Scene() {}
+    Scene() = default;
     void Read(Value &obj, Asset &r);
 };
 
 struct Shader : public Object {
-    Shader() {}
+    Shader() = default;
     void Read(Value &obj, Asset &r);
 };
 
@@ -782,7 +744,7 @@ struct Skin : public Object {
     std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
     std::string name; //!< The user-defined name of this object.
 
-    Skin() {}
+    Skin() = default;
     void Read(Value &obj, Asset &r);
 };
 
@@ -796,7 +758,7 @@ struct Technique : public Object {
     struct Functions {
     };
 
-    Technique() {}
+    Technique() = default;
     void Read(Value &obj, Asset &r);
 };
 
@@ -805,13 +767,7 @@ struct Texture : public Object {
     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 internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
-
-    //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
-    //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
-
-    Texture() {}
+    Texture() = default;
     void Read(Value &obj, Asset &r);
 };
 
@@ -826,7 +782,6 @@ struct Light : public Object {
     };
 
     Type type;
-
     vec4 color;
     float distance;
     float constantAttenuation;
@@ -835,9 +790,8 @@ struct Light : public Object {
     float falloffAngle;
     float falloffExponent;
 
-    Light() {}
+    Light() = default;
     void Read(Value &obj, Asset &r);
-
     void SetDefaults();
 };
 
@@ -865,15 +819,11 @@ struct Animation : public Object {
         Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
     };
 
-    // AnimChannel Channels[3];            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
-    // AnimParameters Parameters;          //!< The samplers that interpolate between the key-frames.
-    // AnimSampler Samplers[3];            //!< The parameterized inputs representing the key-frame data.
-
     std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
     AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
     std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
 
-    Animation() {}
+    Animation() = default;
     void Read(Value &obj, Asset &r);
 };
 
@@ -963,13 +913,11 @@ struct AssetMetadata {
 
 //! Root object for a glTF asset
 class Asset {
-    typedef std::gltf_unordered_map<std::string, int> IdMap;
+    using IdMap = std::gltf_unordered_map<std::string, int>;
 
     template <class T>
     friend class LazyDict;
-
     friend struct Buffer; // To access OpenFile
-
     friend class AssetWriter;
 
 private:
@@ -1010,12 +958,9 @@ public:
     LazyDict<Material> materials;
     LazyDict<Mesh> meshes;
     LazyDict<Node> nodes;
-    //LazyDict<Program>   programs;
     LazyDict<Sampler> samplers;
     LazyDict<Scene> scenes;
-    //LazyDict<Shader>    shaders;
     LazyDict<Skin> skins;
-    //LazyDict<Technique> techniques;
     LazyDict<Texture> textures;
 
     LazyDict<Light> lights; // KHR_materials_common ext
@@ -1024,16 +969,20 @@ public:
 
 public:
     Asset(IOSystem *io = 0) :
-            mIOSystem(io), asset(), accessors(*this, "accessors"), animations(*this, "animations"), buffers(*this, "buffers"), bufferViews(*this, "bufferViews"), cameras(*this, "cameras"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes")
-            //, programs    (*this, "programs")
-            ,
+            mIOSystem(io), 
+            asset(), 
+            accessors(*this, "accessors"), 
+            animations(*this, "animations"), 
+            buffers(*this, "buffers"), 
+            bufferViews(*this, "bufferViews"), 
+            cameras(*this, "cameras"), 
+            images(*this, "images"), 
+            materials(*this, "materials"), 
+            meshes(*this, "meshes"), 
+            nodes(*this, "nodes"),
             samplers(*this, "samplers"),
-            scenes(*this, "scenes")
-            //, shaders     (*this, "shaders")
-            ,
-            skins(*this, "skins")
-            //, techniques  (*this, "techniques")
-            ,
+            scenes(*this, "scenes"),
+            skins(*this, "skins"),
             textures(*this, "textures"),
             lights(*this, "lights", "KHR_materials_common") {
         memset(&extensionsUsed, 0, sizeof(extensionsUsed));

+ 0 - 2
code/AssetLib/glTF/glTFCommon.h

@@ -237,8 +237,6 @@ bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out);
 #define CHECK_EXT(EXT) \
     if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
 
-
-
 //! Helper struct to represent values that might not be present
 template <class T>
 struct Nullable {

+ 47 - 29
code/AssetLib/glTF2/glTF2Asset.h

@@ -106,7 +106,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #       define gltf_unordered_map tr1::unordered_map
 #       define gltf_unordered_set tr1::unordered_set
 #   else
-#      define gltf_unordered_map unordered_map
+#       define gltf_unordered_map unordered_map
 #       define gltf_unordered_set unordered_set
 #   endif
 #endif
@@ -1087,29 +1087,11 @@ class Asset {
 
     template <class T>
     friend class LazyDict;
-
     friend struct Buffer; // To access OpenFile
-
     friend class AssetWriter;
 
-private:
-    IOSystem *mIOSystem;
-    rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
-
-    std::string mCurrentAssetDir;
-
-    size_t mSceneLength;
-    size_t mBodyOffset, mBodyLength;
-
     std::vector<LazyDictBase *> mDicts;
 
-    IdMap mUsedIds;
-
-    Ref<Buffer> mBodyBuffer;
-
-    Asset(Asset &);
-    Asset &operator=(const Asset &);
-
 public:
     //! Keeps info about the enabled extensions
     struct Extensions {
@@ -1125,16 +1107,36 @@ public:
         bool KHR_draco_mesh_compression;
         bool FB_ngon_encoding;
         bool KHR_texture_basisu;
+
+        Extensions() :
+                KHR_materials_pbrSpecularGlossiness(false), 
+                KHR_materials_unlit(false), 
+                KHR_lights_punctual(false), 
+                KHR_texture_transform(false), 
+                KHR_materials_sheen(false), 
+                KHR_materials_clearcoat(false), 
+                KHR_materials_transmission(false), 
+                KHR_materials_volume(false),
+                KHR_materials_ior(false),
+                KHR_draco_mesh_compression(false),
+                FB_ngon_encoding(false),
+                KHR_texture_basisu(false) {
+            // empty
+        }
     } extensionsUsed;
 
     //! Keeps info about the required extensions
     struct RequiredExtensions {
         bool KHR_draco_mesh_compression;
         bool KHR_texture_basisu;
+
+        RequiredExtensions() : KHR_draco_mesh_compression(false), KHR_texture_basisu(false) {
+            // empty
+        }
     } extensionsRequired;
 
     AssetMetadata asset;
-    Value *extras = nullptr;
+    Value *extras;
 
     // Dictionaries for each type of object
 
@@ -1156,10 +1158,12 @@ public:
     Ref<Scene> scene;
 
 public:
-    Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) : 
-            mIOSystem(io),
-            mSchemaDocumentProvider(schemaDocumentProvider),
+    Asset(IOSystem *io = nullptr, rapidjson::IRemoteSchemaDocumentProvider *schemaDocumentProvider = nullptr) :
+            mDicts(),
+            extensionsUsed(),
+            extensionsRequired(),
             asset(),
+            extras(nullptr),
             accessors(*this, "accessors"),
             animations(*this, "animations"),
             buffers(*this, "buffers"),
@@ -1173,9 +1177,10 @@ public:
             samplers(*this, "samplers"),
             scenes(*this, "scenes"),
             skins(*this, "skins"),
-            textures(*this, "textures") {
-        memset(&extensionsUsed, 0, sizeof(extensionsUsed));
-        memset(&extensionsRequired, 0, sizeof(extensionsRequired));
+            textures(*this, "textures") ,
+            mIOSystem(io),
+            mSchemaDocumentProvider(schemaDocumentProvider) {
+        // empty
     }
 
     //! Main function
@@ -1192,18 +1197,31 @@ public:
 
     Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
 
+    Asset(Asset &) = delete;
+    Asset &operator=(const Asset &) = delete;
+
 private:
     void ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneData);
 
-    //! Obtain a JSON document from the stream.
-    // \param second argument is a buffer used by the document. It must be kept
-    // alive while the document is in use.
+    /// Obtain a JSON document from the stream.
+    /// \param second argument is a buffer used by the document. It must be kept
+    /// alive while the document is in use.
     Document ReadDocument(IOStream& stream, bool isBinary, std::vector<char>& sceneData);
 
     void ReadExtensionsUsed(Document &doc);
     void ReadExtensionsRequired(Document &doc);
 
     IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
+
+private:
+    IOSystem *mIOSystem;
+    rapidjson::IRemoteSchemaDocumentProvider *mSchemaDocumentProvider;
+    std::string mCurrentAssetDir;
+    size_t mSceneLength;
+    size_t mBodyOffset;
+    size_t mBodyLength;
+    IdMap mUsedIds;
+    Ref<Buffer> mBodyBuffer;
 };
 
 inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {

+ 99 - 91
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -515,72 +515,74 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, float &prop, const char
 }
 
 void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
-    if (mat.GetTextureCount(tt) > 0) {
-        aiString tex;
-
-        // Read texcoord (UV map index)
-        mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
+    if (mat.GetTextureCount(tt) == 0) {
+        return;
+    }
+        
+    aiString tex;
 
-        if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
-            std::string path = tex.C_Str();
+    // Read texcoord (UV map index)
+    mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
 
-            if (path.size() > 0) {
-                std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
-                if (it != mTexturesByPath.end()) {
-                    texture = mAsset->textures.Get(it->second);
-                }
+    if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
+        std::string path = tex.C_Str();
 
-                bool useBasisUniversal = false;
-                if (!texture) {
-                    std::string texId = mAsset->FindUniqueID("", "texture");
-                    texture = mAsset->textures.Create(texId);
-                    mTexturesByPath[path] = texture.GetIndex();
-
-                    std::string imgId = mAsset->FindUniqueID("", "image");
-                    texture->source = mAsset->images.Create(imgId);
-
-                    const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
-                    if (curTex != nullptr) { // embedded
-                        texture->source->name = curTex->mFilename.C_Str();
-
-                        //basisu: embedded ktx2, bu
-                        if (curTex->achFormatHint[0]) {
-                            std::string mimeType = "image/";
-                            if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
-                                mimeType += "jpeg";
-                            else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
-                                useBasisUniversal = true;
-                                mimeType += "ktx";
-                            } else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
-                                useBasisUniversal = true;
-                                mimeType += "ktx2";
-                            } else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
-                                useBasisUniversal = true;
-                                mimeType += "basis";
-                            } else
-                                mimeType += curTex->achFormatHint;
-                            texture->source->mimeType = mimeType;
-                        }
+        if (path.size() > 0) {
+            std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
+            if (it != mTexturesByPath.end()) {
+                texture = mAsset->textures.Get(it->second);
+            }
 
-                        // The asset has its own buffer, see Image::SetData
-                        //basisu: "image/ktx2", "image/basis" as is
-                        texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
-                    } else {
-                        texture->source->uri = path;
-                        if (texture->source->uri.find(".ktx") != std::string::npos ||
-                                texture->source->uri.find(".basis") != std::string::npos) {
+            bool useBasisUniversal = false;
+            if (!texture) {
+                std::string texId = mAsset->FindUniqueID("", "texture");
+                texture = mAsset->textures.Create(texId);
+                mTexturesByPath[path] = texture.GetIndex();
+
+                std::string imgId = mAsset->FindUniqueID("", "image");
+                texture->source = mAsset->images.Create(imgId);
+
+                const aiTexture *curTex = mScene->GetEmbeddedTexture(path.c_str());
+                if (curTex != nullptr) { // embedded
+                    texture->source->name = curTex->mFilename.C_Str();
+
+                    //basisu: embedded ktx2, bu
+                    if (curTex->achFormatHint[0]) {
+                        std::string mimeType = "image/";
+                        if (memcmp(curTex->achFormatHint, "jpg", 3) == 0)
+                            mimeType += "jpeg";
+                        else if (memcmp(curTex->achFormatHint, "ktx", 3) == 0) {
                             useBasisUniversal = true;
-                        }
+                            mimeType += "ktx";
+                        } else if (memcmp(curTex->achFormatHint, "kx2", 3) == 0) {
+                            useBasisUniversal = true;
+                            mimeType += "ktx2";
+                        } else if (memcmp(curTex->achFormatHint, "bu", 2) == 0) {
+                            useBasisUniversal = true;
+                            mimeType += "basis";
+                        } else
+                            mimeType += curTex->achFormatHint;
+                        texture->source->mimeType = mimeType;
                     }
 
-                    //basisu
-                    if (useBasisUniversal) {
-                        mAsset->extensionsUsed.KHR_texture_basisu = true;
-                        mAsset->extensionsRequired.KHR_texture_basisu = true;
+                    // The asset has its own buffer, see Image::SetData
+                    //basisu: "image/ktx2", "image/basis" as is
+                    texture->source->SetData(reinterpret_cast<uint8_t *>(curTex->pcData), curTex->mWidth, *mAsset);
+                } else {
+                    texture->source->uri = path;
+                    if (texture->source->uri.find(".ktx") != std::string::npos ||
+                            texture->source->uri.find(".basis") != std::string::npos) {
+                        useBasisUniversal = true;
                     }
+                }
 
-                    GetTexSampler(mat, texture, tt, slot);
+                //basisu
+                if (useBasisUniversal) {
+                    mAsset->extensionsUsed.KHR_texture_basisu = true;
+                    mAsset->extensionsRequired.KHR_texture_basisu = true;
                 }
+
+                GetTexSampler(mat, texture, tt, slot);
             }
         }
     }
@@ -588,12 +590,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
 
 void glTF2Exporter::GetMatTex(const aiMaterial &mat, TextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
     Ref<Texture> &texture = prop.texture;
-
     GetMatTex(mat, texture, prop.texCoord, tt, slot);
-
-    //if (texture) {
-    //    GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
-    //}
 }
 
 void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, aiTextureType tt, unsigned int slot = 0) {
@@ -681,12 +678,14 @@ bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlo
 
 bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) {
     // Return true if got any valid Sheen properties or textures
-    if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS)
+    if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) {
         return false;
+    }
 
     // Default Sheen color factor {0,0,0} disables Sheen, so do not export
-    if (sheen.sheenColorFactor == defaultSheenFactor)
+    if (sheen.sheenColorFactor == defaultSheenFactor) {
         return false;
+    }
 
     mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor);
 
@@ -781,9 +780,7 @@ void glTF2Exporter::ExportMaterials() {
             aiColor4D specularColor;
             ai_real shininess;
 
-            if (
-                    mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS &&
-                    mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
+            if (mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) {
                 // convert specular color to luminance
                 float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f;
                 //normalize shininess (assuming max is 1000) with an inverse exponentional curve
@@ -916,7 +913,8 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
     return parentNodeRef;
 }
 
-void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef, std::vector<aiMatrix4x4> &inverseBindMatricesData) {
+void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef, 
+        std::vector<aiMatrix4x4> &inverseBindMatricesData) {
     if (aimesh->mNumBones < 1) {
         return;
     }
@@ -986,7 +984,8 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
     } // End: for-loop mNumMeshes
 
     Mesh::Primitive &p = meshRef->primitives.back();
-    Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+    Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, 
+        vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
     if (vertexJointAccessor) {
         size_t offset = vertexJointAccessor->bufferView->byteOffset;
         size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
@@ -1069,8 +1068,11 @@ void glTF2Exporter::ExportMeshes() {
         p.ngonEncoded = (aim->mPrimitiveTypes & aiPrimitiveType_NGONEncodingFlag) != 0;
 
         /******************* Vertices ********************/
-        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
-        if (v) p.attributes.position.push_back(v);
+        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3,
+            AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
+        if (v) {
+            p.attributes.position.push_back(v);
+        }
 
         /******************** Normals ********************/
         // Normalize all normals as the validator can emit a warning otherwise
@@ -1080,13 +1082,17 @@ void glTF2Exporter::ExportMeshes() {
             }
         }
 
-        Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
-        if (n) p.attributes.normal.push_back(n);
+        Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, 
+            AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
+        if (n) {
+            p.attributes.normal.push_back(n);
+        }
 
         /************** Texture coordinates **************/
         for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-            if (!aim->HasTextureCoords(i))
+            if (!aim->HasTextureCoords(i)) {
                 continue;
+            }
 
             // Flip UV y coords
             if (aim->mNumUVComponents[i] > 1) {
@@ -1098,16 +1104,21 @@ void glTF2Exporter::ExportMeshes() {
             if (aim->mNumUVComponents[i] > 0) {
                 AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
 
-                Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
-                if (tc) p.attributes.texcoord.push_back(tc);
+                Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], 
+                    AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
+                if (tc) {
+                    p.attributes.texcoord.push_back(tc);
+                }
             }
         }
 
         /*************** Vertex colors ****************/
         for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) {
-            Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
-            if (c)
+            Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel],
+                AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
+            if (c) {
                 p.attributes.color.push_back(c);
+            }
         }
 
         /*************** Vertices indices ****************/
@@ -1121,7 +1132,8 @@ void glTF2Exporter::ExportMeshes() {
                 }
             }
 
-            p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
+            p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, 
+                ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
         }
 
         switch (aim->mPrimitiveTypes) {
@@ -1136,6 +1148,7 @@ void glTF2Exporter::ExportMeshes() {
             break;
         default: // aiPrimitiveType_TRIANGLE
             p.mode = PrimitiveMode_TRIANGLES;
+            break;
         }
 
         /*************** Skins ****************/
@@ -1155,8 +1168,9 @@ void glTF2Exporter::ExportMeshes() {
             p.targets.resize(aim->mNumAnimMeshes);
             for (unsigned int am = 0; am < aim->mNumAnimMeshes; ++am) {
                 aiAnimMesh *pAnimMesh = aim->mAnimMeshes[am];
-                if (bExportTargetNames)
-                    m->targetNames.push_back(pAnimMesh->mName.data);
+                if (bExportTargetNames) {
+                    m->targetNames.emplace_back(pAnimMesh->mName.data);
+                }
                 // position
                 if (pAnimMesh->HasPositions()) {
                     // NOTE: in gltf it is the diff stored
@@ -1319,12 +1333,12 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
     }
 
     for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
-        node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
+        node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
     }
 
     for (unsigned int i = 0; i < n->mNumChildren; ++i) {
         unsigned int idx = ExportNode(n->mChildren[i], node);
-        node->children.push_back(mAsset->nodes.Get(idx));
+        node->children.emplace_back(mAsset->nodes.Get(idx));
     }
 
     return node.GetIndex();
@@ -1366,12 +1380,12 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
     }
 
     for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
-        node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
+        node->meshes.emplace_back(mAsset->meshes.Get(n->mMeshes[i]));
     }
 
     for (unsigned int i = 0; i < n->mNumChildren; ++i) {
         unsigned int idx = ExportNode(n->mChildren[i], node);
-        node->children.push_back(mAsset->nodes.Get(idx));
+        node->children.emplace_back(mAsset->nodes.Get(idx));
     }
 
     return node.GetIndex();
@@ -1386,7 +1400,7 @@ void glTF2Exporter::ExportScene() {
 
     // root node will be the first one exported (idx 0)
     if (mAsset->nodes.Size() > 0) {
-        scene->nodes.push_back(mAsset->nodes.Get(0u));
+        scene->nodes.emplace_back(mAsset->nodes.Get(0u));
     }
 
     // set as the default scene
@@ -1521,12 +1535,6 @@ void glTF2Exporter::ExportAnimations() {
                 AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE);
             }
         }
-
-        // Assimp documentation states this is not used (not implemented)
-        // for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
-        //     const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
-        // }
-
     } // End: for-loop mNumAnimations
 }
 

+ 6 - 5
test/unit/Common/utMesh.cpp

@@ -60,7 +60,7 @@ protected:
 };
 
 TEST_F(utMesh, emptyMeshHasNoContentTest) {
-  EXPECT_EQ(0, mesh->mName.length);
+  EXPECT_EQ(0u, mesh->mName.length);
   EXPECT_FALSE(mesh->HasPositions());
   EXPECT_FALSE(mesh->HasFaces());
   EXPECT_FALSE(mesh->HasNormals());
@@ -69,8 +69,8 @@ TEST_F(utMesh, emptyMeshHasNoContentTest) {
   EXPECT_FALSE(mesh->HasVertexColors(AI_MAX_NUMBER_OF_COLOR_SETS));
   EXPECT_FALSE(mesh->HasTextureCoords(0));
   EXPECT_FALSE(mesh->HasTextureCoords(AI_MAX_NUMBER_OF_TEXTURECOORDS));
-  EXPECT_EQ(0, mesh->GetNumUVChannels());
-  EXPECT_EQ(0, mesh->GetNumColorChannels());
+  EXPECT_EQ(0u, mesh->GetNumUVChannels());
+  EXPECT_EQ(0u, mesh->GetNumColorChannels());
   EXPECT_FALSE(mesh->HasBones());
   EXPECT_FALSE(mesh->HasTextureCoordsName(0));
   EXPECT_FALSE(mesh->HasTextureCoordsName(AI_MAX_NUMBER_OF_TEXTURECOORDS));
@@ -80,8 +80,8 @@ TEST_F(utMesh, setTextureCoordsName) {
   EXPECT_FALSE(mesh->HasTextureCoordsName(0));
   const aiString texcoords_name("texcoord_name");
   mesh->SetTextureCoordsName(0, texcoords_name);
-  EXPECT_TRUE(mesh->HasTextureCoordsName(0));
-  EXPECT_FALSE(mesh->HasTextureCoordsName(1));
+  EXPECT_TRUE(mesh->HasTextureCoordsName(0u));
+  EXPECT_FALSE(mesh->HasTextureCoordsName(1u));
   ASSERT_NE(nullptr, mesh->mTextureCoordsNames);
   ASSERT_NE(nullptr, mesh->mTextureCoordsNames[0]);
   EXPECT_STREQ(texcoords_name.C_Str(), mesh->mTextureCoordsNames[0]->C_Str());
@@ -94,3 +94,4 @@ TEST_F(utMesh, setTextureCoordsName) {
   EXPECT_EQ(nullptr, mesh->mTextureCoordsNames[0]);
   EXPECT_EQ(nullptr, mesh->GetTextureCoordsName(0));
 }
+

+ 2 - 2
test/unit/utColladaExport.cpp

@@ -124,9 +124,9 @@ TEST_F(utColladaExport, testExportLight) {
     ASSERT_NE(pTest, nullptr);
     ASSERT_TRUE(pTest->HasLights());
 
-    const unsigned int origNumLights(pTest->mNumLights);
+    const unsigned int origNumLights = pTest->mNumLights;
     // There are FIVE!!! LIGHTS!!!
-    EXPECT_EQ(5, origNumLights) << "lights.dae should contain five lights";
+    EXPECT_EQ(5u, origNumLights) << "lights.dae should contain five lights";
 
     std::vector<aiLight> origLights(5);
     for (size_t i = 0; i < origNumLights; i++) {