mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
support blend shapes
This commit is contained in:
parent
1e11242da3
commit
aa297d26ee
@ -17,6 +17,7 @@
|
||||
#define SOURCES \
|
||||
config_mayaegg.cxx config_mayaegg.h \
|
||||
mayaEggGroupUserData.cxx mayaEggGroupUserData.I mayaEggGroupUserData.h \
|
||||
mayaBlendDesc.cxx mayaBlendDesc.h \
|
||||
mayaNodeDesc.cxx mayaNodeDesc.h \
|
||||
mayaNodeTree.cxx mayaNodeTree.h \
|
||||
mayaToEggConverter.cxx mayaToEggConverter.h
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "config_mayaegg.h"
|
||||
#include "mayaEggGroupUserData.h"
|
||||
#include "mayaNodeDesc.h"
|
||||
#include "mayaBlendDesc.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
@ -60,6 +61,7 @@ init_libmayaegg() {
|
||||
|
||||
MayaEggGroupUserData::init_type();
|
||||
MayaNodeDesc::init_type();
|
||||
MayaBlendDesc::init_type();
|
||||
|
||||
// For some reason, static init is not reliably running when this is
|
||||
// loaded as a plug-in of a plug-in. Initialize these explicitly
|
||||
|
80
pandatool/src/mayaegg/mayaBlendDesc.cxx
Normal file
80
pandatool/src/mayaegg/mayaBlendDesc.cxx
Normal file
@ -0,0 +1,80 @@
|
||||
// Filename: mayaBlendDesc.cxx
|
||||
// Created by: drose (10Feb04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "mayaBlendDesc.h"
|
||||
|
||||
TypeHandle MayaBlendDesc::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaBlendDesc::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaBlendDesc::
|
||||
MayaBlendDesc(MFnBlendShapeDeformer deformer, int weight_index) :
|
||||
_deformer(deformer),
|
||||
_weight_index(weight_index)
|
||||
{
|
||||
ostringstream strm;
|
||||
strm << _deformer.name().asChar() << "." << _weight_index;
|
||||
set_name(strm.str());
|
||||
|
||||
_anim = (EggSAnimData *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaBlendDesc::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaBlendDesc::
|
||||
~MayaBlendDesc() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaBlendDesc::set_slider
|
||||
// Access: Public
|
||||
// Description: Moves the Maya slider associated with this blend
|
||||
// shape to the indicated value. This will move all the
|
||||
// affected vertices.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaBlendDesc::
|
||||
set_slider(float value) {
|
||||
_deformer.setWeight(_weight_index, value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaBlendDesc::get_slider
|
||||
// Access: Public
|
||||
// Description: Returns the current position of the Maya slider
|
||||
// associated with this blend shape.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MayaBlendDesc::
|
||||
get_slider() const {
|
||||
return _deformer.weight(_weight_index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaBlendDesc::clear_egg
|
||||
// Access: Private
|
||||
// Description: Clears the egg pointers from this blend desc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaBlendDesc::
|
||||
clear_egg() {
|
||||
_anim = (EggSAnimData *)NULL;
|
||||
}
|
81
pandatool/src/mayaegg/mayaBlendDesc.h
Normal file
81
pandatool/src/mayaegg/mayaBlendDesc.h
Normal file
@ -0,0 +1,81 @@
|
||||
// Filename: mayaBlendDesc.h
|
||||
// Created by: drose (10Feb04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 MAYABLENDDESC_H
|
||||
#define MAYABLENDDESC_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "referenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "namable.h"
|
||||
|
||||
#include "pre_maya_include.h"
|
||||
#include <maya/MFnBlendShapeDeformer.h>
|
||||
#include "post_maya_include.h"
|
||||
|
||||
class EggTable;
|
||||
class EggSAnimData;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MayaBlendDesc
|
||||
// Description : A handle to a Maya blend shape description. This is
|
||||
// just one target of a Maya BlendShape object, and
|
||||
// thus corresponds more or less one-to-one with a
|
||||
// single Egg morph target. (We don't attempt to
|
||||
// support Maya's chained target shapes here; should we
|
||||
// need to later, it would mean breaking each of those
|
||||
// target shapes on the one continuous Maya slider into
|
||||
// a separate MayaBlendDesc object, and synthesizing the
|
||||
// egg slider values appropriately.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class MayaBlendDesc : public ReferenceCount, public Namable {
|
||||
public:
|
||||
MayaBlendDesc(MFnBlendShapeDeformer deformer, int weight_index);
|
||||
~MayaBlendDesc();
|
||||
|
||||
void set_slider(float value);
|
||||
float get_slider() const;
|
||||
|
||||
private:
|
||||
void clear_egg();
|
||||
|
||||
MFnBlendShapeDeformer _deformer;
|
||||
int _weight_index;
|
||||
|
||||
EggSAnimData *_anim;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ReferenceCount::init_type();
|
||||
Namable::init_type();
|
||||
register_type(_type_handle, "MayaBlendDesc",
|
||||
ReferenceCount::get_class_type(),
|
||||
Namable::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class MayaNodeTree;
|
||||
};
|
||||
|
||||
#endif
|
@ -17,8 +17,17 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "mayaNodeDesc.h"
|
||||
#include "mayaNodeTree.h"
|
||||
#include "mayaBlendDesc.h"
|
||||
#include "maya_funcs.h"
|
||||
|
||||
#include "pre_maya_include.h"
|
||||
#include <maya/MFnBlendShapeDeformer.h>
|
||||
#include <maya/MItDependencyGraph.h>
|
||||
#include <maya/MFnNurbsSurface.h>
|
||||
#include <maya/MFnMesh.h>
|
||||
#include "post_maya_include.h"
|
||||
|
||||
TypeHandle MayaNodeDesc::_type_handle;
|
||||
|
||||
// This is a list of the names of Maya connections that count as a
|
||||
@ -41,8 +50,9 @@ static const int num_transform_connections = sizeof(transform_connections) / siz
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaNodeDesc::
|
||||
MayaNodeDesc(MayaNodeDesc *parent, const string &name) :
|
||||
MayaNodeDesc(MayaNodeTree *tree, MayaNodeDesc *parent, const string &name) :
|
||||
Namable(name),
|
||||
_tree(tree),
|
||||
_parent(parent)
|
||||
{
|
||||
_dag_path = (MDagPath *)NULL;
|
||||
@ -73,11 +83,13 @@ MayaNodeDesc::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeDesc::from_dag_path
|
||||
// Access: Public
|
||||
// Description: Indicates an associated between the MayaNodeDesc and
|
||||
// Description: Indicates an association between the MayaNodeDesc and
|
||||
// some Maya instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaNodeDesc::
|
||||
from_dag_path(const MDagPath &dag_path) {
|
||||
MStatus status;
|
||||
|
||||
if (_dag_path == (MDagPath *)NULL) {
|
||||
_dag_path = new MDagPath(dag_path);
|
||||
|
||||
@ -113,6 +125,18 @@ from_dag_path(const MDagPath &dag_path) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dag_path.hasFn(MFn::kNurbsSurface)) {
|
||||
MFnNurbsSurface surface(dag_path, &status);
|
||||
if (status) {
|
||||
check_blend_shapes(surface, "create");
|
||||
}
|
||||
} else if (dag_path.hasFn(MFn::kMesh)) {
|
||||
MFnMesh mesh(dag_path, &status);
|
||||
if (status) {
|
||||
check_blend_shapes(mesh, "inMesh");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,6 +164,30 @@ get_dag_path() const {
|
||||
return *_dag_path;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeDesc::get_num_blend_descs
|
||||
// Access: Public
|
||||
// Description: Returns the number of unique MayaBlendDesc objects
|
||||
// (and hence the number of morph sliders) that affect
|
||||
// the geometry in this node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int MayaNodeDesc::
|
||||
get_num_blend_descs() const {
|
||||
return _blend_descs.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeDesc::get_blend_desc
|
||||
// Access: Public
|
||||
// Description: Returns the nth MayaBlendDesc object that affects the
|
||||
// geometry in this node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaBlendDesc *MayaNodeDesc::
|
||||
get_blend_desc(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_blend_descs.size(), NULL);
|
||||
return _blend_descs[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeDesc::is_joint
|
||||
// Access: Public
|
||||
@ -296,3 +344,63 @@ check_pseudo_joints(bool joint_above) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeDesc::check_blend_shapes
|
||||
// Access: Private
|
||||
// Description: Looks for blend shapes on a NURBS surface or polygon
|
||||
// mesh and records any blend shapes found. This is
|
||||
// similar to MayaToEggConverter::get_vertex_weights(),
|
||||
// which checks for membership of vertices to joints;
|
||||
// Maya stores the blend shape table in the same place.
|
||||
// See the comments in get_vertex_weights() for a more
|
||||
// in-depth description of the iteration process here.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaNodeDesc::
|
||||
check_blend_shapes(const MFnDagNode &node, const string &attrib_name) {
|
||||
MStatus status;
|
||||
|
||||
MObject attr = node.attribute(attrib_name.c_str());
|
||||
|
||||
MPlug history(node.object(), attr);
|
||||
MItDependencyGraph it(history, MFn::kDependencyNode,
|
||||
MItDependencyGraph::kUpstream,
|
||||
MItDependencyGraph::kDepthFirst,
|
||||
MItDependencyGraph::kNodeLevel);
|
||||
|
||||
while (!it.isDone()) {
|
||||
MObject c_node = it.thisNode();
|
||||
|
||||
if (c_node.hasFn(MFn::kBlendShape)) {
|
||||
MFnBlendShapeDeformer blends(c_node, &status);
|
||||
if (!status) {
|
||||
status.perror("MFnBlendShapeDeformer constructor");
|
||||
} else {
|
||||
MObjectArray base_objects;
|
||||
status = blends.getBaseObjects(base_objects);
|
||||
if (!status) {
|
||||
status.perror("MFnBlendShapeDeformer::getBaseObjects");
|
||||
} else {
|
||||
for (unsigned int oi = 0; oi < base_objects.length(); oi++) {
|
||||
MObject base_object = base_objects[oi];
|
||||
|
||||
MIntArray index_list;
|
||||
status = blends.weightIndexList(index_list);
|
||||
if (!status) {
|
||||
status.perror("MFnBlendShapeDeformer::weightIndexList");
|
||||
} else {
|
||||
for (unsigned int i = 0; i < index_list.length(); i++) {
|
||||
int wi = index_list[i];
|
||||
PT(MayaBlendDesc) blend_desc = new MayaBlendDesc(blends, wi);
|
||||
blend_desc = _tree->add_blend_desc(blend_desc);
|
||||
_blend_descs.push_back(blend_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.next();
|
||||
}
|
||||
}
|
||||
|
@ -21,14 +21,17 @@
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "mayaBlendDesc.h"
|
||||
#include "referenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "namable.h"
|
||||
|
||||
#include "pre_maya_include.h"
|
||||
#include <maya/MDagPath.h>
|
||||
#include <maya/MFnDagNode.h>
|
||||
#include "post_maya_include.h"
|
||||
|
||||
class MayaNodeTree;
|
||||
class EggGroup;
|
||||
class EggTable;
|
||||
class EggXfmSAnim;
|
||||
@ -42,18 +45,23 @@ class EggXfmSAnim;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class MayaNodeDesc : public ReferenceCount, public Namable {
|
||||
public:
|
||||
MayaNodeDesc(MayaNodeDesc *parent = NULL, const string &name = string());
|
||||
MayaNodeDesc(MayaNodeTree *tree,
|
||||
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;
|
||||
|
||||
int get_num_blend_descs() const;
|
||||
MayaBlendDesc *get_blend_desc(int n) const;
|
||||
|
||||
bool is_joint() const;
|
||||
bool is_joint_parent() const;
|
||||
|
||||
bool is_tagged() const;
|
||||
|
||||
MayaNodeTree *_tree;
|
||||
MayaNodeDesc *_parent;
|
||||
typedef pvector< PT(MayaNodeDesc) > Children;
|
||||
Children _children;
|
||||
@ -65,6 +73,8 @@ private:
|
||||
void clear_egg();
|
||||
void mark_joint_parent();
|
||||
void check_pseudo_joints(bool joint_above);
|
||||
void check_blend_shapes(const MFnDagNode &node,
|
||||
const string &attrib_name);
|
||||
|
||||
MDagPath *_dag_path;
|
||||
|
||||
@ -72,6 +82,9 @@ private:
|
||||
EggTable *_egg_table;
|
||||
EggXfmSAnim *_anim;
|
||||
|
||||
typedef pvector< PT(MayaBlendDesc) > BlendDescs;
|
||||
BlendDescs _blend_descs;
|
||||
|
||||
enum JointType {
|
||||
JT_none, // Not a joint.
|
||||
JT_joint, // An actual joint in Maya.
|
||||
|
@ -17,12 +17,14 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "mayaNodeTree.h"
|
||||
#include "mayaBlendDesc.h"
|
||||
#include "mayaEggGroupUserData.h"
|
||||
#include "config_mayaegg.h"
|
||||
#include "maya_funcs.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "eggData.h"
|
||||
#include "dcast.h"
|
||||
|
||||
@ -40,11 +42,12 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaNodeTree::
|
||||
MayaNodeTree() {
|
||||
_root = new MayaNodeDesc;
|
||||
_root = new MayaNodeDesc(this);
|
||||
_fps = 0.0;
|
||||
_egg_data = (EggData *)NULL;
|
||||
_egg_root = (EggGroupNode *)NULL;
|
||||
_skeleton_node = (EggGroupNode *)NULL;
|
||||
_morph_node = (EggGroupNode *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -235,11 +238,12 @@ get_node(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaNodeTree::
|
||||
clear() {
|
||||
_root = new MayaNodeDesc;
|
||||
_root = new MayaNodeDesc(this);
|
||||
_fps = 0.0;
|
||||
_egg_data = (EggData *)NULL;
|
||||
_egg_root = (EggGroupNode *)NULL;
|
||||
_skeleton_node = (EggGroupNode *)NULL;
|
||||
_morph_node = (EggGroupNode *)NULL;
|
||||
_nodes_by_path.clear();
|
||||
_nodes.clear();
|
||||
}
|
||||
@ -253,11 +257,17 @@ clear() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaNodeTree::
|
||||
clear_egg(EggData *egg_data, EggGroupNode *egg_root,
|
||||
EggGroupNode *skeleton_node) {
|
||||
EggGroupNode *skeleton_node, EggGroupNode *morph_node) {
|
||||
_root->clear_egg();
|
||||
BlendDescs::iterator bi;
|
||||
for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
|
||||
(*bi)->clear_egg();
|
||||
}
|
||||
|
||||
_egg_data = egg_data;
|
||||
_egg_root = egg_root;
|
||||
_skeleton_node = skeleton_node;
|
||||
_morph_node = morph_node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -428,6 +438,88 @@ get_egg_anim(MayaNodeDesc *node_desc) {
|
||||
return node_desc->_anim;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::get_egg_slider
|
||||
// Access: Public
|
||||
// Description: Returns the anim table corresponding to the slider
|
||||
// for the indicated blend. Creates the table node if it
|
||||
// has not already been created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggSAnimData *MayaNodeTree::
|
||||
get_egg_slider(MayaBlendDesc *blend_desc) {
|
||||
nassertr(_morph_node != (EggGroupNode *)NULL, NULL);
|
||||
|
||||
if (blend_desc->_anim == (EggSAnimData *)NULL) {
|
||||
// We need to make a new anim table.
|
||||
EggSAnimData *egg_anim = new EggSAnimData(blend_desc->get_name());
|
||||
egg_anim->set_fps(_fps);
|
||||
_morph_node->add_child(egg_anim);
|
||||
|
||||
blend_desc->_anim = egg_anim;
|
||||
}
|
||||
|
||||
return blend_desc->_anim;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::add_blend_desc
|
||||
// Access: Public
|
||||
// Description: Adds the indicated MayaBlendDesc object to the list
|
||||
// of blends collected so far. If a MayaBlendDesc
|
||||
// object with the same name is already part of the
|
||||
// tree, the supplied object is discarded and the
|
||||
// previously-added object is returned; otherwise, the
|
||||
// supplied object is added to the tree and the same
|
||||
// object is returned.
|
||||
//
|
||||
// In either case, the return value is the MayaBlendDesc
|
||||
// that should be used henceforth.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaBlendDesc *MayaNodeTree::
|
||||
add_blend_desc(MayaBlendDesc *blend_desc) {
|
||||
BlendDescs::iterator bi = _blend_descs.insert(blend_desc).first;
|
||||
|
||||
return (*bi);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::get_num_blend_descs
|
||||
// Access: Public
|
||||
// Description: Returns the number of unique MayaBlendDesc objects
|
||||
// (and hence the number of morph sliders) discovered in
|
||||
// the tree.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int MayaNodeTree::
|
||||
get_num_blend_descs() const {
|
||||
return _blend_descs.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::get_blend_desc
|
||||
// Access: Public
|
||||
// Description: Returns the nth MayaBlendDesc object discovered in
|
||||
// the tree.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MayaBlendDesc *MayaNodeTree::
|
||||
get_blend_desc(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_blend_descs.size(), NULL);
|
||||
return _blend_descs[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::reset_sliders
|
||||
// Access: Public
|
||||
// Description: Resets all of the sliders associated with all blend
|
||||
// shapes down to 0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaNodeTree::
|
||||
reset_sliders() {
|
||||
BlendDescs::iterator bi;
|
||||
for (bi = _blend_descs.begin(); bi != _blend_descs.end(); ++bi) {
|
||||
(*bi)->set_slider(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MayaNodeTree::r_build_node
|
||||
@ -465,7 +557,7 @@ r_build_node(const string &path) {
|
||||
}
|
||||
|
||||
MayaNodeDesc *parent_node_desc = r_build_node(parent_path);
|
||||
node_desc = new MayaNodeDesc(parent_node_desc, local_name);
|
||||
node_desc = new MayaNodeDesc(this, parent_node_desc, local_name);
|
||||
_nodes.push_back(node_desc);
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,16 @@
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "mayaNodeDesc.h"
|
||||
#include "mayaBlendDesc.h"
|
||||
#include "globPattern.h"
|
||||
#include "indirectCompareNames.h"
|
||||
#include "ordered_vector.h"
|
||||
|
||||
class EggData;
|
||||
class EggGroupNode;
|
||||
class EggTable;
|
||||
class EggXfmSAnim;
|
||||
class EggSAnimData;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MayaNodeTree
|
||||
@ -47,26 +53,38 @@ public:
|
||||
|
||||
void clear();
|
||||
void clear_egg(EggData *egg_data, EggGroupNode *egg_root,
|
||||
EggGroupNode *skeleton_node);
|
||||
EggGroupNode *skeleton_node, EggGroupNode *morph_node);
|
||||
EggGroup *get_egg_group(MayaNodeDesc *node_desc);
|
||||
EggTable *get_egg_table(MayaNodeDesc *node_desc);
|
||||
EggXfmSAnim *get_egg_anim(MayaNodeDesc *node_desc);
|
||||
EggSAnimData *get_egg_slider(MayaBlendDesc *blend_desc);
|
||||
|
||||
MayaBlendDesc *add_blend_desc(MayaBlendDesc *blend_desc);
|
||||
int get_num_blend_descs() const;
|
||||
MayaBlendDesc *get_blend_desc(int n) const;
|
||||
|
||||
void reset_sliders();
|
||||
|
||||
public:
|
||||
PT(MayaNodeDesc) _root;
|
||||
float _fps;
|
||||
|
||||
private:
|
||||
MayaNodeDesc *r_build_node(const string &path);
|
||||
|
||||
EggData *_egg_data;
|
||||
EggGroupNode *_egg_root;
|
||||
EggGroupNode *_skeleton_node;
|
||||
|
||||
MayaNodeDesc *r_build_node(const string &path);
|
||||
EggGroupNode *_morph_node;
|
||||
|
||||
typedef pmap<string, MayaNodeDesc *> NodesByPath;
|
||||
NodesByPath _nodes_by_path;
|
||||
|
||||
typedef pvector<MayaNodeDesc *> Nodes;
|
||||
Nodes _nodes;
|
||||
|
||||
typedef ov_set<PT(MayaBlendDesc), IndirectCompareNames<MayaBlendDesc> > BlendDescs;
|
||||
BlendDescs _blend_descs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "eggTexture.h"
|
||||
#include "eggTextureCollection.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "string_utils.h"
|
||||
#include "dcast.h"
|
||||
|
||||
@ -71,6 +72,7 @@
|
||||
#include <maya/MFnSkinCluster.h>
|
||||
#include <maya/MFnSingleIndexedComponent.h>
|
||||
#include <maya/MFnDoubleIndexedComponent.h>
|
||||
#include <maya/MFnBlendShapeDeformer.h>
|
||||
#include <maya/MItDependencyGraph.h>
|
||||
#include <maya/MDagPathArray.h>
|
||||
#include <maya/MSelectionList.h>
|
||||
@ -503,6 +505,11 @@ convert_char_model() {
|
||||
MGlobal::viewFrame(frame);
|
||||
}
|
||||
|
||||
// It's also important for us to reset all the blend shape sliders
|
||||
// to 0 before we get out the model. Otherwise, the model we
|
||||
// convert will have the current positions of the sliders baked in.
|
||||
_tree.reset_sliders();
|
||||
|
||||
EggGroup *char_node = new EggGroup(_character_name);
|
||||
get_egg_data().add_child(char_node);
|
||||
char_node->set_dart_type(EggGroup::DT_default);
|
||||
@ -529,11 +536,13 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
|
||||
root_table_node->add_child(bundle_node);
|
||||
EggTable *skeleton_node = new EggTable("<skeleton>");
|
||||
bundle_node->add_child(skeleton_node);
|
||||
EggTable *morph_node = new EggTable("morph");
|
||||
bundle_node->add_child(morph_node);
|
||||
|
||||
// Set the frame rate before we start asking for anim tables to be
|
||||
// created.
|
||||
_tree._fps = output_frame_rate;
|
||||
_tree.clear_egg(&get_egg_data(), NULL, skeleton_node);
|
||||
_tree.clear_egg(&get_egg_data(), NULL, skeleton_node, morph_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
|
||||
@ -544,6 +553,7 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
|
||||
PT(EggGroup) tgroup = new EggGroup;
|
||||
|
||||
int num_nodes = _tree.get_num_nodes();
|
||||
int num_sliders = _tree.get_num_blend_descs();
|
||||
int i;
|
||||
|
||||
MTime frame(start_frame, MTime::uiUnit());
|
||||
@ -576,6 +586,16 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_sliders; i++) {
|
||||
MayaBlendDesc *blend_desc = _tree.get_blend_desc(i);
|
||||
if (mayaegg_cat.is_spam()) {
|
||||
mayaegg_cat.spam()
|
||||
<< "slider " << blend_desc->get_name() << "\n";
|
||||
}
|
||||
EggSAnimData *anim = _tree.get_egg_slider(blend_desc);
|
||||
anim->add_data(blend_desc->get_slider());
|
||||
}
|
||||
|
||||
frame += frame_inc;
|
||||
}
|
||||
|
||||
@ -589,6 +609,12 @@ convert_char_chan(double start_frame, double end_frame, double frame_inc,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_sliders; i++) {
|
||||
MayaBlendDesc *blend_desc = _tree.get_blend_desc(i);
|
||||
EggSAnimData *anim = _tree.get_egg_slider(blend_desc);
|
||||
anim->optimize();
|
||||
}
|
||||
|
||||
mayaegg_cat.info(false)
|
||||
<< "\n";
|
||||
|
||||
@ -605,7 +631,7 @@ bool MayaToEggConverter::
|
||||
convert_hierarchy(EggGroupNode *egg_root) {
|
||||
int num_nodes = _tree.get_num_nodes();
|
||||
|
||||
_tree.clear_egg(&get_egg_data(), egg_root, NULL);
|
||||
_tree.clear_egg(&get_egg_data(), egg_root, NULL, NULL);
|
||||
for (int i = 0; i < num_nodes; i++) {
|
||||
MayaNodeDesc *node = _tree.get_node(i);
|
||||
if (!process_model_node(node)) {
|
||||
@ -637,7 +663,7 @@ process_model_node(MayaNodeDesc *node_desc) {
|
||||
MFnDagNode dag_node(dag_path, &status);
|
||||
if (!status) {
|
||||
status.perror("MFnDagNode constructor");
|
||||
mayaegg_cat.error() << dag_path.fullPathName() << "\n";
|
||||
mayaegg_cat.error() << dag_path.fullPathName().asChar() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -701,7 +727,7 @@ process_model_node(MayaNodeDesc *node_desc) {
|
||||
<< ":\n"
|
||||
<< " it appears to have a NURBS surface, but does not.\n";
|
||||
} else {
|
||||
make_nurbs_surface(dag_path, surface, egg_group);
|
||||
make_nurbs_surface(node_desc, dag_path, surface, egg_group);
|
||||
}
|
||||
}
|
||||
|
||||
@ -943,8 +969,8 @@ get_joint_transform(const MDagPath &dag_path, EggGroup *egg_group) {
|
||||
// indicated egg group.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MayaToEggConverter::
|
||||
make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
EggGroup *egg_group) {
|
||||
make_nurbs_surface(MayaNodeDesc *node_desc, const MDagPath &dag_path,
|
||||
MFnNurbsSurface &surface, EggGroup *egg_group) {
|
||||
MStatus status;
|
||||
string name = surface.name().asChar();
|
||||
|
||||
@ -1022,6 +1048,31 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
status.perror("MFnNurbsSurface::getCVs");
|
||||
return;
|
||||
}
|
||||
|
||||
// Also get out all the alternate blend shapes for the surface by
|
||||
// applying each morph slider one at a time.
|
||||
pvector<MPointArray> morph_cvs;
|
||||
if (_animation_convert == AC_model) {
|
||||
int num_sliders = node_desc->get_num_blend_descs();
|
||||
morph_cvs.reserve(num_sliders);
|
||||
for (int i = 0; i < num_sliders; i++) {
|
||||
MayaBlendDesc *blend_desc = node_desc->get_blend_desc(i);
|
||||
|
||||
// Temporarily push the slider up to 1.0 so we can see what the
|
||||
// surface looks like at that value.
|
||||
blend_desc->set_slider(1.0);
|
||||
MPointArray cv_array;
|
||||
status = surface.getCVs(cv_array, MSpace::kWorld);
|
||||
blend_desc->set_slider(0.0);
|
||||
|
||||
if (!status) {
|
||||
status.perror("MFnNurbsSurface::getCVs");
|
||||
return;
|
||||
}
|
||||
morph_cvs.push_back(cv_array);
|
||||
}
|
||||
}
|
||||
|
||||
MDoubleArray u_knot_array, v_knot_array;
|
||||
status = surface.getKnotsInU(u_knot_array);
|
||||
if (!status) {
|
||||
@ -1044,7 +1095,7 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
int v_cvs = surface.numCVsInV();
|
||||
|
||||
// Maya repeats CVS at the end for a periodic surface, and doesn't
|
||||
// count them in the weighted array, below.
|
||||
// count them in the joint weight array, below.
|
||||
int maya_u_cvs = (u_form == MFnNurbsSurface::kPeriodic) ? u_cvs - u_degree : u_cvs;
|
||||
int maya_v_cvs = (v_form == MFnNurbsSurface::kPeriodic) ? v_cvs - v_degree : v_cvs;
|
||||
|
||||
@ -1081,9 +1132,10 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
for (i = 0; i < egg_nurbs->get_num_cvs(); i++) {
|
||||
int ui = egg_nurbs->get_u_index(i);
|
||||
int vi = egg_nurbs->get_v_index(i);
|
||||
int maya_vi = v_cvs * ui + vi;
|
||||
|
||||
double v[4];
|
||||
MStatus status = cv_array[v_cvs * ui + vi].get(v);
|
||||
status = cv_array[maya_vi].get(v);
|
||||
if (!status) {
|
||||
status.perror("MPoint::get");
|
||||
} else {
|
||||
@ -1092,6 +1144,28 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
|
||||
p4d = p4d * vertex_frame_inv;
|
||||
vert->set_pos(p4d);
|
||||
|
||||
// Now generate the morph targets for the vertex.
|
||||
if (!morph_cvs.empty()) {
|
||||
// Morph deltas are given in 3-d space, not in 4-d homogenous
|
||||
// space.
|
||||
LPoint3d p3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
|
||||
|
||||
for (unsigned int si = 0; si < morph_cvs.size(); si++) {
|
||||
MayaBlendDesc *blend_desc = node_desc->get_blend_desc(si);
|
||||
status = morph_cvs[si][maya_vi].get(v);
|
||||
if (!status) {
|
||||
status.perror("MPoint::get");
|
||||
} else {
|
||||
LPoint3d m3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
|
||||
LVector3d delta = m3d - p3d;
|
||||
if (!delta.almost_equal(LVector3d::zero())) {
|
||||
EggMorphVertex dxyz(blend_desc->get_name(), delta);
|
||||
vert->_dxyzs.insert(dxyz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
egg_nurbs->add_vertex(vert);
|
||||
}
|
||||
}
|
||||
@ -1630,6 +1704,16 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
|
||||
pi.next();
|
||||
}
|
||||
|
||||
// TODO: We also need to compute the vertex morphs for the polyset,
|
||||
// based on whatever blend shapes may be present. This should be
|
||||
// similar to the code in make_nurbs_surface(), except that since we
|
||||
// don't have a one-to-one relationship of egg vertices to Maya
|
||||
// vertices, we probably have to get the morphs down here, after we
|
||||
// have added all of the egg vertices. I'll be happy to make this
|
||||
// work as soon as someone gives me a sample Maya file that
|
||||
// demonstrates blend shapes with polygon meshes.
|
||||
|
||||
|
||||
// Now that we've added all the polygons (and created all the
|
||||
// vertices), go back through the vertex pool and set up the
|
||||
// appropriate joint membership for each of the vertices.
|
||||
|
@ -104,7 +104,8 @@ private:
|
||||
// I ran into core dumps trying to pass around a MFnMesh object by
|
||||
// value. From now on, all MFn* objects will be passed around by
|
||||
// reference.
|
||||
void make_nurbs_surface(const MDagPath &dag_path,
|
||||
void make_nurbs_surface(MayaNodeDesc *node_desc,
|
||||
const MDagPath &dag_path,
|
||||
MFnNurbsSurface &surface,
|
||||
EggGroup *group);
|
||||
EggNurbsCurve *make_trim_curve(const MFnNurbsCurve &curve,
|
||||
|
Loading…
x
Reference in New Issue
Block a user