2
0
Эх сурвалжийг харах

Merge branch 'master' into search-invalid-textures-missing-texture-types

Kim Kulling 5 жил өмнө
parent
commit
bdd5e52176

+ 5 - 6
code/FBX/FBXMeshGeometry.cpp

@@ -446,20 +446,19 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
             return;
         }
         std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+        ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 
-        if (tempData.size() != vertex_count) {
+        if (tempData.size() != mapping_offsets.size()) {
             FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ")
-                                  << tempData.size() << ", expected " << vertex_count);
+                                  << tempData.size() << ", expected " << mapping_offsets.size());
             return;
         }
 
         data_out.resize(vertex_count);
-		for (size_t i = 0, e = tempData.size(); i < e; ++i) {
-
+        for (size_t i = 0, e = tempData.size(); i < e; ++i) {
             const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
             for (unsigned int j = istart; j < iend; ++j) {
-				data_out[mappings[j]] = tempData[i];
+                data_out[mappings[j]] = tempData[i];
             }
         }
     }

+ 6 - 2
code/FBX/FBXParser.cpp

@@ -367,9 +367,13 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
     // first - next in the fbx token stream comes ',',
     // which fast_atof could interpret as decimal point.
 #define MAX_FLOAT_LENGTH 31
-    char temp[MAX_FLOAT_LENGTH + 1];
     const size_t length = static_cast<size_t>(t.end()-t.begin());
-    std::copy(t.begin(),t.end(),temp);
+    if (length > MAX_FLOAT_LENGTH) {
+        return 0.f;
+    }
+
+    char temp[MAX_FLOAT_LENGTH + 1];
+    std::copy(t.begin(), t.end(), temp);
     temp[std::min(static_cast<size_t>(MAX_FLOAT_LENGTH),length)] = '\0';
 
     return fast_atof(temp);

+ 63 - 27
code/M3D/M3DImporter.cpp

@@ -109,7 +109,9 @@ using namespace std;
 // ------------------------------------------------------------------------------------------------
 //  Default constructor
 M3DImporter::M3DImporter() :
-		mScene(nullptr) {}
+		mScene(nullptr) {
+			// empty
+		}
 
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if file is a binary or ASCII Model 3D file.
@@ -225,7 +227,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
 
 // ------------------------------------------------------------------------------------------------
 // convert materials. properties are converted using a static table in M3DMaterials.h
-void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
+void M3DImporter::importMaterials(const M3DWrapper &m3d) {
 	unsigned int i, j, k, l, n;
 	m3dm_t *m;
 	aiString name = aiString(AI_DEFAULT_MATERIAL_NAME);
@@ -233,9 +235,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 	ai_real f;
 
 	ai_assert(mScene != nullptr);
-	ai_assert(m3d_wrap);
+	ai_assert(m3d);
 
-	mScene->mNumMaterials = m3d_wrap->nummaterial + 1;
+	mScene->mNumMaterials = m3d->nummaterial + 1;
 	mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
 
 	ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials);
@@ -248,8 +250,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 	mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
 	mScene->mMaterials[0] = mat;
 
