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..7b05dc000 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]);