00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "mayaNodeDesc.h"
00016 #include "mayaNodeTree.h"
00017 #include "mayaBlendDesc.h"
00018 #include "mayaToEggConverter.h"
00019 #include "maya_funcs.h"
00020 #include "eggGroup.h"
00021 #include "config_mayaegg.h"
00022
00023 #include "pre_maya_include.h"
00024 #include <maya/MFnBlendShapeDeformer.h>
00025 #include <maya/MItDependencyGraph.h>
00026 #include <maya/MFnNurbsSurface.h>
00027 #include <maya/MFnMesh.h>
00028 #include "post_maya_include.h"
00029
00030 TypeHandle MayaNodeDesc::_type_handle;
00031
00032
00033
00034 static const char *transform_connections[] = {
00035 "translate",
00036 "translateX",
00037 "translateY",
00038 "translateZ",
00039 "rotate",
00040 "rotateX",
00041 "rotateY",
00042 "rotateZ",
00043 };
00044 static const int num_transform_connections = sizeof(transform_connections) / sizeof(const char *);
00045
00046
00047
00048
00049
00050
00051 MayaNodeDesc::
00052 MayaNodeDesc(MayaNodeTree *tree, MayaNodeDesc *parent, const string &name) :
00053 Namable(name),
00054 _tree(tree),
00055 _parent(parent)
00056 {
00057 _dag_path = (MDagPath *)NULL;
00058 _egg_group = (EggGroup *)NULL;
00059 _egg_table = (EggTable *)NULL;
00060 _anim = (EggXfmSAnim *)NULL;
00061 _joint_type = JT_none;
00062 _is_lod = false;
00063 _tagged = false;
00064 _joint_tagged = false;
00065
00066
00067 if (_parent != (MayaNodeDesc *)NULL) {
00068 _parent->_children.push_back(this);
00069 }
00070 }
00071
00072
00073
00074
00075
00076
00077 MayaNodeDesc::
00078 ~MayaNodeDesc() {
00079 if (_dag_path != (MDagPath *)NULL) {
00080 delete _dag_path;
00081 }
00082 }
00083
00084
00085
00086
00087
00088
00089
00090 void MayaNodeDesc::
00091 from_dag_path(const MDagPath &dag_path, MayaToEggConverter *converter) {
00092 MStatus status;
00093
00094 if (_dag_path == (MDagPath *)NULL) {
00095 _dag_path = new MDagPath(dag_path);
00096
00097 string name;
00098 MFnDagNode dag_node(dag_path, &status);
00099 if (!status) {
00100 status.perror("MFnDagNode constructor");
00101 } else {
00102 name = dag_node.name().asChar();
00103 }
00104
00105 if (_dag_path->hasFn(MFn::kJoint) || converter->force_joint(name)) {
00106
00107
00108 _joint_type = JT_joint;
00109 if (_parent != (MayaNodeDesc *)NULL) {
00110 _parent->mark_joint_parent();
00111 }
00112
00113 } else {
00114
00115
00116
00117 bool transform_connected = false;
00118
00119 MStatus status;
00120 MObject node = dag_path.node(&status);
00121 if (status) {
00122 for (int i = 0;
00123 i < num_transform_connections && !transform_connected;
00124 i++) {
00125 if (is_connected(node, transform_connections[i])) {
00126 transform_connected = true;
00127 }
00128 }
00129 }
00130
00131 if (transform_connected) {
00132 _joint_type = JT_joint;
00133 if (_parent != (MayaNodeDesc *)NULL) {
00134 _parent->mark_joint_parent();
00135 }
00136 }
00137 }
00138
00139 if (dag_path.hasFn(MFn::kNurbsSurface)) {
00140 MFnNurbsSurface surface(dag_path, &status);
00141 if (status) {
00142 check_blend_shapes(surface, "create");
00143 }
00144 } else if (dag_path.hasFn(MFn::kMesh)) {
00145 MFnMesh mesh(dag_path, &status);
00146 if (status) {
00147 check_blend_shapes(mesh, "inMesh");
00148 }
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 bool MayaNodeDesc::
00160 has_dag_path() const {
00161 return (_dag_path != (MDagPath *)NULL);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 const MDagPath &MayaNodeDesc::
00172 get_dag_path() const {
00173 nassertr(_dag_path != (MDagPath *)NULL, *_dag_path);
00174 return *_dag_path;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 int MayaNodeDesc::
00185 get_num_blend_descs() const {
00186 return _blend_descs.size();
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 MayaBlendDesc *MayaNodeDesc::
00196 get_blend_desc(int n) const {
00197 nassertr(n >= 0 && n < (int)_blend_descs.size(), NULL);
00198 return _blend_descs[n];
00199 }
00200
00201
00202
00203
00204
00205
00206
00207 bool MayaNodeDesc::
00208 is_joint() const {
00209
00210 return _joint_tagged && (_joint_type == JT_joint || _joint_type == JT_pseudo_joint);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 bool MayaNodeDesc::
00220 is_joint_parent() const {
00221 return _joint_type == JT_joint_parent;
00222
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 bool MayaNodeDesc::
00232 is_joint_tagged() const {
00233 return _joint_tagged;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242 void MayaNodeDesc::
00243 tag_joint() {
00244 _joint_tagged = true;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253 void MayaNodeDesc::
00254 tag_joint_recursively() {
00255 _joint_tagged = true;
00256
00257 Children::const_iterator ci;
00258 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00259 MayaNodeDesc *child = (*ci);
00260 child->tag_joint_recursively();
00261 }
00262 }
00263
00264
00265
00266
00267
00268
00269
00270 bool MayaNodeDesc::
00271 is_tagged() const {
00272 return _tagged;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 void MayaNodeDesc::
00282 tag() {
00283 _tagged = true;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 void MayaNodeDesc::
00293 untag() {
00294 _tagged = false;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303 void MayaNodeDesc::
00304 tag_recursively() {
00305 _tagged = true;
00306
00307 Children::const_iterator ci;
00308 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00309 MayaNodeDesc *child = (*ci);
00310 child->tag_recursively();
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 void MayaNodeDesc::
00321 untag_recursively() {
00322 _tagged = false;
00323
00324 Children::const_iterator ci;
00325 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00326 MayaNodeDesc *child = (*ci);
00327 child->untag_recursively();
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 bool MayaNodeDesc::
00338 has_object_type(string object_type) const {
00339 bool ret = false;
00340 if ((_egg_group != (EggGroup*) NULL)
00341 && _egg_group->has_object_type(object_type)) {
00342 return true;
00343 }
00344 if (_parent != (MayaNodeDesc *)NULL) {
00345 ret |= _parent->has_object_type(object_type);
00346 }
00347 return ret;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 void MayaNodeDesc::
00357 clear_egg() {
00358 _egg_group = (EggGroup *)NULL;
00359 _egg_table = (EggTable *)NULL;
00360 _anim = (EggXfmSAnim *)NULL;
00361
00362 Children::const_iterator ci;
00363 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00364 MayaNodeDesc *child = (*ci);
00365 child->clear_egg();
00366 }
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 void MayaNodeDesc::
00376 mark_joint_parent() {
00377 if (_joint_type == JT_none) {
00378 _joint_type = JT_joint_parent;
00379 if (_parent != (MayaNodeDesc *)NULL) {
00380 _parent->mark_joint_parent();
00381 }
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 void MayaNodeDesc::
00394 check_pseudo_joints(bool joint_above) {
00395 static PN_uint32 space_count = 0;
00396 string space;
00397 for (PN_uint32 idx=0; idx<space_count; ++idx) {
00398 space.append(" ");
00399 }
00400 if (mayaegg_cat.is_spam()) {
00401 mayaegg_cat.spam() << "cpj:" << space << get_name() << " joint_type: " << _joint_type << endl;
00402 }
00403 if (_joint_type == JT_joint_parent && joint_above) {
00404
00405
00406
00407 _joint_type = JT_pseudo_joint;
00408 }
00409
00410 if (_joint_type == JT_joint) {
00411
00412
00413 joint_above = true;
00414 }
00415
00416
00417
00418 if (_joint_type != JT_none) {
00419
00420 bool any_joints = false;
00421 Children::const_iterator ci;
00422 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00423 MayaNodeDesc *child = (*ci);
00424 if (mayaegg_cat.is_spam()) {
00425 ++space_count;
00426 }
00427 child->check_pseudo_joints(joint_above);
00428
00429 if (child->_joint_type == JT_joint || child->_joint_type == JT_pseudo_joint) {
00430 any_joints = true;
00431 }
00432 }
00433
00434
00435
00436 if (any_joints) {
00437 bool all_joints = true;
00438 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00439 MayaNodeDesc *child = (*ci);
00440 MStatus status;
00441 MFnDagNode dag_node(child->get_dag_path(), &status);
00442 if (!status) {
00443 status.perror("MFnDagNode constructor");
00444 }
00445 string type_name = dag_node.typeName().asChar();
00446 if (child->_joint_type == JT_joint_parent) {
00447 child->_joint_type = JT_pseudo_joint;
00448 } else if (child->_joint_type == JT_none) {
00449 if (mayaegg_cat.is_spam()) {
00450 mayaegg_cat.spam() << "cpj: " << space << "jt_none for " << child->get_name() << endl;
00451 }
00452 if (type_name.find("transform") == string::npos) {
00453 if (mayaegg_cat.is_spam()) {
00454 mayaegg_cat.spam() << "cpj: " << space << "all_joints false for " << get_name() << endl;
00455 }
00456 all_joints = false;
00457 }
00458 }
00459 }
00460
00461 if (all_joints) {
00462
00463 if (_joint_type == JT_joint_parent) {
00464 if (!get_name().empty()) {
00465 _joint_type = JT_pseudo_joint;
00466 }
00467 }
00468 }
00469 }
00470 }
00471 if (mayaegg_cat.is_spam()) {
00472 if (space_count > 0)
00473 --space_count;
00474 }
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 void MayaNodeDesc::
00489 check_blend_shapes(const MFnDagNode &node, const string &attrib_name) {
00490 MStatus status;
00491
00492 MObject attr = node.attribute(attrib_name.c_str());
00493
00494 MPlug history(node.object(), attr);
00495 MItDependencyGraph it(history, MFn::kDependencyNode,
00496 MItDependencyGraph::kUpstream,
00497 MItDependencyGraph::kDepthFirst,
00498 MItDependencyGraph::kNodeLevel);
00499
00500 while (!it.isDone()) {
00501 MObject c_node = it.thisNode();
00502
00503 if (c_node.hasFn(MFn::kBlendShape)) {
00504 MFnBlendShapeDeformer blends(c_node, &status);
00505 if (!status) {
00506 status.perror("MFnBlendShapeDeformer constructor");
00507
00508 } else {
00509
00510
00511
00512 MPlug plug = blends.findPlug("pb");
00513 bool is_parallel_blender;
00514 status = plug.getValue(is_parallel_blender);
00515 if (!status) {
00516 status.perror("Could not get value of pb plug.");
00517 is_parallel_blender = false;
00518 }
00519
00520 if (is_parallel_blender ||
00521 _tree->ignore_slider(blends.name().asChar())) {
00522 _tree->report_ignored_slider(blends.name().asChar());
00523
00524 } else {
00525 MObjectArray base_objects;
00526 status = blends.getBaseObjects(base_objects);
00527 if (!status) {
00528 status.perror("MFnBlendShapeDeformer::getBaseObjects");
00529 } else {
00530 for (unsigned int oi = 0; oi < base_objects.length(); oi++) {
00531 MObject base_object = base_objects[oi];
00532
00533 MIntArray index_list;
00534 status = blends.weightIndexList(index_list);
00535 if (!status) {
00536 status.perror("MFnBlendShapeDeformer::weightIndexList");
00537 } else {
00538 for (unsigned int i = 0; i < index_list.length(); i++) {
00539 int wi = index_list[i];
00540 PT(MayaBlendDesc) blend_desc = new MayaBlendDesc(blends, wi);
00541 blend_desc = _tree->add_blend_desc(blend_desc);
00542 _blend_descs.push_back(blend_desc);
00543 }
00544 }
00545 }
00546 }
00547 }
00548 }
00549 }
00550
00551 it.next();
00552 }
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 void MayaNodeDesc::
00566 check_lods() {
00567
00568
00569 Children::iterator ci;
00570 for (ci = _children.begin(); ci != _children.end(); ++ci) {
00571 MayaNodeDesc *child = (*ci);
00572 child->check_lods();
00573 }
00574
00575
00576 if (_dag_path != (MDagPath *)NULL &&
00577 _dag_path->hasFn(MFn::kLodGroup)) {
00578
00579
00580 MStatus status;
00581 MFnDagNode dag_node(*_dag_path, &status);
00582 if (!status) {
00583 status.perror("Couldn't get node from dag path for lodGroup");
00584 return;
00585 }
00586
00587 MPlug plug = dag_node.findPlug("threshold", &status);
00588 if (!status) {
00589 status.perror("Couldn't get threshold attributes on lodGroup");
00590 return;
00591 }
00592
00593
00594
00595 unsigned int num_elements = plug.numElements();
00596 unsigned int num_children = _children.size();
00597 if (num_elements + 1 != num_children) {
00598 mayaegg_cat.warning()
00599 << "Node " << get_name() << " has " << num_elements
00600 << " LOD entries, but " << num_children << " children.\n";
00601 }
00602
00603
00604
00605
00606
00607
00608 double switch_out = 0.0;
00609 unsigned int i = 0;
00610 while (i < num_elements && i < num_children) {
00611 MPlug element = plug.elementByLogicalIndex(i);
00612 MayaNodeDesc *child = _children[i];
00613
00614 double switch_in;
00615 status = element.getValue(switch_in);
00616 if (!status) {
00617 status.perror("Couldn't get double value from threshold.");
00618 return;
00619 }
00620
00621 child->_is_lod = true;
00622 child->_switch_in = switch_in;
00623 child->_switch_out = switch_out;
00624
00625 switch_out = switch_in;
00626 ++i;
00627 }
00628
00629 while (i < num_children) {
00630
00631
00632
00633 MayaNodeDesc *child = _children[i];
00634 child->_is_lod = true;
00635 child->_switch_in = switch_out * 4.0;
00636 child->_switch_out = switch_out;
00637
00638 ++i;
00639 }
00640 }
00641 }