-	for (i = 0; i < m3d_wrap->nummaterial; i++) {
-		m = &m3d_wrap->material[i];
+	if (!m3d->nummaterial || !m3d->material) {
+		return;
+	}
+
+	for (i = 0; i < m3d->nummaterial; i++) {
+		m = &m3d->material[i];
 		aiMaterial *mat = new aiMaterial;
 		name.Set(std::string(m->name));
 		mat->AddProperty(&name, AI_MATKEY_NAME);
@@ -294,9 +300,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 			// texture map properties
 			if (m->prop[j].type >= 128 && aiTxProps[k].pKey &&
 					// extra check, should never happen, do we have the refered texture?
-					m->prop[j].value.textureid < m3d_wrap->numtexture &&
-					m3d_wrap->texture[m->prop[j].value.textureid].name) {
-				name.Set(std::string(std::string(m3d_wrap->texture[m->prop[j].value.textureid].name) + ".png"));
+					m->prop[j].value.textureid < m3d->numtexture &&
+					m3d->texture[m->prop[j].value.textureid].name) {
+				name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png"));
 				mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
 				n = 0;
 				mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
@@ -310,7 +316,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 // import textures, this is the simplest of all
 void M3DImporter::importTextures(const M3DWrapper &m3d) {
 	unsigned int i;
-	const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" };
+	const char *formatHint[] = {
+		"rgba0800",
+		"rgba0808",
+		"rgba8880",
+		"rgba8888"
+	};
 	m3dtx_t *t;
 
 	ai_assert(mScene != nullptr);
@@ -319,8 +330,9 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
 	mScene->mNumTextures = m3d->numtexture;
 	ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures);
 
-	if (!m3d->numtexture)
+	if (!m3d->numtexture || !m3d->texture) {
 		return;
+	}
 
 	mScene->mTextures = new aiTexture *[m3d->numtexture];
 	for (i = 0; i < m3d->numtexture; i++) {
@@ -371,7 +383,13 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
 // individually. In assimp there're per mesh vertex and UV lists, and they must be
 // indexed simultaneously.
 void M3DImporter::importMeshes(const M3DWrapper &m3d) {
-	unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX;
+	ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface);
+
+	if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) {
+		return;
+	}
+
+    unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX;
 	std::vector<aiMesh *> *meshes = new std::vector<aiMesh *>();
 	std::vector<aiFace> *faces = nullptr;
 	std::vector<aiVector3D> *vertices = nullptr;
@@ -385,7 +403,6 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 	ai_assert(m3d);
 	ai_assert(mScene->mRootNode != nullptr);
 
-	ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface);
 
 	for (i = 0; i < m3d->numface; i++) {
 		// we must switch mesh if material changes
@@ -420,6 +437,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 			k = static_cast<unsigned int>(vertices->size());
 			pFace->mIndices[j] = k;
 			l = m3d->face[i].vertex[j];
+			if(l >= m3d->numvertex) continue;
 			pos.x = m3d->vertex[l].x;
 			pos.y = m3d->vertex[l].y;
 			pos.z = m3d->vertex[l].z;
@@ -432,14 +450,14 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 				vertexids->push_back(l);
 			}
 			l = m3d->face[i].texcoord[j];
-			if (l != M3D_UNDEF) {
+			if (l != M3D_UNDEF && l < m3d->numtmap) {
 				uv.x = m3d->tmap[l].u;
 				uv.y = m3d->tmap[l].v;
 				uv.z = 0.0;
 				texcoords->push_back(uv);
 			}
 			l = m3d->face[i].normal[j];
-			if (l != M3D_UNDEF) {
+			if (l != M3D_UNDEF && l < m3d->numvertex) {
 				norm.x = m3d->vertex[l].x;
 				norm.y = m3d->vertex[l].y;
 				norm.z = m3d->vertex[l].z;
@@ -487,8 +505,15 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo
 
 	ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid);
 
-	for (n = 0, i = parentid + 1; i < m3d->numbone; i++)
-		if (m3d->bone[i].parent == parentid) n++;
+	if (!m3d->numbone || !m3d->bone) {
+		return;
+	}
+
+	for (n = 0, i = parentid + 1; i < m3d->numbone; i++) {
+		if (m3d->bone[i].parent == parentid) {
+			n++;
+		}
+	}
 	pParent->mChildren = new aiNode *[n];
 
 	for (i = parentid + 1; i < m3d->numbone; i++) {
@@ -521,8 +546,9 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) {
 
 	ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations);
 
-	if (!m3d->numaction || !m3d->numbone)
+	if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) {
 		return;
+	}
 
 	mScene->mAnimations = new aiAnimation *[m3d->numaction];
 	for (i = 0; i < m3d->numaction; i++) {
@@ -552,6 +578,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) {
 						ori = a->frame[j].transform[k].ori;
 					}
 				}
+				if(pos >= m3d->numvertex || ori >= m3d->numvertex) continue;
 				m3dv_t *v = &m3d->vertex[pos];
 				m3dv_t *q = &m3d->vertex[ori];
 				pAnim->mChannels[l]->mPositionKeys[j].mTime = t;
@@ -587,6 +614,8 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
 	ai_assert(m3d);
 	ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex);
 	ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex);
+	if (!m3d->numvertex || !m3d->vertex)
+		return;
 	m3dv_t *p = &m3d->vertex[posid];
 	m3dv_t *q = &m3d->vertex[orientid];
 
