diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 765f5e0f8..cece307d9 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -775,7 +775,7 @@ namespace glTF2 PrimitiveMode mode; struct Attributes { - AccessorList position, normal, texcoord, color, joint, jointmatrix, weight; + AccessorList position, normal, tangent, texcoord, color, joint, jointmatrix, weight; } attributes; Ref indices; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 29ab9a49a..549df747e 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -867,6 +867,9 @@ namespace { else if ((pos = Compare(attr, "NORMAL"))) { v = &(p.attributes.normal); } + else if ((pos = Compare(attr, "TANGENT"))) { + v = &(p.attributes.tangent); + } else if ((pos = Compare(attr, "TEXCOORD"))) { v = &(p.attributes.texcoord); } @@ -906,7 +909,7 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { if (!it->value.IsUint()) continue; const char* attr = it->name.GetString(); - // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, + // Valid attribute semantics include POSITION, NORMAL, TANGENT, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. int undPos = 0; diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 297f2bc72..ca12d3657 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -362,7 +362,31 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) attr.position[0]->ExtractData(aim->mVertices); } - if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); + if (attr.normal.size() > 0 && attr.normal[0]) { + attr.normal[0]->ExtractData(aim->mNormals); + + // only extract tangents if normals are present + if (attr.tangent.size() > 0 && attr.tangent[0]) { + // generate bitangents from normals and tangents according to spec + struct Tangent + { + aiVector3D xyz; + ai_real w; + } *tangents = nullptr; + + attr.tangent[0]->ExtractData(tangents); + + aim->mTangents = new aiVector3D[aim->mNumVertices]; + aim->mBitangents = new aiVector3D[aim->mNumVertices]; + + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + aim->mTangents[i] = tangents[i].xyz; + aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; + } + + delete tangents; + } + } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); @@ -492,7 +516,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& { Node& node = *ptr; - aiNode* ainode = new aiNode(node.id); + aiNode* ainode = new aiNode(node.name); if (!node.children.empty()) { ainode->mNumChildren = unsigned(node.children.size()); @@ -515,7 +539,13 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& CopyValue(node.translation.value, trans); aiMatrix4x4 t; aiMatrix4x4::Translation(trans, t); - matrix = t * matrix; + matrix = matrix * t; + } + + if (node.rotation.isPresent) { + aiQuaternion rot; + CopyValue(node.rotation.value, rot); + matrix = matrix * aiMatrix4x4(rot.GetMatrix()); } if (node.scale.isPresent) { @@ -523,14 +553,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& CopyValue(node.scale.value, scal); aiMatrix4x4 s; aiMatrix4x4::Scaling(scal, s); - matrix = s * matrix; - } - - - if (node.rotation.isPresent) { - aiQuaternion rot; - CopyValue(node.rotation.value, rot); - matrix = aiMatrix4x4(rot.GetMatrix()) * matrix; + matrix = matrix * s; } }