Merge pull request #2215 from ruyo/gltf_skinmesh

glTF2 importer multiple primitives and 16-bit index buffer skinmesh support.
pull/2223/head
Kim Kulling 2018-11-13 16:07:10 +01:00 committed by GitHub
commit e6905b6a5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 42 additions and 32 deletions

View File

@ -732,9 +732,9 @@ static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) {
} }
} }
static void BuildVertexWeightMapping(Ref<Mesh>& mesh, std::vector<std::vector<aiVertexWeight>>& map) static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector<std::vector<aiVertexWeight>>& map)
{ {
Mesh::Primitive::Attributes& attr = mesh->primitives[0].attributes; Mesh::Primitive::Attributes& attr = primitive.attributes;
if (attr.weight.empty() || attr.joint.empty()) { if (attr.weight.empty() || attr.joint.empty()) {
return; return;
} }
@ -745,15 +745,22 @@ static void BuildVertexWeightMapping(Ref<Mesh>& mesh, std::vector<std::vector<ai
const int num_vertices = attr.weight[0]->count; const int num_vertices = attr.weight[0]->count;
struct Weights { float values[4]; }; struct Weights { float values[4]; };
struct Indices { uint8_t values[4]; };
Weights* weights = nullptr; Weights* weights = nullptr;
Indices* indices = nullptr;
attr.weight[0]->ExtractData(weights); attr.weight[0]->ExtractData(weights);
attr.joint[0]->ExtractData(indices);
struct Indices8 { uint8_t values[4]; };
struct Indices16 { uint16_t values[4]; };
Indices8* indices8 = nullptr;
Indices16* indices16 = nullptr;
if (attr.joint[0]->GetElementSize() == 4) {
attr.joint[0]->ExtractData(indices8);
}else {
attr.joint[0]->ExtractData(indices16);
}
for (int i = 0; i < num_vertices; ++i) { for (int i = 0; i < num_vertices; ++i) {
for (int j = 0; j < 4; ++j) { for (int j = 0; j < 4; ++j) {
const unsigned int bone = indices[i].values[j]; const unsigned int bone = (indices8!=nullptr) ? indices8[i].values[j] : indices16[i].values[j];
const float weight = weights[i].values[j]; const float weight = weights[i].values[j];
if (weight > 0 && bone < map.size()) { if (weight > 0 && bone < map.size()) {
map[bone].reserve(8); map[bone].reserve(8);
@ -763,7 +770,8 @@ static void BuildVertexWeightMapping(Ref<Mesh>& mesh, std::vector<std::vector<ai
} }
delete[] weights; delete[] weights;
delete[] indices; delete[] indices8;
delete[] indices16;
} }
aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr) aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
@ -797,7 +805,8 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
ainode->mMeshes = new unsigned int[count]; ainode->mMeshes = new unsigned int[count];
if (node.skin) { if (node.skin) {
aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]]; for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]+primitiveNo];
mesh->mNumBones = node.skin->jointNames.size(); mesh->mNumBones = node.skin->jointNames.size();
mesh->mBones = new aiBone*[mesh->mNumBones]; mesh->mBones = new aiBone*[mesh->mNumBones];
@ -811,7 +820,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
// we then need to reconvert the data back into the vertex-to-bone // we then need to reconvert the data back into the vertex-to-bone
// mapping which makes things doubly-slow. // mapping which makes things doubly-slow.
std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones); std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones);
BuildVertexWeightMapping(node.meshes[0], weighting); BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
for (size_t i = 0; i < mesh->mNumBones; ++i) { for (size_t i = 0; i < mesh->mNumBones; ++i) {
aiBone* bone = new aiBone(); aiBone* bone = new aiBone();
@ -830,6 +839,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
mesh->mBones[i] = bone; mesh->mBones[i] = bone;
} }
} }
}
int k = 0; int k = 0;
for (unsigned int j = meshOffsets[mesh_idx]; j < meshOffsets[mesh_idx + 1]; ++j, ++k) { for (unsigned int j = meshOffsets[mesh_idx]; j < meshOffsets[mesh_idx + 1]; ++j, ++k) {