find skeleton root joint and only allow four joint weights per vertex

pull/1034/head
Angelo Scandaliato 2016-10-11 15:28:04 -07:00
parent 1f377bc99d
commit 57a00d5faa
3 changed files with 63 additions and 32 deletions

View File

@ -811,6 +811,8 @@ namespace glTF
Ref<Skin> skin; //!< The ID of the skin referenced by this node. Ref<Skin> skin; //!< The ID of the skin referenced by this node.
std::string jointName; //!< Name used when this node is a joint in a skin. std::string jointName; //!< Name used when this node is a joint in a skin.
Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
Node() {} Node() {}
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
}; };

View File

@ -132,7 +132,7 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc
ExportMaterials(); ExportMaterials();
if (mScene->mRootNode) { if (mScene->mRootNode) {
ExportNode(mScene->mRootNode); ExportNodeHierarchy(mScene->mRootNode);
} }
ExportMeshes(); ExportMeshes();
@ -391,39 +391,33 @@ bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
/* /*
* Find the root joint of the skeleton. * Find the root joint of the skeleton.
* Starts will any joint node and traces up the tree,
* until a parent is found that does not have a jointName.
* Returns the first parent Ref<Node> found that does not have a jointName.
*/ */
Ref<Node> FindSkeletonRootJoint(Ref<Skin>& skinRef) Ref<Node> FindSkeletonRootJoint(Ref<Skin>& skinRef)
{ {
Ref<Node> candidateNodeRef; Ref<Node> startNodeRef;
Ref<Node> testNodeRef; Ref<Node> parentNodeRef;
for (unsigned int i = 0; i < skinRef->jointNames.size(); ++i) { // Arbitrarily use the first joint to start the search.
candidateNodeRef = skinRef->jointNames[i]; startNodeRef = skinRef->jointNames[0];
bool candidateIsRoot = true; parentNodeRef = skinRef->jointNames[0];
for (unsigned int j = 0; j < skinRef->jointNames.size(); ++j) { do {
if (i == j) continue; startNodeRef = parentNodeRef;
parentNodeRef = startNodeRef->parent;
} while (!parentNodeRef->jointName.empty());
testNodeRef = skinRef->jointNames[j]; return parentNodeRef;
for (unsigned int k = 0; k < testNodeRef->children.size(); ++k) {
std::string childNodeRefID = testNodeRef->children[k]->id;
if (childNodeRefID.compare(candidateNodeRef->id) == 0) {
candidateIsRoot = false;
}
}
}
if(candidateIsRoot == true) {
return candidateNodeRef;
}
}
return candidateNodeRef;
} }
void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef) void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer>& bufferRef)
{ {
if (aim->mNumBones < 1) {
return;
}
std::string skinName = aim->mName.C_Str(); std::string skinName = aim->mName.C_Str();
skinName = mAsset.FindUniqueID(skinName, "skin"); skinName = mAsset.FindUniqueID(skinName, "skin");
Ref<Skin> skinRef = mAsset.skins.Create(skinName); Ref<Skin> skinRef = mAsset.skins.Create(skinName);
@ -434,7 +428,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer
// Store the vertex joint and weight data. // Store the vertex joint and weight data.
vec4* vertexJointData = new vec4[aim->mNumVertices]; vec4* vertexJointData = new vec4[aim->mNumVertices];
vec4* vertexWeightData = new vec4[aim->mNumVertices]; vec4* vertexWeightData = new vec4[aim->mNumVertices];
unsigned int* jointsPerVertex = new unsigned int[aim->mNumVertices]; int* jointsPerVertex = new int[aim->mNumVertices];
for (size_t i = 0; i < aim->mNumVertices; ++i) { for (size_t i = 0; i < aim->mNumVertices; ++i) {
jointsPerVertex[i] = 0; jointsPerVertex[i] = 0;
for (size_t j = 0; j < 4; ++j) { for (size_t j = 0; j < 4; ++j) {
@ -462,11 +456,16 @@ void ExportSkin(Asset& mAsset, const aiMesh* aim, Ref<Mesh>& meshRef, Ref<Buffer
// aib->mWeights =====> vertexWeightData // aib->mWeights =====> vertexWeightData
for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) { for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) {
aiVertexWeight tmpVertWeight = aib->mWeights[idx_weights]; unsigned int vertexId = aib->mWeights[idx_weights].mVertexId;
vertexJointData[tmpVertWeight.mVertexId][jointsPerVertex[tmpVertWeight.mVertexId]] = idx_bone; float vertWeight = aib->mWeights[idx_weights].mWeight;
vertexWeightData[tmpVertWeight.mVertexId][jointsPerVertex[tmpVertWeight.mVertexId]] = tmpVertWeight.mWeight;
jointsPerVertex[tmpVertWeight.mVertexId] += 1; // A vertex can only have at most four joint weights. Ignore all others.
if (jointsPerVertex[vertexId] > 3) { continue; }
vertexJointData[vertexId][jointsPerVertex[vertexId]] = idx_bone;
vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
jointsPerVertex[vertexId] += 1;
} }
} // End: for-loop mNumMeshes } // End: for-loop mNumMeshes
@ -714,7 +713,8 @@ void glTFExporter::ExportMeshes()
}// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) }// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i)
} }
unsigned int glTFExporter::ExportNode(const aiNode* n)
unsigned int glTFExporter::ExportNodeHierarchy(const aiNode* n)
{ {
Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node"));
@ -728,7 +728,31 @@ unsigned int glTFExporter::ExportNode(const aiNode* n)
} }
for (unsigned int i = 0; i < n->mNumChildren; ++i) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
unsigned int idx = ExportNode(n->mChildren[i]); unsigned int idx = ExportNode(n->mChildren[i], node);
node->children.push_back(mAsset->nodes.Get(idx));
}
return node.GetIndex();
}
unsigned int glTFExporter::ExportNode(const aiNode* n, Ref<Node>& parent)
{
Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node"));
node->parent = parent;
if (!n->mTransformation.IsIdentity()) {
node->matrix.isPresent = true;
CopyValue(n->mTransformation, node->matrix.value);
}
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
node->meshes.push_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.push_back(mAsset->nodes.Get(idx));
} }

View File

@ -58,8 +58,12 @@ struct aiMaterial;
namespace glTF namespace glTF
{ {
template<class T>
class Ref;
class Asset; class Asset;
struct TexProperty; struct TexProperty;
struct Node;
} }
namespace Assimp namespace Assimp
@ -98,7 +102,8 @@ namespace Assimp
void ExportMetadata(); void ExportMetadata();
void ExportMaterials(); void ExportMaterials();
void ExportMeshes(); void ExportMeshes();
unsigned int ExportNode(const aiNode* node); unsigned int ExportNodeHierarchy(const aiNode* n);
unsigned int ExportNode(const aiNode* node, glTF::Ref<glTF::Node>& parent);
void ExportScene(); void ExportScene();
void ExportAnimations(); void ExportAnimations();
}; };