build a tree of NodeDesc's first, then use to generate joints and tables

This commit is contained in:
David Rose 2003-06-07 01:26:02 +00:00
parent da5268db7a
commit 74d002cb4e
8 changed files with 924 additions and 528 deletions

View File

@ -17,6 +17,8 @@
#define SOURCES \
config_mayaegg.cxx config_mayaegg.h \
mayaEggGroupUserData.cxx mayaEggGroupUserData.I mayaEggGroupUserData.h \
mayaNodeDesc.cxx mayaNodeDesc.h \
mayaNodeTree.cxx mayaNodeTree.h \
mayaToEggConverter.cxx mayaToEggConverter.h
#end ss_lib_target

View File

@ -18,6 +18,7 @@
#include "config_mayaegg.h"
#include "mayaEggGroupUserData.h"
#include "mayaNodeDesc.h"
#include "dconfig.h"
@ -45,5 +46,6 @@ init_libmayaegg() {
initialized = true;
MayaEggGroupUserData::init_type();
MayaNodeDesc::init_type();
}

View File

@ -0,0 +1,191 @@
// Filename: mayaNodeDesc.cxx
// Created by: drose (06Jun03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "mayaNodeDesc.h"
TypeHandle MayaNodeDesc::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaNodeDesc::
MayaNodeDesc(MayaNodeDesc *parent, const string &name) :
Namable(name),
_parent(parent)
{
_dag_path = (MDagPath *)NULL;
_egg_group = (EggGroup *)NULL;
_egg_table = (EggTable *)NULL;
_anim = (EggXfmSAnim *)NULL;
_joint_type = JT_none;
// Add ourselves to our parent.
if (_parent != (MayaNodeDesc *)NULL) {
_parent->_children.push_back(this);
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaNodeDesc::
~MayaNodeDesc() {
if (_dag_path != (MDagPath *)NULL) {
delete _dag_path;
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::from_dag_path
// Access: Public
// Description: Indicates an associated between the MayaNodeDesc and
// some Maya instance.
////////////////////////////////////////////////////////////////////
void MayaNodeDesc::
from_dag_path(const MDagPath &dag_path) {
if (_dag_path == (MDagPath *)NULL) {
_dag_path = new MDagPath(dag_path);
if (_dag_path->hasFn(MFn::kJoint)) {
// This node is a joint.
_joint_type = JT_joint;
if (_parent != (MayaNodeDesc *)NULL) {
_parent->mark_joint_parent();
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::has_dag_path
// Access: Public
// Description: Returns true if a Maya dag path has been associated
// with this node, false otherwise.
////////////////////////////////////////////////////////////////////
bool MayaNodeDesc::
has_dag_path() const {
return (_dag_path != (MDagPath *)NULL);
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::get_dag_path
// Access: Public
// Description: Returns the dag path associated with this node. It
// is an error to call this unless has_dag_path()
// returned true.
////////////////////////////////////////////////////////////////////
const MDagPath &MayaNodeDesc::
get_dag_path() const {
nassertr(_dag_path != (MDagPath *)NULL, *_dag_path);
return *_dag_path;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::is_joint
// Access: Private
// Description: Returns true if the node should be treated as a joint
// by the converter.
////////////////////////////////////////////////////////////////////
bool MayaNodeDesc::
is_joint() const {
return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::is_joint_parent
// Access: Private
// Description: Returns true if the node is the parent or ancestor of
// a joint.
////////////////////////////////////////////////////////////////////
bool MayaNodeDesc::
is_joint_parent() const {
return _joint_type == JT_joint_parent;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::clear_egg
// Access: Private
// Description: Recursively clears the egg pointers from this node
// and all children.
////////////////////////////////////////////////////////////////////
void MayaNodeDesc::
clear_egg() {
_egg_group = (EggGroup *)NULL;
_egg_table = (EggTable *)NULL;
_anim = (EggXfmSAnim *)NULL;
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
MayaNodeDesc *child = (*ci);
child->clear_egg();
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::mark_joint_parent
// Access: Private
// Description: Indicates that this node has at least one child that
// is a joint or a pseudo-joint.
////////////////////////////////////////////////////////////////////
void MayaNodeDesc::
mark_joint_parent() {
if (_joint_type == JT_none) {
_joint_type = JT_joint_parent;
if (_parent != (MayaNodeDesc *)NULL) {
_parent->mark_joint_parent();
}
}
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeDesc::check_pseudo_joints
// Access: Private
// Description: Walks the hierarchy, looking for non-joint nodes that
// are both children and parents of a joint. These
// nodes are deemed to be pseudo joints, since the
// converter must treat them as joints.
////////////////////////////////////////////////////////////////////
void MayaNodeDesc::
check_pseudo_joints(bool joint_above) {
if (_joint_type == JT_joint_parent && joint_above) {
// This is one such node: it is the parent of a joint
// (JT_joint_parent is set), and it is the child of a joint
// (joint_above is set).
_joint_type = JT_pseudo_joint;
}
if (_joint_type == JT_joint) {
// If this node is itself a joint, then joint_above is true for
// all child nodes.
joint_above = true;
}
// Don't bother traversing further if _joint_type is none, since
// that means this node has no joint children.
if (_joint_type != JT_none) {
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
MayaNodeDesc *child = (*ci);
child->check_pseudo_joints(joint_above);
}
}
}

View File

@ -0,0 +1,98 @@
// Filename: mayaNodeDesc.h
// Created by: drose (06Jun03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef MAYANODEDESC_H
#define MAYANODEDESC_H
#include "pandatoolbase.h"
#include "referenceCount.h"
#include "pointerTo.h"
#include "namable.h"
#include "pre_maya_include.h"
#include <maya/MDagPath.h>
#include "post_maya_include.h"
class EggGroup;
class EggTable;
class EggXfmSAnim;
////////////////////////////////////////////////////////////////////
// Class : MayaNodeDesc
// Description : Describes a single instance of a node in the Maya
// scene graph, relating it to the corresponding egg
// structures (e.g. node, group, or table entry) that
// will be created.
////////////////////////////////////////////////////////////////////
class MayaNodeDesc : public ReferenceCount, public Namable {
public:
MayaNodeDesc(MayaNodeDesc *parent = NULL, const string &name = string());
~MayaNodeDesc();
void from_dag_path(const MDagPath &dag_path);
bool has_dag_path() const;
const MDagPath &get_dag_path() const;
bool is_joint() const;
bool is_joint_parent() const;
MayaNodeDesc *_parent;
typedef pvector< PT(MayaNodeDesc) > Children;
Children _children;
private:
void clear_egg();
void mark_joint_parent();
void check_pseudo_joints(bool joint_above);
MDagPath *_dag_path;
EggGroup *_egg_group;
EggTable *_egg_table;
EggXfmSAnim *_anim;
enum JointType {
JT_none, // Not a joint.
JT_joint, // An actual joint in Maya.
JT_pseudo_joint, // Not a joint in Maya, but treated just like a
// joint for the purposes of the converter.
JT_joint_parent, // A parent or ancestor of a joint or pseudo joint.
};
JointType _joint_type;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ReferenceCount::init_type();
Namable::init_type();
register_type(_type_handle, "MayaNodeDesc",
ReferenceCount::get_class_type(),
Namable::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class MayaNodeTree;
};
#endif

View File

@ -0,0 +1,387 @@
// Filename: mayaNodeTree.cxx
// Created by: drose (06Jun03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "mayaNodeTree.h"
#include "mayaEggGroupUserData.h"
#include "config_mayaegg.h"
#include "maya_funcs.h"
#include "eggGroup.h"
#include "eggTable.h"
#include "eggXfmSAnim.h"
#include "eggData.h"
#include "pre_maya_include.h"
#include <maya/MString.h>
#include <maya/MItDag.h>
#include <maya/MSelectionList.h>
#include <maya/MGlobal.h>
#include "post_maya_include.h"
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
MayaNodeTree::
MayaNodeTree() {
_root = new MayaNodeDesc;
_fps = 0.0;
_egg_data = (EggData *)NULL;
_egg_root = (EggGroupNode *)NULL;
_skeleton_node = (EggGroupNode *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::build_node
// Access: Public
// Description: Returns a pointer to the node corresponding to the
// indicated dag_path object, creating it first if
// necessary.
////////////////////////////////////////////////////////////////////
MayaNodeDesc *MayaNodeTree::
build_node(const MDagPath &dag_path) {
MayaNodeDesc *node_desc = r_build_node(dag_path.fullPathName().asChar());
node_desc->from_dag_path(dag_path);
return node_desc;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::build_complete_hierarchy
// Access: Public
// Description: Walks through the complete Maya hierarchy and builds
// up the corresponding tree.
////////////////////////////////////////////////////////////////////
bool MayaNodeTree::
build_complete_hierarchy() {
MStatus status;
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
if (!status) {
status.perror("MItDag constructor");
return false;
}
// Get the entire Maya scene.
// This while loop walks through the entire Maya hierarchy, one
// node at a time. Maya's MItDag object automatically performs a
// depth-first traversal of its scene graph.
bool all_ok = true;
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
build_node(dag_path);
}
dag_iterator.next();
}
if (all_ok) {
_root->check_pseudo_joints(false);
}
return all_ok;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::build_selected_hierarchy
// Access: Public
// Description: Walks through the selected subset of the Maya
// hierarchy (or the complete hierarchy, if nothing is
// selected) and builds up the corresponding tree.
////////////////////////////////////////////////////////////////////
bool MayaNodeTree::
build_selected_hierarchy() {
MStatus status;
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
if (!status) {
status.perror("MItDag constructor");
return false;
}
// Get only the selected geometry.
MSelectionList selection;
status = MGlobal::getActiveSelectionList(selection);
if (!status) {
status.perror("MGlobal::getActiveSelectionList");
return false;
}
// Get the selected geometry only if the selection is nonempty;
// otherwise, get the whole scene anyway.
if (selection.isEmpty()) {
mayaegg_cat.info()
<< "Selection list is empty.\n";
return build_complete_hierarchy();
}
bool all_ok = true;
unsigned int length = selection.length();
for (unsigned int i = 0; i < length; i++) {
MDagPath root_path;
status = selection.getDagPath(i, root_path);
if (!status) {
status.perror("MSelectionList::getDagPath");
} else {
// Now traverse through the selected dag path and all nested
// dag paths.
dag_iterator.reset(root_path);
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
build_node(dag_path);
}
dag_iterator.next();
}
}
}
if (all_ok) {
_root->check_pseudo_joints(false);
}
return all_ok;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::get_num_nodes
// Access: Public
// Description: Returns the total number of nodes in the hierarchy,
// not counting the root node.
////////////////////////////////////////////////////////////////////
int MayaNodeTree::
get_num_nodes() const {
return _nodes.size();
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::get_node
// Access: Public
// Description: Returns the nth node in the hierarchy, in an
// arbitrary ordering.
////////////////////////////////////////////////////////////////////
MayaNodeDesc *MayaNodeTree::
get_node(int n) const {
nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
return _nodes[n];
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::clear_egg
// Access: Public
// Description: Removes all of the references to generated egg
// structures from the tree, and prepares the tree for
// generating new egg structures.
////////////////////////////////////////////////////////////////////
void MayaNodeTree::
clear_egg(EggData *egg_data, EggGroupNode *egg_root,
EggGroupNode *skeleton_node) {
_root->clear_egg();
_egg_data = egg_data;
_egg_root = egg_root;
_skeleton_node = skeleton_node;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::get_egg_group
// Access: Public
// Description: Returns the EggGroupNode corresponding to the group
// or joint for the indicated node. Creates the group
// node if it has not already been created.
////////////////////////////////////////////////////////////////////
EggGroup *MayaNodeTree::
get_egg_group(MayaNodeDesc *node_desc) {
nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
if (node_desc->_egg_group == (EggGroup *)NULL) {
// We need to make a new group node.
EggGroup *egg_group;
nassertr(node_desc->_parent != (MayaNodeDesc *)NULL, NULL);
egg_group = new EggGroup(node_desc->get_name());
if (node_desc->is_joint()) {
egg_group->set_group_type(EggGroup::GT_joint);
}
if (node_desc->_parent == _root) {
// The parent is the root.
_egg_root->add_child(egg_group);
} else {
// The parent is another node.
EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
parent_egg_group->add_child(egg_group);
}
if (node_desc->has_dag_path()) {
// Check for an object type setting, from Oliver's plug-in.
MObject dag_object = node_desc->get_dag_path().node();
string object_type;
if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
egg_group->add_object_type(object_type);
}
if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
egg_group->add_object_type(object_type);
}
if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
egg_group->add_object_type(object_type);
}
// We treat the object type "billboard" as a special case: we
// apply this one right away and also flag the group as an
// instance.
if (egg_group->has_object_type("billboard")) {
egg_group->remove_object_type("billboard");
egg_group->set_group_type(EggGroup::GT_instance);
egg_group->set_billboard_type(EggGroup::BT_axis);
} else if (egg_group->has_object_type("billboard-point")) {
egg_group->remove_object_type("billboard-point");
egg_group->set_group_type(EggGroup::GT_instance);
egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
}
// We also treat the object type "dcs" and "model" as a special
// case, so we can test for these flags later.
if (egg_group->has_object_type("dcs")) {
egg_group->remove_object_type("dcs");
egg_group->set_dcs_type(EggGroup::DC_default);
}
if (egg_group->has_object_type("model")) {
egg_group->remove_object_type("model");
egg_group->set_model_flag(true);
}
// And "vertex-color" has meaning only to this converter.
if (egg_group->has_object_type("vertex-color")) {
egg_group->remove_object_type("vertex-color");
MayaEggGroupUserData *user_data = new MayaEggGroupUserData;
user_data->_vertex_color = true;
egg_group->set_user_data(user_data);
}
}
node_desc->_egg_group = egg_group;
}
return node_desc->_egg_group;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::get_egg_table
// Access: Public
// Description: Returns the EggTable corresponding to the joint
// for the indicated node. Creates the table node if it
// has not already been created.
////////////////////////////////////////////////////////////////////
EggTable *MayaNodeTree::
get_egg_table(MayaNodeDesc *node_desc) {
nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
nassertr(node_desc->is_joint(), NULL);
if (node_desc->_egg_table == (EggTable *)NULL) {
// We need to make a new table node.
nassertr(node_desc->_parent != (MayaNodeDesc *)NULL, NULL);
EggTable *egg_table = new EggTable(node_desc->get_name());
node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
node_desc->_anim->set_fps(_fps);
egg_table->add_child(node_desc->_anim);
if (!node_desc->_parent->is_joint()) {
// The parent is not a joint; put it at the top.
_skeleton_node->add_child(egg_table);
} else {
// The parent is another joint.
EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
parent_egg_table->add_child(egg_table);
}
node_desc->_egg_table = egg_table;
}
return node_desc->_egg_table;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::get_egg_anim
// Access: Public
// Description: Returns the anim table corresponding to the joint
// for the indicated node. Creates the table node if it
// has not already been created.
////////////////////////////////////////////////////////////////////
EggXfmSAnim *MayaNodeTree::
get_egg_anim(MayaNodeDesc *node_desc) {
get_egg_table(node_desc);
return node_desc->_anim;
}
////////////////////////////////////////////////////////////////////
// Function: MayaNodeTree::r_build_node
// Access: Private
// Description: The recursive implementation of build_node().
////////////////////////////////////////////////////////////////////
MayaNodeDesc *MayaNodeTree::
r_build_node(const string &path) {
// If we have already encountered this pathname, return the
// corresponding MayaNodeDesc immediately.
NodesByPath::const_iterator ni = _nodes_by_path.find(path);
if (ni != _nodes_by_path.end()) {
return (*ni).second;
}
// Otherwise, we have to create it. Do this recursively, so we
// create each node along the path.
MayaNodeDesc *node_desc;
if (path.empty()) {
// This is the top.
node_desc = _root;
} else {
// Maya uses vertical bars to separate path components. Remove
// everything from the rightmost bar on; this will give us the
// parent's path name.
size_t bar = path.rfind("|");
string parent_path, local_name;
if (bar != string::npos) {
parent_path = path.substr(0, bar);
local_name = path.substr(bar + 1);
} else {
local_name = path;
}
MayaNodeDesc *parent_node_desc = r_build_node(parent_path);
node_desc = new MayaNodeDesc(parent_node_desc, local_name);
_nodes.push_back(node_desc);
}
_nodes_by_path.insert(NodesByPath::value_type(path, node_desc));
return node_desc;
}

View File

@ -0,0 +1,67 @@
// Filename: mayaNodeTree.h
// Created by: drose (06Jun03)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef MAYANODETREE_H
#define MAYANODETREE_H
#include "pandatoolbase.h"
#include "mayaNodeDesc.h"
class EggData;
class EggGroupNode;
////////////////////////////////////////////////////////////////////
// Class : MayaNodeTree
// Description : Describes a complete tree of maya nodes for
// conversion.
////////////////////////////////////////////////////////////////////
class MayaNodeTree {
public:
MayaNodeTree();
MayaNodeDesc *build_node(const MDagPath &dag_path);
bool build_complete_hierarchy();
bool build_selected_hierarchy();
int get_num_nodes() const;
MayaNodeDesc *get_node(int n) const;
void clear_egg(EggData *egg_data, EggGroupNode *egg_root,
EggGroupNode *skeleton_node);
EggGroup *get_egg_group(MayaNodeDesc *node_desc);
EggTable *get_egg_table(MayaNodeDesc *node_desc);
EggXfmSAnim *get_egg_anim(MayaNodeDesc *node_desc);
PT(MayaNodeDesc) _root;
float _fps;
private:
EggData *_egg_data;
EggGroupNode *_egg_root;
EggGroupNode *_skeleton_node;
MayaNodeDesc *r_build_node(const string &path);
typedef pmap<string, MayaNodeDesc *> NodesByPath;
NodesByPath _nodes_by_path;
typedef pvector<MayaNodeDesc *> Nodes;
Nodes _nodes;
};
#endif

View File

@ -188,8 +188,6 @@ convert_maya(bool from_selection) {
_from_selection = from_selection;
_textures.clear();
_shaders.clear();
_groups.clear();
_tables.clear();
if (!open_api()) {
mayaegg_cat.error()
@ -235,6 +233,13 @@ convert_maya(bool from_selection) {
bool all_ok = true;
if (_from_selection) {
all_ok = _tree.build_selected_hierarchy();
} else {
all_ok = _tree.build_complete_hierarchy();
}
if (all_ok) {
switch (get_animation_convert()) {
case AC_pose:
// pose: set to a specific frame, then get out the static geometry.
@ -282,6 +287,7 @@ convert_maya(bool from_selection) {
};
reparent_decals(&get_egg_data());
}
if (all_ok) {
mayaegg_cat.info()
@ -355,10 +361,9 @@ convert_flip(double start_frame, double end_frame, double frame_inc,
sequence_node->add_child(frame_root);
MGlobal::viewFrame(frame);
if (!convert_hierarchy(frame_root)) {
if (!convert_hierarchy(&get_egg_data())) {
all_ok = false;
}
_groups.clear();
frame += frame_inc;
}
@ -408,38 +413,10 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
EggTable *skeleton_node = new EggTable("<skeleton>");
bundle_node->add_child(skeleton_node);
// First, walk through the scene graph and build up the table of
// joints.
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
if (!status) {
status.perror("MItDag constructor");
return false;
}
bool all_ok = true;
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
if (!process_chan_node(dag_path, skeleton_node)) {
all_ok = false;
}
}
dag_iterator.next();
}
// Now walk through the joints in that table and make sure they're
// all set to use the correct frame frame.
double fps = output_frame_rate / frame_inc;
Tables::iterator ti;
for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
JointAnim *joint_anim = (*ti).second;
nassertr(joint_anim != (JointAnim *)NULL &&
joint_anim->_anim != (EggXfmSAnim *)NULL, false);
joint_anim->_anim->set_fps(fps);
}
// Set the frame rate before we start asking for anim tables to be
// created.
_tree._fps = output_frame_rate / frame_inc;
_tree.clear_egg(&get_egg_data(), NULL, skeleton_node);
// Now we can get the animation data by walking through all of the
// frames, one at a time, and getting the joint angles at each
@ -449,6 +426,9 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
// each joint each frame.
PT(EggGroup) tgroup = new EggGroup;
int num_nodes = _tree.get_num_nodes();
int i;
MTime frame(start_frame, MTime::uiUnit());
MTime frame_stop(end_frame, MTime::uiUnit());
while (frame <= frame_stop) {
@ -461,114 +441,50 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
}
MGlobal::viewFrame(frame);
for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
JointAnim *joint_anim = (*ti).second;
get_joint_transform(joint_anim->_dag_path, tgroup);
joint_anim->_anim->add_data(tgroup->get_transform());
for (i = 0; i < num_nodes; i++) {
MayaNodeDesc *node_desc = _tree.get_node(i);
if (node_desc->is_joint()) {
get_joint_transform(node_desc->get_dag_path(), tgroup);
_tree.get_egg_anim(node_desc)->add_data(tgroup->get_transform());
}
}
frame += frame_inc;
}
// Now optimize all of the tables we just filled up, for no real
// good reason.
for (i = 0; i < num_nodes; i++) {
MayaNodeDesc *node_desc = _tree.get_node(i);
if (node_desc->is_joint()) {
_tree.get_egg_anim(node_desc)->optimize();
}
}
mayaegg_cat.info(false)
<< "\n";
// Finally, clean up by deleting all of the JointAnim structures we
// created.
for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
JointAnim *joint_anim = (*ti).second;
delete joint_anim;
}
_tables.clear();
return all_ok;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::convert_hierarchy
// Access: Private
// Description: Walks the entire Maya hierarchy, converting it to a
// corresponding egg hierarchy under the indicated root
// node.
// Description: Generates egg structures for each node in the Maya
// hierarchy.
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
convert_hierarchy(EggGroupNode *egg_root) {
MStatus status;
int num_nodes = _tree.get_num_nodes();
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
if (!status) {
status.perror("MItDag constructor");
_tree.clear_egg(&get_egg_data(), egg_root, NULL);
for (int i = 0; i < num_nodes; i++) {
if (!process_model_node(_tree.get_node(i))) {
return false;
}
if (_from_selection) {
// Get only the selected geometry.
MSelectionList selection;
status = MGlobal::getActiveSelectionList(selection);
if (!status) {
status.perror("MGlobal::getActiveSelectionList");
return false;
}
// Get the selected geometry only if the selection is nonempty;
// otherwise, get the whole scene anyway.
if (!selection.isEmpty()) {
bool all_ok = true;
unsigned int length = selection.length();
for (unsigned int i = 0; i < length; i++) {
MDagPath root_path;
status = selection.getDagPath(i, root_path);
if (!status) {
status.perror("MSelectionList::getDagPath");
} else {
// Now traverse through the selected dag path and all nested
// dag paths.
dag_iterator.reset(root_path);
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
if (!process_model_node(dag_path, egg_root)) {
all_ok = false;
}
}
dag_iterator.next();
}
}
}
return all_ok;
} else {
mayaegg_cat.info()
<< "Selection list is empty.\n";
// Fall through.
}
}
// Get the entire Maya scene.
// This while loop walks through the entire Maya hierarchy, one
// node at a time. Maya's MItDag object automatically performs a
// depth-first traversal of its scene graph.
bool all_ok = true;
while (!dag_iterator.isDone()) {
MDagPath dag_path;
status = dag_iterator.getPath(dag_path);
if (!status) {
status.perror("MItDag::getPath");
} else {
if (!process_model_node(dag_path, egg_root)) {
all_ok = false;
}
}
dag_iterator.next();
}
return all_ok;
return true;
}
////////////////////////////////////////////////////////////////////
@ -580,7 +496,14 @@ convert_hierarchy(EggGroupNode *egg_root) {
// successful, false if an error was encountered.
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
process_model_node(MayaNodeDesc *node_desc) {
if (!node_desc->has_dag_path()) {
// If the node has no Maya equivalent, never mind.
return true;
}
MDagPath dag_path = node_desc->get_dag_path();
MStatus status;
MFnDagNode dag_node(dag_path, &status);
if (!status) {
@ -588,9 +511,11 @@ process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
return false;
}
string path = dag_path.fullPathName().asChar();
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< dag_path.fullPathName().asChar() << ": " << dag_node.typeName();
<< path << ": " << dag_node.typeName();
if (MAnimUtil::isAnimated(dag_path)) {
mayaegg_cat.debug(false)
@ -600,70 +525,54 @@ process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
mayaegg_cat.debug(false) << "\n";
}
if (dag_node.inUnderWorld()) {
if (node_desc->is_joint()) {
// Don't bother with joints unless we're getting an animatable
// model.
if (_animation_convert == AC_model) {
EggGroup *egg_group = _tree.get_egg_group(node_desc);
get_joint_transform(dag_path, egg_group);
}
} else if (dag_node.inUnderWorld()) {
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring underworld node " << dag_path.fullPathName().asChar()
<< "Ignoring underworld node " << path
<< "\n";
}
} else if (dag_node.isIntermediateObject()) {
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring intermediate object " << dag_path.fullPathName().asChar()
<< "Ignoring intermediate object " << path
<< "\n";
}
} else if (dag_path.hasFn(MFn::kCamera)) {
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring camera node " << dag_path.fullPathName().asChar()
<< "Ignoring camera node " << path
<< "\n";
}
} else if (dag_path.hasFn(MFn::kLight)) {
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Ignoring light node " << dag_path.fullPathName().asChar()
<< "Ignoring light node " << path
<< "\n";
}
} else if (dag_path.hasFn(MFn::kJoint)) {
// A joint.
// Don't bother with joints unless we're getting an animatable
// model.
if (_animation_convert == AC_model) {
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
if (egg_group != (EggGroup *)NULL) {
egg_group->set_group_type(EggGroup::GT_joint);
get_joint_transform(dag_path, egg_group);
}
}
} else if (dag_path.hasFn(MFn::kNurbsSurface)) {
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
if (egg_group == (EggGroup *)NULL) {
mayaegg_cat.error()
<< "Cannot determine group node.\n";
return false;
} else {
if (_animation_convert != AC_model) {
EggGroup *egg_group = _tree.get_egg_group(node_desc);
get_transform(dag_path, egg_group);
}
MFnNurbsSurface surface(dag_path, &status);
if (!status) {
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName().asChar()
<< "Error in node " << path
<< ":\n"
<< " it appears to have a NURBS surface, but does not.\n";
} else {
make_nurbs_surface(dag_path, surface, egg_group, egg_root);
}
make_nurbs_surface(dag_path, surface, egg_group);
}
} else if (dag_path.hasFn(MFn::kNurbsCurve)) {
@ -671,61 +580,38 @@ process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
// Animated models, as a general rule, don't want these sorts of
// things in them.
if (_animation_convert != AC_model) {
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
if (egg_group == (EggGroup *)NULL) {
mayaegg_cat.error()
<< "Cannot determine group node.\n";
} else {
EggGroup *egg_group = _tree.get_egg_group(node_desc);
get_transform(dag_path, egg_group);
MFnNurbsCurve curve(dag_path, &status);
if (!status) {
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName().asChar() << ":\n"
<< "Error in node " << path << ":\n"
<< " it appears to have a NURBS curve, but does not.\n";
} else {
make_nurbs_curve(dag_path, curve, egg_group, egg_root);
}
make_nurbs_curve(dag_path, curve, egg_group);
}
}
} else if (dag_path.hasFn(MFn::kMesh)) {
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
if (egg_group == (EggGroup *)NULL) {
mayaegg_cat.error()
<< "Cannot determine group node.\n";
return false;
} else {
if (_animation_convert != AC_model) {
EggGroup *egg_group = _tree.get_egg_group(node_desc);
get_transform(dag_path, egg_group);
}
MFnMesh mesh(dag_path, &status);
if (!status) {
mayaegg_cat.info()
<< "Error in node " << dag_path.fullPathName().asChar() << ":\n"
<< "Error in node " << path << ":\n"
<< " it appears to have a polygon mesh, but does not.\n";
} else {
make_polyset(dag_path, mesh, egg_group, egg_root);
}
make_polyset(dag_path, mesh, egg_group);
}
} else if (dag_path.hasFn(MFn::kLocator)) {
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
EggGroup *egg_group = _tree.get_egg_group(node_desc);
if (egg_group == (EggGroup *)NULL) {
mayaegg_cat.error()
<< "Cannot determine group node.\n";
return false;
} else {
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< "Locator at " << dag_path.fullPathName().asChar() << "\n";
<< "Locator at " << path << "\n";
}
// Presumably, the locator's position has some meaning to the
@ -737,59 +623,15 @@ process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
// this. Perhaps there's no reason to ever change this, since
// locators within character models may not be meaningful.
egg_group->set_dcs_type(EggGroup::DC_net);
}
get_transform(dag_path, egg_group);
}
make_locator(dag_path, dag_node, egg_group, egg_root);
}
make_locator(dag_path, dag_node, egg_group);
} else {
// Get the translation/rotation/scale data
EggGroup *egg_group = get_egg_group(dag_path, egg_root);
if (egg_group != (EggGroup *)NULL) {
if (_animation_convert != AC_model) {
// Just a generic node.
EggGroup *egg_group = _tree.get_egg_group(node_desc);
get_transform(dag_path, egg_group);
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::process_chan_node
// Access: Private
// Description: Similar to process_model_node(), but this code path
// is followed only when we are building a table of
// animation data (AC_chan). It just builds up the
// EggTable hierarchy according to the joint table.
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
process_chan_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
MStatus status;
MFnDagNode dag_node(dag_path, &status);
if (!status) {
status.perror("MFnDagNode constructor");
return false;
}
if (dag_path.hasFn(MFn::kJoint)) {
// A joint.
if (mayaegg_cat.is_debug()) {
mayaegg_cat.debug()
<< dag_path.fullPathName().asChar() << ": " << dag_node.typeName();
if (MAnimUtil::isAnimated(dag_path)) {
mayaegg_cat.debug(false)
<< " (animated)";
}
mayaegg_cat.debug(false) << "\n";
}
get_egg_table(dag_path, egg_root);
}
return true;
}
@ -802,6 +644,12 @@ process_chan_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
get_transform(const MDagPath &dag_path, EggGroup *egg_group) {
if (_animation_convert == AC_model) {
// When we're getting an animated model, we only get transforms
// for joints.
return;
}
MStatus status;
MObject transformNode = dag_path.transform(&status);
if (!status && status.statusCode() == MStatus::kInvalidParameter) {
@ -959,7 +807,7 @@ get_joint_transform(const MDagPath &dag_path, EggGroup *egg_group) {
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
EggGroup *egg_group, EggGroupNode *egg_root) {
EggGroup *egg_group) {
MStatus status;
string name = surface.name().asChar();
@ -1015,7 +863,7 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
status.perror("MFnMesh constructor");
return;
}
make_polyset(polyset_path, polyset_fn, egg_group, egg_root, shader);
make_polyset(polyset_path, polyset_fn, egg_group, shader);
// Now remove the polyset we created.
MFnDagNode parent_node(polyset_parent, &status);
@ -1271,7 +1119,7 @@ make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
EggGroup *egg_group, EggGroupNode *) {
EggGroup *egg_group) {
MStatus status;
string name = curve.name().asChar();
@ -1360,8 +1208,7 @@ make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
EggGroup *egg_group, EggGroupNode *egg_root,
MayaShader *default_shader) {
EggGroup *egg_group, MayaShader *default_shader) {
MStatus status;
string name = mesh.name().asChar();
@ -1556,10 +1403,10 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
MFloatArray weights;
if (_animation_convert == AC_model) {
got_weights =
get_vertex_weights(dag_path, mesh, egg_root, joints, weights);
get_vertex_weights(dag_path, mesh, joints, weights);
}
if (got_weights) {
if (got_weights && !joints.empty()) {
int num_joints = joints.size();
int num_weights = (int)weights.length();
int num_verts = num_weights / num_joints;
@ -1598,7 +1445,7 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
////////////////////////////////////////////////////////////////////
void MayaToEggConverter::
make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
EggGroup *egg_group, EggGroupNode *egg_root) {
EggGroup *egg_group) {
MStatus status;
unsigned int num_children = dag_node.childCount();
@ -1650,7 +1497,6 @@ make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
////////////////////////////////////////////////////////////////////
bool MayaToEggConverter::
get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
EggGroupNode *egg_root,
pvector<EggGroup *> &joints, MFloatArray &weights) {
MStatus status;
@ -1696,7 +1542,8 @@ get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
joints.clear();
for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
MDagPath joint_dag_path = influence_objects[oi];
EggGroup *joint = get_egg_group(joint_dag_path, egg_root);
MayaNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
EggGroup *joint = _tree.get_egg_group(joint_node_desc);
joints.push_back(joint);
}
@ -1736,189 +1583,6 @@ get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
return false;
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_egg_group
// Access: Private
// Description: Returns the EggGroup corresponding to the indicated
// fully-qualified Maya path name. If there is not
// already an EggGroup corresponding to this Maya path,
// creates one and returns it.
//
// In this way we generate a unique EggGroup for each
// Maya node we care about about, and also preserve the
// Maya hierarchy sensibly.
////////////////////////////////////////////////////////////////////
EggGroup *MayaToEggConverter::
get_egg_group(const MDagPath &dag_path, EggGroupNode *egg_root) {
return r_get_egg_group(dag_path.fullPathName().asChar(), dag_path, egg_root);
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::r_get_egg_group
// Access: Private
// Description: The recursive implementation of get_egg_group().
////////////////////////////////////////////////////////////////////
EggGroup *MayaToEggConverter::
r_get_egg_group(const string &name, const MDagPath &dag_path,
EggGroupNode *egg_root) {
// If we have already encountered this pathname, return the
// corresponding EggGroup immediately.
Groups::const_iterator gi = _groups.find(name);
if (gi != _groups.end()) {
return (*gi).second;
}
// Otherwise, we have to create it. Do this recursively, so we
// create each node along the path.
EggGroup *egg_group;
if (name.empty()) {
// This is the top.
egg_group = (EggGroup *)NULL;
} else {
// Maya uses vertical bars to separate path components. Remove
// everything from the rightmost bar on; this will give us the
// parent's path name.
size_t bar = name.rfind("|");
string parent_name, local_name;
if (bar != string::npos) {
parent_name = name.substr(0, bar);
local_name = name.substr(bar + 1);
} else {
local_name = name;
}
EggGroup *parent_egg_group =
r_get_egg_group(parent_name, dag_path, egg_root);
egg_group = new EggGroup(local_name);
if (parent_egg_group != (EggGroup *)NULL) {
parent_egg_group->add_child(egg_group);
} else {
egg_root->add_child(egg_group);
}
// Check for an object type setting, from Oliver's plug-in.
MObject dag_object = dag_path.node();
string object_type;
if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
egg_group->add_object_type(object_type);
}
if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
egg_group->add_object_type(object_type);
}
if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
egg_group->add_object_type(object_type);
}
// We treat the object type "billboard" as a special case: we
// apply this one right away and also flag the group as an
// instance.
if (egg_group->has_object_type("billboard")) {
egg_group->remove_object_type("billboard");
egg_group->set_group_type(EggGroup::GT_instance);
egg_group->set_billboard_type(EggGroup::BT_axis);
} else if (egg_group->has_object_type("billboard-point")) {
egg_group->remove_object_type("billboard-point");
egg_group->set_group_type(EggGroup::GT_instance);
egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
}
// We also treat the object type "dcs" and "model" as a special
// case, so we can test for these flags later.
if (egg_group->has_object_type("dcs")) {
egg_group->remove_object_type("dcs");
egg_group->set_dcs_type(EggGroup::DC_default);
}
if (egg_group->has_object_type("model")) {
egg_group->remove_object_type("model");
egg_group->set_model_flag(true);
}
// And "vertex-color" has meaning only to this converter.
if (egg_group->has_object_type("vertex-color")) {
egg_group->remove_object_type("vertex-color");
MayaEggGroupUserData *user_data = new MayaEggGroupUserData;
user_data->_vertex_color = true;
egg_group->set_user_data(user_data);
}
}
_groups.insert(Groups::value_type(name, egg_group));
return egg_group;
}
////////////////////////////////////////////////////////////////////
// Function: MayaToEggConverter::get_egg_table
// Access: Private
// Description: Returns the EggTable corresponding to the indicated
// fully-qualified Maya path name. This is similar to
// get_egg_group(), but this variant is used only when
// we are building a channel file, which is just a
// hierarchical collection of animation tables.
////////////////////////////////////////////////////////////////////
MayaToEggConverter::JointAnim *MayaToEggConverter::
get_egg_table(const MDagPath &dag_path, EggGroupNode *egg_root) {
string name = dag_path.fullPathName().asChar();
// If we have already encountered this pathname, return the
// corresponding EggTable immediately.
Tables::const_iterator ti = _tables.find(name);
if (ti != _tables.end()) {
return (*ti).second;
}
// Otherwise, we have to create it.
JointAnim *joint_anim;
if (name.empty()) {
// This is the top.
joint_anim = (JointAnim *)NULL;
} else {
// Maya uses vertical bars to separate path components. Remove
// everything from the rightmost bar on; this will give us the
// parent's path name.
size_t bar = name.rfind("|");
string parent_name, local_name;
if (bar != string::npos) {
parent_name = name.substr(0, bar);
local_name = name.substr(bar + 1);
} else {
local_name = name;
}
// Look only one level up for the parent. If it hasn't been
// defined yet, don't define it; instead, just start from the
// root.
JointAnim *parent_joint_anim = NULL;
if (!parent_name.empty()) {
ti = _tables.find(parent_name);
if (ti != _tables.end()) {
parent_joint_anim = (*ti).second;
}
}
joint_anim = new JointAnim;
joint_anim->_dag_path = dag_path;
joint_anim->_table = new EggTable(local_name);
joint_anim->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
joint_anim->_table->add_child(joint_anim->_anim);
if (parent_joint_anim != (JointAnim *)NULL) {
parent_joint_anim->_table->add_child(joint_anim->_table);
} else {
egg_root->add_child(joint_anim->_table);
}
}
_tables.insert(Tables::value_type(name, joint_anim));
return joint_anim;
}
////////////////////////////////////////////////////////////////////
// Function: MayaShader::set_shader_attributes
// Access: Private

View File

@ -21,6 +21,7 @@
#include "pandatoolbase.h"
#include "somethingToEggConverter.h"
#include "mayaNodeTree.h"
#include "mayaApi.h"
#include "mayaShaders.h"
@ -79,12 +80,13 @@ public:
private:
bool convert_flip(double start_frame, double end_frame,
double frame_inc, double output_frame_rate);
bool convert_char_model();
bool convert_char_chan(double start_frame, double end_frame,
double frame_inc, double output_frame_rate);
bool convert_hierarchy(EggGroupNode *egg_root);
bool process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root);
bool process_chan_node(const MDagPath &dag_path, EggGroupNode *egg_root);
bool process_model_node(MayaNodeDesc *node_desc);
void get_transform(const MDagPath &dag_path, EggGroup *egg_group);
void get_joint_transform(const MDagPath &dag_path, EggGroup *egg_group);
@ -93,35 +95,22 @@ private:
// reference.
void make_nurbs_surface(const MDagPath &dag_path,
MFnNurbsSurface &surface,
EggGroup *group, EggGroupNode *egg_root);
EggGroup *group);
EggNurbsCurve *make_trim_curve(const MFnNurbsCurve &curve,
const string &nurbs_name,
EggGroupNode *egg_group,
int trim_curve_index);
void make_nurbs_curve(const MDagPath &dag_path,
const MFnNurbsCurve &curve,
EggGroup *group, EggGroupNode *egg_root);
EggGroup *group);
void make_polyset(const MDagPath &dag_path,
const MFnMesh &mesh,
EggGroup *egg_group, EggGroupNode *egg_root,
EggGroup *egg_group,
MayaShader *default_shader = NULL);
void make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
EggGroup *egg_group, EggGroupNode *egg_root);
EggGroup *egg_group);
bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
EggGroupNode *egg_root,
pvector<EggGroup *> &joints, MFloatArray &weights);
class JointAnim {
public:
MDagPath _dag_path;
EggTable *_table;
EggXfmSAnim *_anim;
};
EggGroup *get_egg_group(const MDagPath &dag_path, EggGroupNode *egg_root);
EggGroup *r_get_egg_group(const string &name, const MDagPath &dag_path,
EggGroupNode *egg_root);
JointAnim *get_egg_table(const MDagPath &dag_path, EggGroupNode *egg_root);
JointAnim *get_egg_table(const string &name, EggGroupNode *egg_root);
void set_shader_attributes(EggPrimitive &primitive,
const MayaShader &shader);
void apply_texture_properties(EggTexture &tex,
@ -131,15 +120,11 @@ private:
bool reparent_decals(EggGroupNode *egg_parent);
typedef pmap<string, EggGroup *> Groups;
Groups _groups;
typedef pmap<string, JointAnim *> Tables;
Tables _tables;
string _program_name;
bool _from_selection;
MayaNodeTree _tree;
public:
MayaShaders _shaders;
EggTextureCollection _textures;