@@ -629,16 +658,18 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
 // ------------------------------------------------------------------------------------------------
 // find a node by name
 aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) {
-	unsigned int i;
-
 	ai_assert(pNode != nullptr);
 	ai_assert(mScene != nullptr);
 
-	if (pNode->mName == name)
+	if (pNode->mName == name) {
 		return pNode;
-	for (i = 0; i < pNode->mNumChildren; i++) {
+	}
+
+	for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
 		aiNode *pChild = findNode(pNode->mChildren[i], name);
-		if (pChild) return pChild;
+		if (pChild) {
+			return pChild;
+		}
 	}
 	return nullptr;
 }
@@ -700,8 +731,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 		// this is complicated, because M3D stores a list of bone id / weight pairs per
 		// vertex but assimp uses lists of local vertex id/weight pairs per local bone list
 		pMesh->mNumBones = m3d->numbone;
-		/* we need aiBone with mOffsetMatrix for bones without weights as well */
-		if (pMesh->mNumBones) {
+		// we need aiBone with mOffsetMatrix for bones without weights as well
+		if (pMesh->mNumBones && m3d->numbone && m3d->bone) {
 			pMesh->mBones = new aiBone *[pMesh->mNumBones];
 			for (unsigned int i = 0; i < m3d->numbone; i++) {
 				aiNode *pNode;
@@ -715,10 +746,13 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 				} else
 					pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4();
 			}
-			if (vertexids->size()) {
+			if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) {
 				unsigned int i, j;
 				// first count how many vertices we have per bone
 				for (i = 0; i < vertexids->size(); i++) {
+					if(vertexids->at(i) >= m3d->numvertex) {
+						continue;
+					}
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
 					if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
@@ -742,9 +776,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 				}
 				// fill up with data
 				for (i = 0; i < vertexids->size(); i++) {
+					if(vertexids->at(i) >= m3d->numvertex) continue;
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
-					if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
+					if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
+							if(m3d->skin[s].boneid[k] >= m3d->numbone) continue;
 							aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name));
 							for (j = 0; j < pMesh->mNumBones; j++) {
 								if (pMesh->mBones[j]->mName == name) {

+ 1 - 0
code/glTF/glTFAsset.h

@@ -191,6 +191,7 @@ namespace glTF
     //! Values for the BufferView::target field
     enum BufferViewTarget
     {
+        BufferViewTarget_NONE = 0,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
     };

+ 3 - 1
code/glTF/glTFAssetWriter.inl

@@ -203,7 +203,9 @@ namespace glTF {
         obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl);
         obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
         obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
-        obj.AddMember("target", int(bv.target), w.mAl);
+        if (bv.target != BufferViewTarget_NONE) {
+            obj.AddMember("target", int(bv.target), w.mAl);
+        }
     }
 
     inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/)

+ 8 - 12
code/glTF/glTFExporter.cpp

@@ -160,10 +160,7 @@ static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o)
 
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
 {
-    o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
-    o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
-    o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
-    o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+    memcpy(&o, &v, sizeof(aiMatrix4x4));
 }
 
 static void IdentityMatrix4(glTF::mat4& o)
@@ -230,9 +227,8 @@ inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* da
 	}
 }
 
-inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
-    unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
-{
+inline Ref<Accessor> ExportData(Asset &a, std::string &meshName, Ref<Buffer> &buffer,
+        unsigned int count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) {
     if (!count || !data) return Ref<Accessor>();
 
     unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
@@ -251,7 +247,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     bv->buffer = buffer;
     bv->byteOffset = unsigned(offset);
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
-    bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
+    bv->target = target;
 
     // accessor
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
@@ -616,13 +612,13 @@ void glTFExporter::ExportMeshes()
 		// If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
 		if(comp_allow) idx_srcdata_begin = b->byteLength;
 
-        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+        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 ********************/
 		if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array.
 
-		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		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 **************/
@@ -639,7 +635,7 @@ void glTFExporter::ExportMeshes()
 
 				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, false);
+				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);
 			}
 		}
@@ -657,7 +653,7 @@ void glTFExporter::ExportMeshes()
                 }
             }
 
