mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
Assimp: Support skeletons with unconnected bones
We needed to detect islands of bones and create anims and parts for them.
This commit is contained in:
parent
ad238ad995
commit
1df9be6fc0
@ -421,8 +421,7 @@ load_material(size_t index) {
|
|||||||
// Description: Creates a CharacterJoint from an aiNode
|
// Description: Creates a CharacterJoint from an aiNode
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void AssimpLoader::
|
void AssimpLoader::
|
||||||
create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node)
|
create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node) {
|
||||||
{
|
|
||||||
const aiMatrix4x4 &t = node.mTransformation;
|
const aiMatrix4x4 &t = node.mTransformation;
|
||||||
LMatrix4 mat(t.a1, t.b1, t.c1, t.d1,
|
LMatrix4 mat(t.a1, t.b1, t.c1, t.d1,
|
||||||
t.a2, t.b2, t.c2, t.d2,
|
t.a2, t.b2, t.c2, t.d2,
|
||||||
@ -430,6 +429,9 @@ create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *pare
|
|||||||
t.a4, t.b4, t.c4, t.d4);
|
t.a4, t.b4, t.c4, t.d4);
|
||||||
PT(CharacterJoint) joint = new CharacterJoint(character, bundle, parent, node.mName.C_Str(), mat);
|
PT(CharacterJoint) joint = new CharacterJoint(character, bundle, parent, node.mName.C_Str(), mat);
|
||||||
|
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Creating joint for: " << node.mName.C_Str() << "\n";
|
||||||
|
|
||||||
for (size_t i = 0; i < node.mNumChildren; ++i) {
|
for (size_t i = 0; i < node.mNumChildren; ++i) {
|
||||||
if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) {
|
if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) {
|
||||||
create_joint(character, bundle, joint, *node.mChildren[i]);
|
create_joint(character, bundle, joint, *node.mChildren[i]);
|
||||||
@ -443,8 +445,7 @@ create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *pare
|
|||||||
// Description: Creates a AnimChannelMatrixXfmTable from an aiNodeAnim
|
// Description: Creates a AnimChannelMatrixXfmTable from an aiNodeAnim
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void AssimpLoader::
|
void AssimpLoader::
|
||||||
create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node)
|
create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node) {
|
||||||
{
|
|
||||||
PT(AnimChannelMatrixXfmTable) group = new AnimChannelMatrixXfmTable(parent, node.mName.C_Str());
|
PT(AnimChannelMatrixXfmTable) group = new AnimChannelMatrixXfmTable(parent, node.mName.C_Str());
|
||||||
|
|
||||||
// See if there is a channel for this node
|
// See if there is a channel for this node
|
||||||
@ -541,18 +542,28 @@ load_mesh(size_t index) {
|
|||||||
_bonemap[bone.mName.C_Str()] = node;
|
_bonemap[bone.mName.C_Str()] = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the root bone node
|
|
||||||
const aiNode *root = _bonemap[mesh.mBones[0]->mName.C_Str()];
|
|
||||||
while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
|
|
||||||
root = root->mParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now create a character from the bones
|
// Now create a character from the bones
|
||||||
character = new Character(mesh.mName.C_Str());
|
character = new Character(mesh.mName.C_Str());
|
||||||
PT(CharacterJointBundle) bundle = character->get_bundle(0);
|
PT(CharacterJointBundle) bundle = character->get_bundle(0);
|
||||||
PT(PartGroup) skeleton = new PartGroup(bundle, "<skeleton>");
|
PT(PartGroup) skeleton = new PartGroup(bundle, "<skeleton>");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mesh.mNumBones; ++i) {
|
||||||
|
const aiBone &bone = *mesh.mBones[i];
|
||||||
|
|
||||||
|
// Find the root bone node
|
||||||
|
const aiNode *root = _bonemap[bone.mName.C_Str()];
|
||||||
|
while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
|
||||||
|
root = root->mParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't process this root if we already have a joint for it
|
||||||
|
if (character->find_joint(root->mName.C_Str())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
create_joint(character, bundle, skeleton, *root);
|
create_joint(character, bundle, skeleton, *root);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create transform blend table
|
// Create transform blend table
|
||||||
PT(TransformBlendTable) tbtable = new TransformBlendTable;
|
PT(TransformBlendTable) tbtable = new TransformBlendTable;
|
||||||
@ -561,7 +572,11 @@ load_mesh(size_t index) {
|
|||||||
for (size_t i = 0; i < mesh.mNumBones; ++i) {
|
for (size_t i = 0; i < mesh.mNumBones; ++i) {
|
||||||
const aiBone &bone = *mesh.mBones[i];
|
const aiBone &bone = *mesh.mBones[i];
|
||||||
CharacterJoint *joint = character->find_joint(bone.mName.C_Str());
|
CharacterJoint *joint = character->find_joint(bone.mName.C_Str());
|
||||||
nassertd(joint != NULL) continue;
|
if (joint == NULL) {
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Could not find joint for bone: " << bone.mName.C_Str() << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
CPT(JointVertexTransform) jvt = new JointVertexTransform(joint);
|
CPT(JointVertexTransform) jvt = new JointVertexTransform(joint);
|
||||||
|
|
||||||
@ -615,11 +630,6 @@ load_mesh(size_t index) {
|
|||||||
if (convert_anim) {
|
if (convert_anim) {
|
||||||
assimp_cat.debug()
|
assimp_cat.debug()
|
||||||
<< "Found animation (" << ai_anim.mName.C_Str() << ") for character (" << mesh.mName.C_Str() << ")\n";
|
<< "Found animation (" << ai_anim.mName.C_Str() << ") for character (" << mesh.mName.C_Str() << ")\n";
|
||||||
// Find the root bone node
|
|
||||||
const aiNode *root = _bonemap[mesh.mBones[0]->mName.C_Str()];
|
|
||||||
while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
|
|
||||||
root = root->mParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now create the animation
|
// Now create the animation
|
||||||
unsigned int frames = 0;
|
unsigned int frames = 0;
|
||||||
@ -642,13 +652,27 @@ load_mesh(size_t index) {
|
|||||||
|
|
||||||
PT(AnimBundle) bundle = new AnimBundle(mesh.mName.C_Str(), fps, frames);
|
PT(AnimBundle) bundle = new AnimBundle(mesh.mName.C_Str(), fps, frames);
|
||||||
PT(AnimGroup) skeleton = new AnimGroup(bundle, "<skeleton>");
|
PT(AnimGroup) skeleton = new AnimGroup(bundle, "<skeleton>");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mesh.mNumBones; ++i) {
|
||||||
|
const aiBone &bone = *mesh.mBones[i];
|
||||||
|
|
||||||
|
// Find the root bone node
|
||||||
|
const aiNode *root = _bonemap[bone.mName.C_Str()];
|
||||||
|
while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
|
||||||
|
root = root->mParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only convert root nodes
|
||||||
|
if (root->mName == bone.mName) {
|
||||||
create_anim_channel(ai_anim, bundle, skeleton, *root);
|
create_anim_channel(ai_anim, bundle, skeleton, *root);
|
||||||
|
|
||||||
// Attach the animation to the character node
|
// Attach the animation to the character node
|
||||||
PT(AnimBundleNode) bundle_node = new AnimBundleNode("anim", bundle);
|
PT(AnimBundleNode) bundle_node = new AnimBundleNode(bone.mName.C_Str(), bundle);
|
||||||
character->add_child(bundle_node);
|
character->add_child(bundle_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: if there is only one UV set, hackily iterate over the texture stages and clear the texcoord name things
|
//TODO: if there is only one UV set, hackily iterate over the texture stages and clear the texcoord name things
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user