mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
Add animation support to dae2egg
This commit is contained in:
parent
6263a591be
commit
9aafde0579
@ -17,11 +17,22 @@
|
|||||||
#include "fcollada_utils.h"
|
#include "fcollada_utils.h"
|
||||||
#include "pt_EggVertex.h"
|
#include "pt_EggVertex.h"
|
||||||
#include "eggXfmSAnim.h"
|
#include "eggXfmSAnim.h"
|
||||||
|
#include "daeToEggConverter.h"
|
||||||
|
#include "daeMaterials.h"
|
||||||
|
|
||||||
|
#include "eggExternalReference.h"
|
||||||
|
|
||||||
#include "FCDocument/FCDocument.h"
|
#include "FCDocument/FCDocument.h"
|
||||||
#include "FCDocument/FCDController.h"
|
#include "FCDocument/FCDController.h"
|
||||||
|
#include "FCDocument/FCDGeometry.h"
|
||||||
#include "FCDocument/FCDSceneNodeTools.h"
|
#include "FCDocument/FCDSceneNodeTools.h"
|
||||||
|
|
||||||
|
#include "FCDocument/FCDSceneNode.h"
|
||||||
|
#include "FCDocument/FCDTransform.h"
|
||||||
|
#include "FCDocument/FCDAnimated.h"
|
||||||
|
#include "FCDocument/FCDAnimationCurve.h"
|
||||||
|
#include "FCDocument/FCDAnimationKey.h"
|
||||||
|
|
||||||
TypeHandle DaeCharacter::_type_handle;
|
TypeHandle DaeCharacter::_type_handle;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -30,75 +41,292 @@ TypeHandle DaeCharacter::_type_handle;
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
DaeCharacter::
|
DaeCharacter::
|
||||||
DaeCharacter(const string name, const FCDControllerInstance* controller_instance) {
|
DaeCharacter(EggGroup *node_group, const FCDControllerInstance *instance) :
|
||||||
_controller_instance = (FCDControllerInstance*) controller_instance;
|
_node_group(node_group),
|
||||||
_name = name;
|
_name(node_group->get_name()),
|
||||||
_frame_rate = 0;
|
_instance(instance),
|
||||||
_skin_controller = NULL;
|
_skin_controller(NULL),
|
||||||
|
_skin_mesh(NULL) {
|
||||||
|
|
||||||
|
_bind_shape_mat = LMatrix4d::ident_mat();
|
||||||
|
|
||||||
// If it's a skin controller, add the controller joints.
|
// If it's a skin controller, add the controller joints.
|
||||||
FCDController* controller = (FCDController*) controller_instance->GetEntity();
|
const FCDController *controller = (const FCDController *)instance->GetEntity();
|
||||||
if (controller == NULL) return;
|
if (controller == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_skin_mesh = controller->GetBaseGeometry()->GetMesh();
|
||||||
|
|
||||||
if (controller->IsSkin()) {
|
if (controller->IsSkin()) {
|
||||||
_skin_controller = controller->GetSkinController();
|
_skin_controller = controller->GetSkinController();
|
||||||
if (_skin_controller == NULL) return;
|
_bind_shape_mat = DAEToEggConverter::convert_matrix(_skin_controller->GetBindShapeTransform());
|
||||||
for (size_t j = 0; j < _skin_controller->GetJointCount(); ++j) {
|
}
|
||||||
_controller_joints[FROM_FSTRING(_skin_controller->GetJoint(j)->GetId())] = (FCDSkinControllerJoint*) _skin_controller->GetJoint(j);
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DaeCharacter::bind_joints
|
||||||
|
// Access: Public
|
||||||
|
// Description: Binds the joints to the character. This means
|
||||||
|
// changing them to the bind pose. It is necessary
|
||||||
|
// to call this before process_skin_geometry.
|
||||||
|
//
|
||||||
|
// Returns the root group.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DaeCharacter::
|
||||||
|
bind_joints(JointMap &joint_map) {
|
||||||
|
_joints.clear();
|
||||||
|
|
||||||
|
size_t num_joints = _skin_controller->GetJointCount();
|
||||||
|
_joints.reserve(num_joints);
|
||||||
|
|
||||||
|
// Record the bind pose for each joint.
|
||||||
|
for (size_t j = 0; j < num_joints; ++j) {
|
||||||
|
const FCDSkinControllerJoint *skin_joint = _skin_controller->GetJoint(j);
|
||||||
|
string sid = FROM_FSTRING(skin_joint->GetId());
|
||||||
|
LMatrix4d bind_pose;
|
||||||
|
bind_pose.invert_from(DAEToEggConverter::convert_matrix(
|
||||||
|
skin_joint->GetBindPoseInverse()));
|
||||||
|
|
||||||
|
// Check that we already encountered this joint during traversal.
|
||||||
|
JointMap::iterator ji = joint_map.find(sid);
|
||||||
|
if (ji != joint_map.end()) {
|
||||||
|
Joint &joint = ji->second;
|
||||||
|
|
||||||
|
if (joint._character != (DaeCharacter *)NULL) {
|
||||||
|
// In some cases, though, multiple controllers share the same joints.
|
||||||
|
// We can't support this without duplicating the joint structure,
|
||||||
|
// so we check if the bind poses are the same.
|
||||||
|
if (!joint._bind_pose.almost_equal(bind_pose, 0.0001)) {
|
||||||
|
// Ugh. What else could we do?
|
||||||
|
daeegg_cat.error()
|
||||||
|
<< "Multiple controllers share joint with sid " << sid
|
||||||
|
<< ", with different bind poses.\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Mark the joint as being controlled by this character.
|
||||||
|
joint._bind_pose = bind_pose;
|
||||||
|
joint._character = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_joints.push_back(joint);
|
||||||
|
} else {
|
||||||
|
daeegg_cat.warning()
|
||||||
|
<< "Unknown joint sid being referenced: '" << sid << "'\n";
|
||||||
|
|
||||||
|
// We still have to add a dummy joint or the index will be off.
|
||||||
|
_joints.push_back(Joint(NULL, NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DaeCharacter::as_egg_bundle
|
// Function: DaeCharacter::adjust_joints
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns the character as a <Bundle> element,
|
// Description: Traverses through the character hierarchy in order
|
||||||
// suited for the animation table.
|
// to bind the mesh to the character. This involves
|
||||||
|
// reorienting the joints to match the bind pose.
|
||||||
|
//
|
||||||
|
// It is important that this is called only once.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PT(EggTable) DaeCharacter::
|
void DaeCharacter::
|
||||||
as_egg_bundle() {
|
adjust_joints(FCDSceneNode *node, const JointMap &joint_map,
|
||||||
PT(EggTable) bundle = new EggTable(_name);
|
const LMatrix4d &transform) {
|
||||||
bundle->set_table_type(EggTable::TT_bundle);
|
|
||||||
PT(EggTable) skeleton = new EggTable("<skeleton>");
|
LMatrix4d this_transform = transform;
|
||||||
skeleton->set_table_type(EggTable::TT_table);
|
|
||||||
bundle->add_child(skeleton);
|
if (node->IsJoint()) {
|
||||||
// Loop through the joint hierarchy
|
string sid = FROM_FSTRING(node->GetSubId());
|
||||||
#if FCOLLADA_VERSION < 0x00030005
|
|
||||||
FCDSceneNodeList roots = _controller_instance->FindSkeletonNodes();
|
JointMap::const_iterator ji = joint_map.find(sid);
|
||||||
#else
|
if (ji != joint_map.end()) {
|
||||||
FCDSceneNodeList roots;
|
const Joint &joint = ji->second;
|
||||||
_controller_instance->FindSkeletonNodes(roots);
|
|
||||||
#endif
|
// Panda needs the joints to be in bind pose. Not fun! We copy the joint
|
||||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
// transform to the default pose, though, so that Panda will restore the
|
||||||
process_joint(skeleton, *it);
|
// joint transformation after binding.
|
||||||
|
|
||||||
|
if (joint._character == this) {
|
||||||
|
LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat *
|
||||||
|
invert(transform);
|
||||||
|
//LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat *
|
||||||
|
// joint._group->get_parent()->get_node_frame_inv();
|
||||||
|
|
||||||
|
this_transform = bind_pose * this_transform;
|
||||||
|
joint._group->set_default_pose(*joint._group);
|
||||||
|
joint._group->set_transform3d(bind_pose);
|
||||||
|
|
||||||
|
/*
|
||||||
|
PT(EggGroup) sphere = new EggGroup;
|
||||||
|
sphere->add_uniform_scale(0.1);
|
||||||
|
sphere->set_group_type(EggGroup::GT_instance);
|
||||||
|
sphere->add_child(new EggExternalReference("", "jack.egg"));
|
||||||
|
joint._group->add_child(sphere);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//this_transform = DAEToEggConverter::convert_matrix(node->ToMatrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the children joints
|
||||||
|
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||||
|
//if (node->GetChild(ch)->IsJoint()) {
|
||||||
|
adjust_joints(node->GetChild(ch), joint_map, this_transform);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
return bundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: DaeCharacter::process_joint
|
// Function: DaeCharacter::influence_vertex
|
||||||
|
// Access: Public
|
||||||
|
// Description: Adds the influences for the given vertex.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DaeCharacter::
|
||||||
|
influence_vertex(int index, EggVertex *vertex) {
|
||||||
|
const FCDSkinControllerVertex *influence = _skin_controller->GetVertexInfluence(index);
|
||||||
|
|
||||||
|
for (size_t pa = 0; pa < influence->GetPairCount(); ++pa) {
|
||||||
|
const FCDJointWeightPair* jwpair = influence->GetPair(pa);
|
||||||
|
|
||||||
|
if (jwpair->jointIndex >= 0 && jwpair->jointIndex < _joints.size()) {
|
||||||
|
EggGroup *joint = _joints[jwpair->jointIndex]._group.p();
|
||||||
|
if (joint != NULL) {
|
||||||
|
joint->ref_vertex(vertex, jwpair->weight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
daeegg_cat.error()
|
||||||
|
<< "Invalid joint index: " << jwpair->jointIndex << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DaeCharacter::collect_keys
|
||||||
|
// Access: Public
|
||||||
|
// Description: Collects all animation keys of animations applied
|
||||||
|
// to this character.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DaeCharacter::
|
||||||
|
collect_keys(pset<float> &keys) {
|
||||||
|
#if FCOLLADA_VERSION < 0x00030005
|
||||||
|
FCDSceneNodeList roots = _instance->FindSkeletonNodes();
|
||||||
|
#else
|
||||||
|
FCDSceneNodeList roots;
|
||||||
|
_instance->FindSkeletonNodes(roots);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
||||||
|
r_collect_keys(*it, keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DaeCharacter::r_collect_keys
|
||||||
|
// Access: Public
|
||||||
|
// Description: Collects all animation keys found for the given
|
||||||
|
// node tree.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void DaeCharacter::
|
||||||
|
r_collect_keys(FCDSceneNode* node, pset<float> &keys) {
|
||||||
|
FCDAnimatedList animateds;
|
||||||
|
|
||||||
|
// Collect all the animation curves
|
||||||
|
for (size_t t = 0; t < node->GetTransformCount(); ++t) {
|
||||||
|
FCDTransform *transform = node->GetTransform(t);
|
||||||
|
FCDAnimated *animated = transform->GetAnimated();
|
||||||
|
|
||||||
|
if (animated != NULL) {
|
||||||
|
const FCDAnimationCurveListList &all_curves = animated->GetCurves();
|
||||||
|
|
||||||
|
for (size_t ci = 0; ci < all_curves.size(); ++ci) {
|
||||||
|
const FCDAnimationCurveTrackList &curves = all_curves[ci];
|
||||||
|
if (curves.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_keys = curves.front()->GetKeyCount();
|
||||||
|
const FCDAnimationKey **curve_keys = curves.front()->GetKeys();
|
||||||
|
|
||||||
|
for (size_t c = 0; c < num_keys; ++c) {
|
||||||
|
keys.insert(curve_keys[c]->input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: DaeCharacter::build_table
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Processes a joint node and its transforms.
|
// Description: Processes a joint node and its transforms.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DaeCharacter::
|
void DaeCharacter::
|
||||||
process_joint(PT(EggTable) parent, FCDSceneNode* node) {
|
build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &keys) {
|
||||||
nassertv(node != NULL);
|
nassertv(node != NULL);
|
||||||
string node_id = FROM_FSTRING(node->GetDaeId());
|
|
||||||
PT(EggTable) joint = new EggTable(node_id);
|
if (!node->IsJoint()) {
|
||||||
joint->set_table_type(EggTable::TT_table);
|
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||||
parent->add_child(joint);
|
build_table(parent, node->GetChild(ch), keys);
|
||||||
PT(EggXfmSAnim) xform = new EggXfmSAnim("xform");
|
}
|
||||||
joint->add_child(xform);
|
return;
|
||||||
xform->set_fps(_frame_rate);
|
|
||||||
// Generate the sampled animation and loop through the matrices
|
|
||||||
FCDSceneNodeTools::GenerateSampledAnimation(node);
|
|
||||||
FMMatrix44List matrices = FCDSceneNodeTools::GetSampledAnimationMatrices();
|
|
||||||
for (FMMatrix44List::const_iterator it = matrices.begin(); it != matrices.end(); ++it) {
|
|
||||||
LMatrix4d matr = DAEToEggConverter::convert_matrix(*it);
|
|
||||||
assert(xform->add_data(matr));
|
|
||||||
}
|
}
|
||||||
// Loop through the children joints
|
|
||||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
string node_id = FROM_FSTRING(node->GetDaeId());
|
||||||
if (node->GetChild(ch)->IsJoint()) {
|
PT(EggTable) table = new EggTable(node_id);
|
||||||
process_joint(joint, node->GetChild(ch));
|
table->set_table_type(EggTable::TT_table);
|
||||||
|
parent->add_child(table);
|
||||||
|
|
||||||
|
PT(EggXfmSAnim) xform = new EggXfmSAnim("xform");
|
||||||
|
table->add_child(xform);
|
||||||
|
|
||||||
|
// Generate the sampled animation and loop through the matrices
|
||||||
|
FCDAnimatedList animateds;
|
||||||
|
|
||||||
|
// Collect all the animation curves
|
||||||
|
for (size_t t = 0; t < node->GetTransformCount(); ++t) {
|
||||||
|
FCDTransform *transform = node->GetTransform(t);
|
||||||
|
FCDAnimated *animated = transform->GetAnimated();
|
||||||
|
if (animated != (FCDAnimated *)NULL) {
|
||||||
|
if (animated->HasCurve()) {
|
||||||
|
animateds.push_back(animated);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sample the scene node transform
|
||||||
|
float last_key;
|
||||||
|
float timing_total = 0;
|
||||||
|
pset<float>::const_iterator ki;
|
||||||
|
for (ki = keys.begin(); ki != keys.end(); ++ki) {
|
||||||
|
for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it) {
|
||||||
|
// Sample each animated, which changes the transform values directly
|
||||||
|
(*it)->Evaluate(*ki);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ki != keys.begin()) {
|
||||||
|
timing_total += (*ki - last_key);
|
||||||
|
}
|
||||||
|
last_key = *ki;
|
||||||
|
|
||||||
|
// Retrieve the new transform matrix for the COLLADA scene node
|
||||||
|
FMMatrix44 fmat = node->ToMatrix();
|
||||||
|
|
||||||
|
// Work around issue in buggy exporters (like ColladaMax)
|
||||||
|
if (IS_NEARLY_ZERO(fmat[3][3])) {
|
||||||
|
fmat[3][3] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xform->add_data(DAEToEggConverter::convert_matrix(fmat));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quantize the FPS, otherwise Panda complains about FPS mismatches.
|
||||||
|
float fps = round(((keys.size() - 1) / timing_total) * 100) * 0.01f;
|
||||||
|
xform->set_fps(fps);
|
||||||
|
|
||||||
|
// Loop through the children joints
|
||||||
|
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||||
|
//if (node->GetChild(ch)->IsJoint()) {
|
||||||
|
build_table(table, node->GetChild(ch), keys);
|
||||||
|
//}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,20 +12,22 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef DAECHARACTER_H
|
||||||
|
#define DAECHARACTER_H
|
||||||
|
|
||||||
#include "pandatoolbase.h"
|
#include "pandatoolbase.h"
|
||||||
#include "typedReferenceCount.h"
|
#include "typedReferenceCount.h"
|
||||||
#include "typeHandle.h"
|
#include "typeHandle.h"
|
||||||
#include "eggTable.h"
|
#include "eggTable.h"
|
||||||
#include "daeToEggConverter.h"
|
|
||||||
|
|
||||||
#include "pre_fcollada_include.h"
|
#include "pre_fcollada_include.h"
|
||||||
#include "FCollada.h"
|
#include "FCollada.h"
|
||||||
#include "FCDocument/FCDSceneNode.h"
|
#include "FCDocument/FCDSceneNode.h"
|
||||||
#include "FCDocument/FCDControllerInstance.h"
|
#include "FCDocument/FCDControllerInstance.h"
|
||||||
#include "FCDocument/FCDSkinController.h"
|
#include "FCDocument/FCDSkinController.h"
|
||||||
|
#include "FCDocument/FCDGeometryMesh.h"
|
||||||
|
|
||||||
#ifndef DAECHARACTER_H
|
class DAEToEggConverter;
|
||||||
#define DAECHARACTER_H
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : DaeCharacter
|
// Class : DaeCharacter
|
||||||
@ -33,16 +35,45 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class DaeCharacter : public TypedReferenceCount {
|
class DaeCharacter : public TypedReferenceCount {
|
||||||
public:
|
public:
|
||||||
DaeCharacter(const string name, const FCDControllerInstance* controller_instance);
|
DaeCharacter(EggGroup *node_group, const FCDControllerInstance* controller_instance);
|
||||||
PT(EggTable) as_egg_bundle();
|
|
||||||
void process_joint(PT(EggTable) parent, FCDSceneNode* node);
|
struct Joint {
|
||||||
|
INLINE Joint(EggGroup *group, const FCDSceneNode *scene_node) :
|
||||||
|
_group(group),
|
||||||
|
_scene_node(scene_node),
|
||||||
|
_character(NULL),
|
||||||
|
_bind_pose(LMatrix4d::ident_mat()) {}
|
||||||
|
|
||||||
|
LMatrix4d _bind_pose;
|
||||||
|
const PT(EggGroup) _group;
|
||||||
|
const FCDSceneNode *_scene_node;
|
||||||
|
DaeCharacter *_character;
|
||||||
|
};
|
||||||
|
typedef pvector<Joint> Joints;
|
||||||
|
typedef pmap<string, Joint> JointMap;
|
||||||
|
|
||||||
|
void bind_joints(JointMap &joint_map);
|
||||||
|
void adjust_joints(FCDSceneNode *node, const JointMap &joint_map,
|
||||||
|
const LMatrix4d &transform = LMatrix4d::ident_mat());
|
||||||
|
|
||||||
|
void influence_vertex(int index, EggVertex *vertex);
|
||||||
|
|
||||||
|
void collect_keys(pset<float> &keys);
|
||||||
|
void r_collect_keys(FCDSceneNode *node, pset<float> &keys);
|
||||||
|
|
||||||
|
void build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &keys);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PT(EggGroup) _node_group;
|
||||||
|
const FCDGeometryMesh *_skin_mesh;
|
||||||
|
const FCDControllerInstance *_instance;
|
||||||
|
LMatrix4d _bind_shape_mat;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _frame_rate;
|
|
||||||
string _name;
|
string _name;
|
||||||
FCDControllerInstance* _controller_instance;
|
const FCDSkinController *_skin_controller;
|
||||||
FCDSkinController* _skin_controller;
|
Joints _joints;
|
||||||
pmap<string, FCDSkinControllerJoint*> _controller_joints;
|
JointMap _bound_joints;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual TypeHandle get_type() const {
|
virtual TypeHandle get_type() const {
|
||||||
|
@ -204,12 +204,13 @@ process_extra(const string semantic, const FCDExtra* extra) {
|
|||||||
for (size_t et = 0; et < etype->GetTechniqueCount(); ++et) {
|
for (size_t et = 0; et < etype->GetTechniqueCount(); ++et) {
|
||||||
const FCDENode* enode = ((const FCDENode*)(etype->GetTechnique(et)))->FindChildNode("double_sided");
|
const FCDENode* enode = ((const FCDENode*)(etype->GetTechnique(et)))->FindChildNode("double_sided");
|
||||||
if (enode != NULL) {
|
if (enode != NULL) {
|
||||||
if (trim(enode->GetContent()) == "1") {
|
string content = trim(enode->GetContent());
|
||||||
|
if (content == "1" || content == "true") {
|
||||||
_materials[semantic]->_double_sided = true;
|
_materials[semantic]->_double_sided = true;
|
||||||
} else if (trim(enode->GetContent()) == "0") {
|
} else if (content == "0" || content == "false") {
|
||||||
_materials[semantic]->_double_sided = false;
|
_materials[semantic]->_double_sided = false;
|
||||||
} else {
|
} else {
|
||||||
daeegg_cat.warning() << "Expected <double_sided> tag to be either 1 or 0, found '" << enode->GetContent() << "' instead" << endl;
|
daeegg_cat.warning() << "Expected <double_sided> tag to be either 1 or 0, found '" << content << "' instead" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
DAEToEggConverter::
|
DAEToEggConverter::
|
||||||
DAEToEggConverter() {
|
DAEToEggConverter() {
|
||||||
|
_unit_name = "meter";
|
||||||
|
_unit_meters = 1.0;
|
||||||
_document = NULL;
|
_document = NULL;
|
||||||
_table = NULL;
|
_table = NULL;
|
||||||
_frame_rate = -1;
|
|
||||||
_error_handler = NULL;
|
_error_handler = NULL;
|
||||||
_invert_transparency = false;
|
_invert_transparency = false;
|
||||||
}
|
}
|
||||||
@ -131,9 +132,6 @@ convert_file(const Filename &filename) {
|
|||||||
// Reset stuff
|
// Reset stuff
|
||||||
clear_error();
|
clear_error();
|
||||||
_joints.clear();
|
_joints.clear();
|
||||||
_vertex_pools.clear();
|
|
||||||
_skeletons.clear();
|
|
||||||
_frame_rate = -1;
|
|
||||||
if (_error_handler == NULL) {
|
if (_error_handler == NULL) {
|
||||||
_error_handler = new FUErrorSimpleHandler;
|
_error_handler = new FUErrorSimpleHandler;
|
||||||
}
|
}
|
||||||
@ -156,166 +154,338 @@ convert_file(const Filename &filename) {
|
|||||||
FCDocumentTools::StandardizeUpAxisAndLength(_document);
|
FCDocumentTools::StandardizeUpAxisAndLength(_document);
|
||||||
}
|
}
|
||||||
|
|
||||||
_table = new EggTable();
|
// Process the scene
|
||||||
_table->set_table_type(EggTable::TT_table);
|
|
||||||
// Process the stuff
|
|
||||||
process_asset();
|
process_asset();
|
||||||
preprocess();
|
PT(EggGroup) scene_group;
|
||||||
|
string model_name = _character_name;
|
||||||
|
|
||||||
FCDSceneNode* visual_scene = _document->GetVisualSceneInstance();
|
FCDSceneNode* visual_scene = _document->GetVisualSceneInstance();
|
||||||
if (visual_scene != NULL) {
|
if (visual_scene != NULL) {
|
||||||
// First check for an <extra> tag
|
if (model_name.empty()) {
|
||||||
const FCDExtra* extra = visual_scene->GetExtra();
|
// By lack of anything better...
|
||||||
//FIXME: eek this looks horrid
|
model_name = FROM_FSTRING(visual_scene->GetName());
|
||||||
if (extra != NULL) {
|
}
|
||||||
const FCDEType* etype = extra->GetDefaultType();
|
scene_group = new EggGroup(model_name);
|
||||||
if (etype != NULL) {
|
_egg_data->add_child(scene_group);
|
||||||
const FCDENode* enode = (const FCDENode*) etype->FindTechnique("MAX3D");
|
|
||||||
if (enode != NULL) {
|
|
||||||
enode = enode->FindChildNode("frame_rate");
|
|
||||||
if (enode != NULL && !string_to_int(enode->GetContent(), _frame_rate)) {
|
|
||||||
daeegg_cat.warning() << "Invalid integer in <frame_rate> tag: '" << enode->GetContent() << "'" << endl;
|
|
||||||
} } } }
|
|
||||||
// Now loop through the children
|
|
||||||
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
|
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
|
||||||
process_node(DCAST(EggGroupNode, _egg_data), visual_scene->GetChild(ch));
|
process_node(scene_group, visual_scene->GetChild(ch));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
daeegg_cat.warning()
|
||||||
|
<< "No visual scene instance found in COLLADA document.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process the characters. This depends on information from collected
|
||||||
|
// joints, which is why it's done in a second step.
|
||||||
|
if (get_animation_convert() != AC_none) {
|
||||||
|
Characters::iterator it;
|
||||||
|
DaeCharacter *character;
|
||||||
|
for (it = _characters.begin(); it != _characters.end(); ++it) {
|
||||||
|
character = *it;
|
||||||
|
if (get_animation_convert() != AC_chan) {
|
||||||
|
character->bind_joints(_joints);
|
||||||
|
|
||||||
|
const FCDGeometryMesh *mesh = character->_skin_mesh;
|
||||||
|
|
||||||
|
if (mesh != NULL) {
|
||||||
|
PT(DaeMaterials) materials = new DaeMaterials(character->_instance);
|
||||||
|
daeegg_cat.spam() << "Processing mesh for controller\n";
|
||||||
|
process_mesh(character->_node_group, mesh, materials, character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the joints in bind pose.
|
||||||
|
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
|
||||||
|
character->adjust_joints(visual_scene->GetChild(ch), _joints, LMatrix4d::ident_mat());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scene_group != NULL) {
|
||||||
|
// Mark the scene as character.
|
||||||
|
if (get_animation_convert() == AC_chan) {
|
||||||
|
_egg_data->remove_child(scene_group);
|
||||||
|
} else {
|
||||||
|
scene_group->set_dart_type(EggGroup::DT_default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_animation_convert() != AC_model) {
|
||||||
|
_table = new EggTable();
|
||||||
|
_table->set_table_type(EggTable::TT_table);
|
||||||
|
_egg_data->add_child(_table);
|
||||||
|
|
||||||
|
PT(EggTable) bundle = new EggTable(model_name);
|
||||||
|
bundle->set_table_type(EggTable::TT_bundle);
|
||||||
|
_table->add_child(bundle);
|
||||||
|
|
||||||
|
PT(EggTable) skeleton = new EggTable("<skeleton>");
|
||||||
|
skeleton->set_table_type(EggTable::TT_table);
|
||||||
|
bundle->add_child(skeleton);
|
||||||
|
|
||||||
|
pset<float> keys;
|
||||||
|
|
||||||
|
Characters::iterator it;
|
||||||
|
DaeCharacter *character;
|
||||||
|
for (it = _characters.begin(); it != _characters.end(); ++it) {
|
||||||
|
DaeCharacter *character = *it;
|
||||||
|
|
||||||
|
// Collect key frame timings.
|
||||||
|
if (get_animation_convert() == AC_both ||
|
||||||
|
get_animation_convert() == AC_chan) {
|
||||||
|
character->collect_keys(keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_frame_inc != 0.0) {
|
||||||
|
// A frame increment was given, this means that we have to sample the
|
||||||
|
// animation.
|
||||||
|
float start, end;
|
||||||
|
if (_end_frame != _start_frame) {
|
||||||
|
start = _start_frame;
|
||||||
|
end = _end_frame;
|
||||||
|
} else {
|
||||||
|
// No range was given. Infer the frame range from the keys.
|
||||||
|
start = *keys.begin();
|
||||||
|
end = *keys.rbegin();
|
||||||
|
}
|
||||||
|
keys.clear();
|
||||||
|
|
||||||
|
for (float t = start; t <= end; t += _frame_inc) {
|
||||||
|
keys.insert(t);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No sampling parameters given; not necessarily a failure, since the
|
||||||
|
// animation may already be sampled. We use the key frames as animation
|
||||||
|
// frames.
|
||||||
|
if (_end_frame != 0.0) {
|
||||||
|
// An end frame was given, chop off all keys after that.
|
||||||
|
float end = _end_frame;
|
||||||
|
pset<float>::iterator ki;
|
||||||
|
for (ki = keys.begin(); ki != keys.end(); ++ki) {
|
||||||
|
if (*ki > end && !IS_THRESHOLD_EQUAL(*ki, end, 0.001)) {
|
||||||
|
keys.erase(ki, keys.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_start_frame != 0.0) {
|
||||||
|
// A start frame was given, chop off all keys before that.
|
||||||
|
float start = _start_frame;
|
||||||
|
pset<float>::iterator ki;
|
||||||
|
for (ki = keys.begin(); ki != keys.end(); ++ki) {
|
||||||
|
if (*ki > start && !IS_THRESHOLD_EQUAL(*ki, start, 0.001)) {
|
||||||
|
keys.erase(keys.begin(), ki);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that this does indeed look like a sampled animation; if not,
|
||||||
|
// issue an appropriate warning.
|
||||||
|
pset<float>::const_iterator ki = keys.begin();
|
||||||
|
if (ki != keys.end()) {
|
||||||
|
float last = *ki;
|
||||||
|
float diff = 0;
|
||||||
|
|
||||||
|
for (++ki; ki != keys.end(); ++ki) {
|
||||||
|
if (diff != 0 && !IS_THRESHOLD_EQUAL((*ki - last), diff, 0.001)) {
|
||||||
|
daeegg_cat.error()
|
||||||
|
<< "This does not appear to be a sampled animation.\n"
|
||||||
|
<< "Specify the -sf, -ef and -if options to indicate how the "
|
||||||
|
<< "animations should be sampled.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff = (*ki - last);
|
||||||
|
last = *ki;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It doesn't really matter which character we grab for this as
|
||||||
|
// it'll iterate over the whole graph right now anyway.
|
||||||
|
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
|
||||||
|
character->build_table(skeleton, visual_scene->GetChild(ch), keys);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SAFE_DELETE(visual_scene);
|
|
||||||
|
|
||||||
_egg_data->add_child(_table);
|
|
||||||
|
|
||||||
// Clean up and return
|
// Clean up and return
|
||||||
|
SAFE_DELETE(visual_scene);
|
||||||
SAFE_DELETE(_document);
|
SAFE_DELETE(_document);
|
||||||
FCollada::Release();
|
FCollada::Release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_asset() {
|
////////////////////////////////////////////////////////////////////
|
||||||
if (_document->GetAsset() == NULL) return;
|
// Function: DAEToEggConverter::get_input_units
|
||||||
|
// Access: Public, Virtual
|
||||||
|
// Description: This may be called after convert_file() has been
|
||||||
|
// called and returned true, indicating a successful
|
||||||
|
// conversion. It will return the distance units
|
||||||
|
// represented by the converted egg file, if known, or
|
||||||
|
// DU_invalid if not known.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
DistanceUnit DAEToEggConverter::
|
||||||
|
get_input_units() {
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 0.001)) {
|
||||||
|
return DU_millimeters;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 0.01)) {
|
||||||
|
return DU_centimeters;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 1.0)) {
|
||||||
|
return DU_meters;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 1000.0)) {
|
||||||
|
return DU_kilometers;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 3.0 * 12.0 * 0.0254)) {
|
||||||
|
return DU_yards;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 12.0 * 0.0254)) {
|
||||||
|
return DU_feet;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 0.0254)) {
|
||||||
|
return DU_inches;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 1852.0)) {
|
||||||
|
return DU_nautical_miles;
|
||||||
|
}
|
||||||
|
if (IS_NEARLY_EQUAL(_unit_meters, 5280.0 * 12.0 * 0.0254)) {
|
||||||
|
return DU_statute_miles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whatever.
|
||||||
|
return DU_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DAEToEggConverter::
|
||||||
|
process_asset() {
|
||||||
|
const FCDAsset *asset = _document->GetAsset();
|
||||||
|
if (_document->GetAsset() == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_unit_name = FROM_FSTRING(asset->GetUnitName());
|
||||||
|
_unit_meters = asset->GetUnitConversionFactor();
|
||||||
|
|
||||||
// Read out the coordinate system
|
// Read out the coordinate system
|
||||||
FMVector3 up_axis (_document->GetAsset()->GetUpAxis());
|
FMVector3 up_axis = asset->GetUpAxis();
|
||||||
|
|
||||||
if (up_axis == FMVector3(0, 1, 0)) {
|
if (up_axis == FMVector3(0, 1, 0)) {
|
||||||
_egg_data->set_coordinate_system(CS_yup_right);
|
_egg_data->set_coordinate_system(CS_yup_right);
|
||||||
|
|
||||||
} else if (up_axis == FMVector3(0, 0, 1)) {
|
} else if (up_axis == FMVector3(0, 0, 1)) {
|
||||||
_egg_data->set_coordinate_system(CS_zup_right);
|
_egg_data->set_coordinate_system(CS_zup_right);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_egg_data->set_coordinate_system(CS_invalid);
|
_egg_data->set_coordinate_system(CS_invalid);
|
||||||
daeegg_cat.warning() << "Unrecognized coordinate system!\n";
|
daeegg_cat.warning() << "Unrecognized coordinate system!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function lists all the joints and referenced skeletons
|
|
||||||
void DAEToEggConverter::preprocess(const FCDSceneNode* node) {
|
|
||||||
// If the node is NULL, take the visual scene instance.
|
|
||||||
if (node == NULL) {
|
|
||||||
assert(_document != NULL);
|
|
||||||
_skeletons.clear();
|
|
||||||
_joints.clear();
|
|
||||||
node = _document->GetVisualSceneInstance();
|
|
||||||
}
|
|
||||||
if (node == NULL) return;
|
|
||||||
if (node->IsJoint()) {
|
|
||||||
_joints[FROM_FSTRING(node->GetDaeId())] = NULL;
|
|
||||||
}
|
|
||||||
// Loop through the instances first.
|
|
||||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
|
||||||
if (node->GetInstance(in)->GetType() == FCDEntityInstance::CONTROLLER) {
|
|
||||||
// Loop through the skeleton roots now.
|
|
||||||
#if FCOLLADA_VERSION < 0x00030005
|
|
||||||
FCDSceneNodeList roots = ((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes();
|
|
||||||
#else
|
|
||||||
FCDSceneNodeList roots;
|
|
||||||
((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes(roots);
|
|
||||||
#endif
|
|
||||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
|
||||||
daeegg_cat.spam() << "Found referenced skeleton root " << FROM_FSTRING((*it)->GetDaeId()) << endl;
|
|
||||||
_skeletons.push_back(FROM_FSTRING((*it)->GetDaeId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Now loop through the children and recurse.
|
|
||||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
|
||||||
preprocess(node->GetChild(ch));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the node. If forced is true, it will even process it if its known to be a skeleton root.
|
// Process the node. If forced is true, it will even process it if its known to be a skeleton root.
|
||||||
void DAEToEggConverter::process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced) {
|
void DAEToEggConverter::
|
||||||
|
process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced) {
|
||||||
nassertv(node != NULL);
|
nassertv(node != NULL);
|
||||||
string node_id = FROM_FSTRING(node->GetDaeId());
|
string node_id = FROM_FSTRING(node->GetDaeId());
|
||||||
daeegg_cat.spam() << "Processing node with ID '" << node_id << "'" << endl;
|
daeegg_cat.spam() << "Processing node with ID '" << node_id << "'" << endl;
|
||||||
// Important! If it's known to be a skeleton root, ignore it for now, unless we're processing forced.
|
|
||||||
if (!forced && count(_skeletons.begin(), _skeletons.end(), node_id) > 0) {
|
|
||||||
daeegg_cat.spam() << "Ignoring skeleton root node with ID '" << node_id << "', we'll process it later" << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Create an egg group for this node
|
// Create an egg group for this node
|
||||||
PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetName()));
|
PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetDaeId()));
|
||||||
process_extra(node_group, node->GetExtra());
|
process_extra(node_group, node->GetExtra());
|
||||||
parent->add_child(node_group);
|
parent->add_child(node_group);
|
||||||
|
|
||||||
// Check if its a joint
|
// Check if its a joint
|
||||||
if (node->IsJoint()) {
|
if (node->IsJoint()) {
|
||||||
|
string sid = FROM_FSTRING(node->GetSubId());
|
||||||
node_group->set_group_type(EggGroup::GT_joint);
|
node_group->set_group_type(EggGroup::GT_joint);
|
||||||
_joints[node_id] = node_group;
|
|
||||||
|
if (!_joints.insert(DaeCharacter::JointMap::value_type(sid,
|
||||||
|
DaeCharacter::Joint(node_group, node))).second) {
|
||||||
|
daeegg_cat.error()
|
||||||
|
<< "Joint with sid " << sid << " occurs more than once!\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Loop through the transforms and apply them
|
|
||||||
for (size_t tr = 0; tr < node->GetTransformCount(); ++tr) {
|
// Loop through the transforms and apply them (in reverse order)
|
||||||
apply_transform(node_group, node->GetTransform(tr));
|
for (size_t tr = node->GetTransformCount(); tr > 0; --tr) {
|
||||||
|
apply_transform(node_group, node->GetTransform(tr - 1));
|
||||||
}
|
}
|
||||||
|
//node_group->set_transform3d(convert_matrix(node->ToMatrix()));
|
||||||
|
|
||||||
// Loop through the instances and process them
|
// Loop through the instances and process them
|
||||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
||||||
process_instance(node_group, node->GetInstance(in));
|
process_instance(node_group, node->GetInstance(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through the children and recursively process them
|
// Loop through the children and recursively process them
|
||||||
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
|
||||||
process_node(DCAST(EggGroupNode, node_group), node->GetChild(ch));
|
process_node(DCAST(EggGroupNode, node_group), node->GetChild(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through any possible scene node instances and process those, too.
|
// Loop through any possible scene node instances and process those, too.
|
||||||
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
|
||||||
if (node->GetInstance(in)->GetEntity() && node->GetInstance(in)->GetEntity()->GetType() == FCDEntity::SCENE_NODE) {
|
const FCDEntity *entity = node->GetInstance(in)->GetEntity();
|
||||||
process_node(DCAST(EggGroupNode, node_group), (const FCDSceneNode*) node->GetInstance(in)->GetEntity());
|
if (entity && entity->GetType() == FCDEntity::SCENE_NODE) {
|
||||||
|
process_node(node_group, (const FCDSceneNode*) entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance) {
|
void DAEToEggConverter::
|
||||||
|
process_instance(EggGroup *parent, const FCDEntityInstance* instance) {
|
||||||
nassertv(instance != NULL);
|
nassertv(instance != NULL);
|
||||||
nassertv(instance->GetEntity() != NULL);
|
nassertv(instance->GetEntity() != NULL);
|
||||||
// Check what kind of instance this is
|
// Check what kind of instance this is
|
||||||
switch (instance->GetType()) {
|
switch (instance->GetType()) {
|
||||||
case FCDEntityInstance::GEOMETRY: {
|
case FCDEntityInstance::GEOMETRY:
|
||||||
const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity();
|
{
|
||||||
assert(geometry != NULL);
|
if (get_animation_convert() != AC_chan) {
|
||||||
if (geometry->IsMesh()) {
|
const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity();
|
||||||
// Now, handle the mesh.
|
assert(geometry != NULL);
|
||||||
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
|
if (geometry->IsMesh()) {
|
||||||
|
// Now, handle the mesh.
|
||||||
|
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
|
||||||
|
}
|
||||||
|
if (geometry->IsSpline()) {
|
||||||
|
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (geometry->IsSpline()) {
|
}
|
||||||
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
|
break;
|
||||||
}
|
|
||||||
break; }
|
case FCDEntityInstance::CONTROLLER:
|
||||||
case FCDEntityInstance::CONTROLLER: {
|
// Add the dart tag and process the controller instance
|
||||||
// Add the dart tag and process the controller instance
|
//parent->set_dart_type(EggGroup::DT_default);
|
||||||
parent->set_dart_type(EggGroup::DT_default);
|
process_controller(parent, (const FCDControllerInstance*) instance);
|
||||||
process_controller(parent, (const FCDControllerInstance*) instance);
|
break;
|
||||||
break; }
|
|
||||||
case FCDEntityInstance::MATERIAL:
|
case FCDEntityInstance::MATERIAL:
|
||||||
// We don't process this directly, handled per-geometry instead.
|
// We don't process this directly, handled per-geometry instead.
|
||||||
break;
|
break;
|
||||||
case FCDEntityInstance::SIMPLE: {
|
|
||||||
// Grab the entity and check it's type.
|
case FCDEntityInstance::SIMPLE:
|
||||||
|
{
|
||||||
|
// Grab the entity and check its type.
|
||||||
const FCDEntity* entity = instance->GetEntity();
|
const FCDEntity* entity = instance->GetEntity();
|
||||||
if (entity->GetType() != FCDEntity::SCENE_NODE) {
|
if (entity->GetType() != FCDEntity::SCENE_NODE) {
|
||||||
daeegg_cat.warning() << "Unsupported entity type found" << endl;
|
daeegg_cat.warning() << "Unsupported entity type found" << endl;
|
||||||
}
|
}
|
||||||
break; }
|
}
|
||||||
default:
|
break;
|
||||||
daeegg_cat.warning() << "Unsupported instance type found" << endl;
|
|
||||||
|
default:
|
||||||
|
daeegg_cat.warning() << "Unsupported instance type found" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes the given mesh.
|
// Processes the given mesh.
|
||||||
void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials) {
|
void DAEToEggConverter::
|
||||||
|
process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh,
|
||||||
|
DaeMaterials *materials, DaeCharacter *character) {
|
||||||
|
|
||||||
nassertv(mesh != NULL);
|
nassertv(mesh != NULL);
|
||||||
daeegg_cat.debug() << "Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl;
|
daeegg_cat.debug() << "Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl;
|
||||||
|
|
||||||
@ -324,7 +494,6 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
parent->add_child(mesh_group);
|
parent->add_child(mesh_group);
|
||||||
PT(EggVertexPool) mesh_pool = new EggVertexPool(FROM_FSTRING(mesh->GetDaeId()));
|
PT(EggVertexPool) mesh_pool = new EggVertexPool(FROM_FSTRING(mesh->GetDaeId()));
|
||||||
mesh_group->add_child(mesh_pool);
|
mesh_group->add_child(mesh_pool);
|
||||||
_vertex_pools[FROM_FSTRING(mesh->GetDaeId())] = mesh_pool;
|
|
||||||
|
|
||||||
// First retrieve the vertex source
|
// First retrieve the vertex source
|
||||||
if (mesh->GetSourceCount() == 0) {
|
if (mesh->GetSourceCount() == 0) {
|
||||||
@ -345,11 +514,14 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
PT(EggGroup) *primitive_holders = new PT(EggGroup) [mesh->GetPolygonsCount()];
|
PT(EggGroup) *primitive_holders = new PT(EggGroup) [mesh->GetPolygonsCount()];
|
||||||
for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
|
for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
|
||||||
const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
|
const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
|
||||||
|
string material_semantic = FROM_FSTRING(polygons->GetMaterialSemantic());
|
||||||
|
|
||||||
// Stores which group holds the primitives.
|
// Stores which group holds the primitives.
|
||||||
PT(EggGroup) primitiveholder;
|
PT(EggGroup) primitiveholder;
|
||||||
// If we have materials, make a group for each material. Then, apply the material's per-group stuff.
|
// If we have materials, make a group for each material. Then, apply the material's per-group stuff.
|
||||||
if (materials != NULL && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) {
|
if (materials != NULL && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) {
|
||||||
primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + FROM_FSTRING(polygons->GetMaterialSemantic()));
|
//primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + material_semantic);
|
||||||
|
primitiveholder = new EggGroup;
|
||||||
mesh_group->add_child(primitiveholder);
|
mesh_group->add_child(primitiveholder);
|
||||||
} else {
|
} else {
|
||||||
primitiveholder = mesh_group;
|
primitiveholder = mesh_group;
|
||||||
@ -357,7 +529,7 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
primitive_holders[gr] = primitiveholder;
|
primitive_holders[gr] = primitiveholder;
|
||||||
// Apply the per-group data of the materials, if we have it.
|
// Apply the per-group data of the materials, if we have it.
|
||||||
if (materials != NULL) {
|
if (materials != NULL) {
|
||||||
materials->apply_to_group(FROM_FSTRING(polygons->GetMaterialSemantic()), primitiveholder, _invert_transparency);
|
materials->apply_to_group(material_semantic, primitiveholder, _invert_transparency);
|
||||||
}
|
}
|
||||||
// Find the position sources
|
// Find the position sources
|
||||||
const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION);
|
const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION);
|
||||||
@ -389,26 +561,47 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
const uint32* tindices;
|
const uint32* tindices;
|
||||||
if (tinput != NULL) tindices = tinput->GetIndices();
|
if (tinput != NULL) tindices = tinput->GetIndices();
|
||||||
// Get a name for potential coordinate sets
|
// Get a name for potential coordinate sets
|
||||||
string tcsetname ("");
|
string tcsetname;
|
||||||
if (materials != NULL && tcinput != NULL) {
|
if (materials != NULL && tcinput != NULL) {
|
||||||
daeegg_cat.debug() << "Assigning texcoord set " << tcinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
|
if (daeegg_cat.is_debug()) {
|
||||||
tcsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXCOORD, tcinput->GetSet());
|
daeegg_cat.debug()
|
||||||
|
<< "Assigning texcoord set " << tcinput->GetSet()
|
||||||
|
<< " to semantic '" << material_semantic << "'\n";
|
||||||
|
}
|
||||||
|
tcsetname = materials->get_uvset_name(material_semantic,
|
||||||
|
FUDaeGeometryInput::TEXCOORD, tcinput->GetSet());
|
||||||
}
|
}
|
||||||
string tbsetname ("");
|
string tbsetname;
|
||||||
if (materials != NULL && binput != NULL) {
|
if (materials != NULL && binput != NULL) {
|
||||||
daeegg_cat.debug() << "Assigning texbinormal set " << binput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
|
if (daeegg_cat.is_debug()) {
|
||||||
tbsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXBINORMAL, binput->GetSet());
|
daeegg_cat.debug()
|
||||||
|
<< "Assigning texbinormal set " << binput->GetSet()
|
||||||
|
<< " to semantic '" << material_semantic << "'\n";
|
||||||
|
}
|
||||||
|
tbsetname = materials->get_uvset_name(material_semantic,
|
||||||
|
FUDaeGeometryInput::TEXBINORMAL, binput->GetSet());
|
||||||
}
|
}
|
||||||
string ttsetname ("");
|
string ttsetname;
|
||||||
if (materials != NULL && tinput != NULL) {
|
if (materials != NULL && tinput != NULL) {
|
||||||
daeegg_cat.debug() << "Assigning textangent set " << tinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
|
if (daeegg_cat.is_debug()) {
|
||||||
ttsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXTANGENT, tinput->GetSet());
|
daeegg_cat.debug()
|
||||||
|
<< "Assigning textangent set " << tinput->GetSet()
|
||||||
|
<< " to semantic '" << material_semantic << "'\n";
|
||||||
|
}
|
||||||
|
ttsetname = materials->get_uvset_name(material_semantic,
|
||||||
|
FUDaeGeometryInput::TEXTANGENT, tinput->GetSet());
|
||||||
}
|
}
|
||||||
// Loop through the indices and add the vertices.
|
// Loop through the indices and add the vertices.
|
||||||
for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) {
|
for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) {
|
||||||
PT_EggVertex vertex = mesh_pool->make_new_vertex();
|
PT_EggVertex vertex = mesh_pool->make_new_vertex();
|
||||||
const float* data = &vsource->GetData()[indices[ix]*3];
|
const float* data = &vsource->GetData()[indices[ix]*3];
|
||||||
vertex->set_pos(LPoint3d(data[0], data[1], data[2]));
|
vertex->set_pos(LPoint3d(data[0], data[1], data[2]));
|
||||||
|
|
||||||
|
if (character != NULL) {
|
||||||
|
// If this is skinned geometry, add the vertex influences.
|
||||||
|
character->influence_vertex(indices[ix], vertex);
|
||||||
|
}
|
||||||
|
|
||||||
// Process the normal
|
// Process the normal
|
||||||
if (nsource != NULL && ninput != NULL) {
|
if (nsource != NULL && ninput != NULL) {
|
||||||
assert(nsource->GetStride() == 3);
|
assert(nsource->GetStride() == 3);
|
||||||
@ -469,26 +662,26 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
PT(EggPrimitive) primitive = NULL;
|
PT(EggPrimitive) primitive = NULL;
|
||||||
// Create a primitive that matches the fcollada type
|
// Create a primitive that matches the fcollada type
|
||||||
switch (polygons->GetPrimitiveType()) {
|
switch (polygons->GetPrimitiveType()) {
|
||||||
case FCDGeometryPolygons::LINES:
|
case FCDGeometryPolygons::LINES:
|
||||||
primitive = new EggLine();
|
primitive = new EggLine();
|
||||||
break;
|
break;
|
||||||
case FCDGeometryPolygons::POLYGONS:
|
case FCDGeometryPolygons::POLYGONS:
|
||||||
primitive = new EggPolygon();
|
primitive = new EggPolygon();
|
||||||
break;
|
break;
|
||||||
case FCDGeometryPolygons::TRIANGLE_FANS:
|
case FCDGeometryPolygons::TRIANGLE_FANS:
|
||||||
primitive = new EggTriangleFan();
|
primitive = new EggTriangleFan();
|
||||||
break;
|
break;
|
||||||
case FCDGeometryPolygons::TRIANGLE_STRIPS:
|
case FCDGeometryPolygons::TRIANGLE_STRIPS:
|
||||||
primitive = new EggTriangleStrip();
|
primitive = new EggTriangleStrip();
|
||||||
break;
|
break;
|
||||||
case FCDGeometryPolygons::POINTS:
|
case FCDGeometryPolygons::POINTS:
|
||||||
primitive = new EggPoint();
|
primitive = new EggPoint();
|
||||||
break;
|
break;
|
||||||
case FCDGeometryPolygons::LINE_STRIPS:
|
case FCDGeometryPolygons::LINE_STRIPS:
|
||||||
daeegg_cat.warning() << "Linestrips not yet supported!" << endl;
|
daeegg_cat.warning() << "Linestrips not yet supported!" << endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
daeegg_cat.warning() << "Unsupported primitive type found!" << endl;
|
daeegg_cat.warning() << "Unsupported primitive type found!" << endl;
|
||||||
}
|
}
|
||||||
if (primitive != NULL) {
|
if (primitive != NULL) {
|
||||||
primitive_holders[gr]->add_child(primitive);
|
primitive_holders[gr]->add_child(primitive);
|
||||||
@ -506,7 +699,8 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
|
|||||||
delete[] primitive_holders;
|
delete[] primitive_holders;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline) {
|
void DAEToEggConverter::
|
||||||
|
process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline) {
|
||||||
assert(geometry_spline != NULL);
|
assert(geometry_spline != NULL);
|
||||||
PT(EggGroup) result = new EggGroup(group_name);
|
PT(EggGroup) result = new EggGroup(group_name);
|
||||||
parent->add_child(result);
|
parent->add_child(result);
|
||||||
@ -521,7 +715,8 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spline) {
|
void DAEToEggConverter::
|
||||||
|
process_spline(EggGroup *parent, const FCDSpline* spline) {
|
||||||
assert(spline != NULL);
|
assert(spline != NULL);
|
||||||
nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS);
|
nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS);
|
||||||
// Now load in the nurbs curve to the egg library
|
// Now load in the nurbs curve to the egg library
|
||||||
@ -542,70 +737,26 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance) {
|
void DAEToEggConverter::
|
||||||
|
process_controller(EggGroup *parent, const FCDControllerInstance *instance) {
|
||||||
assert(instance != NULL);
|
assert(instance != NULL);
|
||||||
const FCDController* controller = (const FCDController*) instance->GetEntity();
|
const FCDController* controller = (const FCDController *)instance->GetEntity();
|
||||||
assert(controller != NULL);
|
assert(controller != NULL);
|
||||||
PT(EggVertexPool) vertex_pool = NULL;
|
|
||||||
// Add the skin geometry
|
if (get_animation_convert() == AC_none) {
|
||||||
const FCDGeometry* geometry = controller->GetBaseGeometry();
|
// If we're exporting a static mesh, export the base geometry as-is.
|
||||||
if (geometry != NULL) {
|
const FCDGeometryMesh *mesh = controller->GetBaseGeometry()->GetMesh();
|
||||||
if (geometry->IsMesh()) {
|
if (mesh != NULL) {
|
||||||
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
|
PT(DaeMaterials) materials = new DaeMaterials(instance);
|
||||||
daeegg_cat.spam() << "Processing mesh for controller\n";
|
daeegg_cat.spam() << "Processing mesh for controller\n";
|
||||||
if (_vertex_pools.count(FROM_FSTRING(geometry->GetMesh()->GetDaeId()))) {
|
process_mesh(parent, mesh, materials);
|
||||||
daeegg_cat.debug() << "Using vertex pool " << FROM_FSTRING(geometry->GetMesh()->GetDaeId()) << "\n";
|
|
||||||
vertex_pool = _vertex_pools[FROM_FSTRING(geometry->GetMesh()->GetDaeId())];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (geometry->IsSpline()) {
|
|
||||||
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add the joint hierarchy
|
|
||||||
#if FCOLLADA_VERSION < 0x00030005
|
|
||||||
FCDSceneNodeList roots = (const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes();
|
|
||||||
#else
|
|
||||||
FCDSceneNodeList roots;
|
|
||||||
(const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes(roots);
|
|
||||||
#endif
|
|
||||||
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
|
|
||||||
process_node(DCAST(EggGroupNode, parent), *it, true);
|
|
||||||
}
|
|
||||||
if (controller->IsSkin()) {
|
|
||||||
// Load in the vertex influences first
|
|
||||||
pmap<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > > influences;
|
|
||||||
if (vertex_pool) {
|
|
||||||
for (size_t in = 0; in < controller->GetSkinController()->GetInfluenceCount(); ++in) {
|
|
||||||
assert(vertex_pool->has_vertex(in));
|
|
||||||
for (size_t pa = 0; pa < controller->GetSkinController()->GetVertexInfluence(in)->GetPairCount(); ++pa) {
|
|
||||||
const FCDJointWeightPair* jwpair = controller->GetSkinController()->GetVertexInfluence(in)->GetPair(pa);
|
|
||||||
influences[jwpair->jointIndex].push_back(pair<PT_EggVertex, PN_stdfloat> (vertex_pool->get_vertex(in), jwpair->weight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Loop through the joints in the vertex influences
|
|
||||||
for (pmap<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > >::iterator it = influences.begin(); it != influences.end(); ++it) {
|
|
||||||
if (it->first == -1) {
|
|
||||||
daeegg_cat.warning() << "Ignoring vertex influence with negative joint index\n";
|
|
||||||
//FIXME: Why are there joints with index -1
|
|
||||||
} else {
|
|
||||||
const string joint_id = FROM_FSTRING(controller->GetSkinController()->GetJoint(it->first)->GetId());
|
|
||||||
//TODO: what if the joints have just not been defined yet?
|
|
||||||
if (_joints.count(joint_id) > 0) {
|
|
||||||
if (_joints[joint_id]) {
|
|
||||||
for (pvector<pair<PT_EggVertex, PN_stdfloat> >::iterator vi = it->second.begin(); vi != it->second.end(); ++vi) {
|
|
||||||
_joints[joint_id]->ref_vertex(vi->first, vi->second);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
daeegg_cat.warning() << "Unprocessed joint being referenced: '" << joint_id << "'" << endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
daeegg_cat.warning() << "Unknown joint being referenced: '" << joint_id << "'" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Add a character for this to the table, the mesh is processed later
|
||||||
|
PT(DaeCharacter) character = new DaeCharacter(parent, instance);
|
||||||
|
_characters.push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller->IsMorph()) {
|
if (controller->IsMorph()) {
|
||||||
assert(controller != NULL);
|
assert(controller != NULL);
|
||||||
const FCDMorphController* morph_controller = controller->GetMorphController();
|
const FCDMorphController* morph_controller = controller->GetMorphController();
|
||||||
@ -628,13 +779,10 @@ void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControl
|
|||||||
morph->add_child(target);
|
morph->add_child(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a <Bundle> for the character and add it to the table
|
|
||||||
PT(DaeCharacter) character = new DaeCharacter(parent->get_name(), instance);
|
|
||||||
_table->add_child(character->as_egg_bundle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra) {
|
void DAEToEggConverter::
|
||||||
|
process_extra(EggGroup *group, const FCDExtra* extra) {
|
||||||
if (extra == NULL) {
|
if (extra == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -660,18 +808,45 @@ void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LMatrix4d DAEToEggConverter::convert_matrix(const FMMatrix44& matrix) {
|
LMatrix4d DAEToEggConverter::
|
||||||
LMatrix4d result = LMatrix4d::zeros_mat();
|
convert_matrix(const FMMatrix44 &matrix) {
|
||||||
for (char x = 0; x < 4; ++x) {
|
return LMatrix4d(
|
||||||
for (char y = 0; y < 4; ++y) {
|
matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
|
||||||
result(x, y) = matrix[x][y];
|
matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
|
||||||
}
|
matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
|
||||||
}
|
matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DAEToEggConverter::apply_transform(const PT(EggGroup) to, const FCDTransform* from) {
|
void DAEToEggConverter::
|
||||||
|
apply_transform(EggGroup *to, const FCDTransform* from) {
|
||||||
assert(from != NULL);
|
assert(from != NULL);
|
||||||
assert(to != NULL);
|
assert(to != NULL);
|
||||||
to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d());
|
//to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d());
|
||||||
|
switch (from->GetType()) {
|
||||||
|
case FCDTransform::TRANSLATION:
|
||||||
|
{
|
||||||
|
const FCDTTranslation *trans = (const FCDTTranslation *)from;
|
||||||
|
to->add_translate3d(TO_VEC3(trans->GetTranslation()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FCDTransform::ROTATION:
|
||||||
|
{
|
||||||
|
const FCDTRotation *rot = (const FCDTRotation *)from;
|
||||||
|
to->add_rotate3d(rot->GetAngle(), TO_VEC3(rot->GetAxis()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FCDTransform::SCALE:
|
||||||
|
{
|
||||||
|
const FCDTScale *scale = (const FCDTScale *)from;
|
||||||
|
to->add_scale3d(TO_VEC3(scale->GetScale()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Either a matrix, or something we can't handle.
|
||||||
|
to->add_matrix4(convert_matrix(from->ToMatrix()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "FMath/FMMatrix44.h"
|
#include "FMath/FMMatrix44.h"
|
||||||
|
|
||||||
#include "daeMaterials.h"
|
#include "daeMaterials.h"
|
||||||
|
#include "daeCharacter.h"
|
||||||
#include "pvector.h" // Include last
|
#include "pvector.h" // Include last
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -54,31 +55,33 @@ public:
|
|||||||
virtual string get_extension() const;
|
virtual string get_extension() const;
|
||||||
|
|
||||||
virtual bool convert_file(const Filename &filename);
|
virtual bool convert_file(const Filename &filename);
|
||||||
|
virtual DistanceUnit get_input_units();
|
||||||
|
|
||||||
bool _invert_transparency;
|
bool _invert_transparency;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
string _unit_name;
|
||||||
|
double _unit_meters;
|
||||||
PT(EggTable) _table;
|
PT(EggTable) _table;
|
||||||
FCDocument* _document;
|
FCDocument* _document;
|
||||||
FUErrorSimpleHandler* _error_handler;
|
FUErrorSimpleHandler* _error_handler;
|
||||||
pmap<const string, PT(EggGroup)> _joints;
|
DaeCharacter::JointMap _joints;
|
||||||
pmap<const string, PT(EggVertexPool)> _vertex_pools;
|
|
||||||
pvector<string> _skeletons;
|
typedef pvector<PT(DaeCharacter)> Characters;
|
||||||
int _frame_rate;
|
Characters _characters;
|
||||||
|
|
||||||
void process_asset();
|
void process_asset();
|
||||||
void preprocess(const FCDSceneNode* node = NULL);
|
void process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced = false);
|
||||||
void process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced = false);
|
void process_instance(EggGroup *parent, const FCDEntityInstance* instance);
|
||||||
void process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance);
|
void process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh,
|
||||||
void process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials);
|
DaeMaterials *materials, DaeCharacter *character = NULL);
|
||||||
void process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline);
|
void process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline);
|
||||||
void process_spline(PT(EggGroup) parent, const FCDSpline* spline);
|
void process_spline(EggGroup *parent, const FCDSpline* spline);
|
||||||
void process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance);
|
void process_controller(EggGroup *parent, const FCDControllerInstance* instance);
|
||||||
//void process_table_joint(PT(EggTable) parent, FCDSceneNode* node);
|
void process_extra(EggGroup *group, const FCDExtra* extra);
|
||||||
void process_extra(PT(EggGroup) group, const FCDExtra* extra);
|
|
||||||
|
|
||||||
static LMatrix4d convert_matrix(const FMMatrix44& matrix);
|
static LMatrix4d convert_matrix(const FMMatrix44& matrix);
|
||||||
void apply_transform(const PT(EggGroup) to, const FCDTransform* from);
|
void apply_transform(EggGroup *to, const FCDTransform* from);
|
||||||
|
|
||||||
friend class DaeCharacter;
|
friend class DaeCharacter;
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,7 @@ DAEToEgg::
|
|||||||
DAEToEgg():
|
DAEToEgg():
|
||||||
SomethingToEgg("COLLADA", ".dae")
|
SomethingToEgg("COLLADA", ".dae")
|
||||||
{
|
{
|
||||||
|
add_animation_options();
|
||||||
add_units_options();
|
add_units_options();
|
||||||
add_normals_options();
|
add_normals_options();
|
||||||
add_transform_options();
|
add_transform_options();
|
||||||
@ -42,6 +43,7 @@ DAEToEgg():
|
|||||||
("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg.");
|
("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg.");
|
||||||
|
|
||||||
_coordinate_system = CS_yup_right;
|
_coordinate_system = CS_yup_right;
|
||||||
|
_animation_convert = AC_both;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -51,6 +53,12 @@ DAEToEgg():
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DAEToEgg::
|
void DAEToEgg::
|
||||||
run() {
|
run() {
|
||||||
|
if (_animation_convert != AC_both && _animation_convert != AC_none &&
|
||||||
|
_animation_convert != AC_chan && _animation_convert != AC_model) {
|
||||||
|
cerr << "Unsupported animation convert option.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
nout << "Reading " << _input_filename << "\n";
|
nout << "Reading " << _input_filename << "\n";
|
||||||
|
|
||||||
_data->set_coordinate_system(_coordinate_system);
|
_data->set_coordinate_system(_coordinate_system);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user