-			p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true);
+			p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
 		}
 
         switch (aim->mPrimitiveTypes) {

+ 1 - 0
code/glTF2/glTF2Asset.h

@@ -198,6 +198,7 @@ namespace glTF2
     //! Values for the BufferView::target field
     enum BufferViewTarget
     {
+        BufferViewTarget_NONE = 0,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
     };

+ 4 - 4
code/glTF2/glTF2AssetWriter.inl

@@ -176,13 +176,13 @@ namespace glTF2 {
                 valSampler.AddMember("input", s.input->index, w.mAl);
                 switch (s.interpolation) {
                     case Interpolation_LINEAR:
-                        valSampler.AddMember("path", "LINEAR", w.mAl);
+                        valSampler.AddMember("interpolation", "LINEAR", w.mAl);
                         break;
                     case Interpolation_STEP:
-                        valSampler.AddMember("path", "STEP", w.mAl);
+                        valSampler.AddMember("interpolation", "STEP", w.mAl);
                         break;
                     case Interpolation_CUBICSPLINE:
-                        valSampler.AddMember("path", "CUBICSPLINE", w.mAl);
+                        valSampler.AddMember("interpolation", "CUBICSPLINE", w.mAl);
                         break;
                 }
                 valSampler.AddMember("output", s.output->index, w.mAl);
@@ -209,7 +209,7 @@ namespace glTF2 {
         if (bv.byteStride != 0) {
             obj.AddMember("byteStride", bv.byteStride, w.mAl);
         }
-        if (bv.target != 0) {
+        if (bv.target != BufferViewTarget_NONE) {
             obj.AddMember("target", int(bv.target), w.mAl);
         }
     }

+ 29 - 13
code/glTF2/glTF2Exporter.cpp

@@ -141,10 +141,7 @@ static void CopyValue(const aiMatrix4x4& v, mat4& o) {
 }
 
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) {
-    o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
-    o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
-    o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
-    o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+    memcpy(&o, &v, sizeof(aiMatrix4x4));
 }
 
 static void IdentityMatrix4(mat4& o) {
@@ -211,7 +208,7 @@ inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* da
 }
 
 inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
-    size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
+    size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE)
 {
     if (!count || !data) {
         return Ref<Accessor>();
@@ -234,7 +231,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     bv->byteOffset = offset;
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
     bv->byteStride = 0;
-    bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
+    bv->target = target;
 
     // accessor
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
@@ -747,7 +744,7 @@ void glTF2Exporter::ExportMeshes()
         p.material = mAsset->materials.Get(aim->mMaterialIndex);
 
 		/******************* Vertices ********************/
-        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		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 ********************/
@@ -758,7 +755,7 @@ void glTF2Exporter::ExportMeshes()
             }
         }
 
-		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		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 **************/
@@ -776,14 +773,14 @@ 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, false);
+				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, false);
+			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);
 		}
@@ -799,7 +796,7 @@ void glTF2Exporter::ExportMeshes()
                 }
             }
 
-			p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true);
+			p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
 		}
 
         switch (aim->mPrimitiveTypes) {
@@ -956,8 +953,27 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& parent)
     node->name = name;
 
     if (!n->mTransformation.IsIdentity()) {
-        node->matrix.isPresent = true;
-        CopyValue(n->mTransformation, node->matrix.value);
+		if (mScene->mNumAnimations > 0) {
+			aiQuaternion quaternion;
+			n->mTransformation.Decompose(*reinterpret_cast<aiVector3D *>(&node->scale.value), quaternion, *reinterpret_cast<aiVector3D *>(&node->translation.value));
+
+			aiVector3D vector(static_cast<ai_real>(1.0f), static_cast<ai_real>(1.0f), static_cast<ai_real>(1.0f));
+			if (!reinterpret_cast<aiVector3D *>(&node->scale.value)->Equal(vector)) {
+				node->scale.isPresent = true;
+			}
+			if (!reinterpret_cast<aiVector3D *>(&node->translation.value)->Equal(vector)) {
+				node->translation.isPresent = true;
+			}
+			node->rotation.isPresent = true;
+			node->rotation.value[0] = quaternion.x;
+			node->rotation.value[1] = quaternion.y;
+			node->rotation.value[2] = quaternion.z;
+			node->rotation.value[3] = quaternion.w;
+			node->matrix.isPresent = false;
+		} else {
+			node->matrix.isPresent = true;
+			CopyValue(n->mTransformation, node->matrix.value);
+		}
     }
 
     for (unsigned int i = 0; i < n->mNumMeshes; ++i) {

+ 5 - 0
code/glTF2/glTF2Importer.cpp

@@ -925,6 +925,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
 
 	if (node.camera) {
 		pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
+		if (node.translation.isPresent) {
+			aiVector3D trans;
+			CopyValue(node.translation.value, trans);
+			pScene->mCameras[node.camera.GetIndex()]->mPosition = trans;
+		}
 	}
 
 	if (node.light) {