mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
Assimp: Add initial support for skeletal mesh animations
This commit is contained in:
parent
1d098b0099
commit
e2c5214f39
@ -32,6 +32,9 @@
|
|||||||
#include "look_at.h"
|
#include "look_at.h"
|
||||||
#include "texturePool.h"
|
#include "texturePool.h"
|
||||||
#include "character.h"
|
#include "character.h"
|
||||||
|
#include "animBundle.h"
|
||||||
|
#include "animBundleNode.h"
|
||||||
|
#include "animChannelMatrixXfmTable.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
|
||||||
#include "pandaIOSystem.h"
|
#include "pandaIOSystem.h"
|
||||||
@ -169,7 +172,7 @@ build_graph() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: AssimpLoader::find_ndoe
|
// Function: AssimpLoader::find_node
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: Finds a node by name.
|
// Description: Finds a node by name.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -434,6 +437,88 @@ create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *pare
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: AssimpLoader::create_anim_channel
|
||||||
|
// Access: Private
|
||||||
|
// Description: Creates a AnimChannelMatrixXfmTable from an aiNodeAnim
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void AssimpLoader::
|
||||||
|
create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node)
|
||||||
|
{
|
||||||
|
PT(AnimChannelMatrixXfmTable) group = new AnimChannelMatrixXfmTable(parent, node.mName.C_Str());
|
||||||
|
|
||||||
|
// See if there is a channel for this node
|
||||||
|
aiNodeAnim *node_anim = NULL;
|
||||||
|
for (size_t i = 0; i < anim.mNumChannels; ++i) {
|
||||||
|
if (anim.mChannels[i]->mNodeName == node.mName) {
|
||||||
|
node_anim = anim.mChannels[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_anim) {
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Found channel for node: " << node.mName.C_Str() << "\n";
|
||||||
|
//assimp_cat.debug()
|
||||||
|
// << "Num Position Keys " << node_anim->mNumPositionKeys << "\n";
|
||||||
|
//assimp_cat.debug()
|
||||||
|
// << "Num Rotation Keys " << node_anim->mNumRotationKeys << "\n";
|
||||||
|
//assimp_cat.debug()
|
||||||
|
// << "Num Scaling Keys " << node_anim->mNumScalingKeys << "\n";
|
||||||
|
|
||||||
|
// Convert positions
|
||||||
|
PTA_stdfloat tablex = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
|
||||||
|
PTA_stdfloat tabley = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
|
||||||
|
PTA_stdfloat tablez = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
|
||||||
|
for (size_t i = 0; i < node_anim->mNumPositionKeys; ++i) {
|
||||||
|
tablex[i] = node_anim->mPositionKeys[i].mValue.x;
|
||||||
|
tabley[i] = node_anim->mPositionKeys[i].mValue.y;
|
||||||
|
tablez[i] = node_anim->mPositionKeys[i].mValue.z;
|
||||||
|
}
|
||||||
|
group->set_table('x', tablex);
|
||||||
|
group->set_table('y', tabley);
|
||||||
|
group->set_table('z', tablez);
|
||||||
|
|
||||||
|
// Convert rotations
|
||||||
|
PTA_stdfloat tableh = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
|
||||||
|
PTA_stdfloat tablep = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
|
||||||
|
PTA_stdfloat tabler = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
|
||||||
|
for (size_t i = 0; i < node_anim->mNumRotationKeys; ++i) {
|
||||||
|
aiQuaternion ai_quat = node_anim->mRotationKeys[i].mValue;
|
||||||
|
LVecBase3 hpr = LQuaternion(ai_quat.w, ai_quat.x, ai_quat.y, ai_quat.z).get_hpr();
|
||||||
|
tableh[i] = hpr.get_x();
|
||||||
|
tablep[i] = hpr.get_y();
|
||||||
|
tabler[i] = hpr.get_z();
|
||||||
|
}
|
||||||
|
group->set_table('h', tableh);
|
||||||
|
group->set_table('p', tablep);
|
||||||
|
group->set_table('r', tabler);
|
||||||
|
|
||||||
|
// Convert scales
|
||||||
|
PTA_stdfloat tablei = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
|
||||||
|
PTA_stdfloat tablej = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
|
||||||
|
PTA_stdfloat tablek = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
|
||||||
|
for (size_t i = 0; i < node_anim->mNumScalingKeys; ++i) {
|
||||||
|
tablei[i] = node_anim->mScalingKeys[i].mValue.x;
|
||||||
|
tablej[i] = node_anim->mScalingKeys[i].mValue.y;
|
||||||
|
tablek[i] = node_anim->mScalingKeys[i].mValue.z;
|
||||||
|
}
|
||||||
|
group->set_table('i', tablei);
|
||||||
|
group->set_table('j', tablej);
|
||||||
|
group->set_table('k', tablek);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "No channel found for node: " << node.mName.C_Str() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node.mNumChildren; ++i) {
|
||||||
|
if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) {
|
||||||
|
create_anim_channel(anim, bundle, group, *node.mChildren[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: AssimpLoader::load_mesh
|
// Function: AssimpLoader::load_mesh
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -508,6 +593,60 @@ load_mesh(size_t index) {
|
|||||||
PT(GeomVertexArrayFormat) tb_aformat = new GeomVertexArrayFormat;
|
PT(GeomVertexArrayFormat) tb_aformat = new GeomVertexArrayFormat;
|
||||||
tb_aformat->add_column(InternalName::make("transform_blend"), 1, Geom::NT_uint16, Geom::C_index);
|
tb_aformat->add_column(InternalName::make("transform_blend"), 1, Geom::NT_uint16, Geom::C_index);
|
||||||
|
|
||||||
|
// Check to see if we need to convert any animations
|
||||||
|
for (size_t i = 0; i < _scene->mNumAnimations; ++i) {
|
||||||
|
aiAnimation &ai_anim = *_scene->mAnimations[i];
|
||||||
|
bool convert_anim = false;
|
||||||
|
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Checking to see if anim (" << ai_anim.mName.C_Str() << ") matches character (" << mesh.mName.C_Str() << ")\n";
|
||||||
|
for (size_t j = 0; j < ai_anim.mNumChannels; ++j) {
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Searching for " << ai_anim.mChannels[j]->mNodeName.C_Str() << " in bone map" << "\n";
|
||||||
|
if (_bonemap.find(ai_anim.mChannels[j]->mNodeName.C_Str()) != _bonemap.end()) {
|
||||||
|
convert_anim = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convert_anim) {
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "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
|
||||||
|
unsigned int frames = 0;
|
||||||
|
for (size_t j = 0; j < ai_anim.mNumChannels; ++j) {
|
||||||
|
if (ai_anim.mChannels[j]->mNumPositionKeys > frames) {
|
||||||
|
frames = ai_anim.mChannels[j]->mNumPositionKeys;
|
||||||
|
}
|
||||||
|
if (ai_anim.mChannels[j]->mNumRotationKeys > frames) {
|
||||||
|
frames = ai_anim.mChannels[j]->mNumRotationKeys;
|
||||||
|
}
|
||||||
|
if (ai_anim.mChannels[j]->mNumScalingKeys > frames) {
|
||||||
|
frames = ai_anim.mChannels[j]->mNumScalingKeys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PN_stdfloat fps = frames / (ai_anim.mTicksPerSecond * ai_anim.mDuration);
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "FPS " << fps << "\n";
|
||||||
|
assimp_cat.debug()
|
||||||
|
<< "Frames " << frames << "\n";
|
||||||
|
|
||||||
|
PT(AnimBundle) bundle = new AnimBundle(mesh.mName.C_Str(), fps, frames);
|
||||||
|
PT(AnimGroup) skeleton = new AnimGroup(bundle, "<skeleton>");
|
||||||
|
create_anim_channel(ai_anim, bundle, skeleton, *root);
|
||||||
|
|
||||||
|
// Attach the animation to the character node
|
||||||
|
PT(AnimBundleNode) bundle_node = new AnimBundleNode("anim", bundle);
|
||||||
|
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
|
||||||
|
|
||||||
PT(GeomVertexFormat) format = new GeomVertexFormat;
|
PT(GeomVertexFormat) format = new GeomVertexFormat;
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
class Character;
|
class Character;
|
||||||
class CharacterJointBundle;
|
class CharacterJointBundle;
|
||||||
class PartGroup;
|
class PartGroup;
|
||||||
|
class AnimBundle;
|
||||||
|
class AnimGroup;
|
||||||
|
|
||||||
struct char_cmp {
|
struct char_cmp {
|
||||||
bool operator () (const char *a, const char *b) const {
|
bool operator () (const char *a, const char *b) const {
|
||||||
@ -76,6 +78,7 @@ private:
|
|||||||
void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr);
|
void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr);
|
||||||
void load_material(size_t index);
|
void load_material(size_t index);
|
||||||
void create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node);
|
void create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node);
|
||||||
|
void create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node);
|
||||||
void load_mesh(size_t index);
|
void load_mesh(size_t index);
|
||||||
void load_node(const aiNode &node, PandaNode *parent);
|
void load_node(const aiNode &node, PandaNode *parent);
|
||||||
void load_light(const aiLight &light);
|
void load_light(const aiLight &light);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user