00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mayaToEggConverter.h"
00020 #include "mayaShader.h"
00021 #include "maya_funcs.h"
00022 #include "config_mayaegg.h"
00023
00024 #include "eggData.h"
00025 #include "eggGroup.h"
00026 #include "eggTable.h"
00027 #include "eggVertex.h"
00028 #include "eggVertexPool.h"
00029 #include "eggNurbsSurface.h"
00030 #include "eggNurbsCurve.h"
00031 #include "eggPolygon.h"
00032 #include "eggPrimitive.h"
00033 #include "eggTexture.h"
00034 #include "eggTextureCollection.h"
00035 #include "eggXfmSAnim.h"
00036 #include "string_utils.h"
00037 #include "dcast.h"
00038
00039 #include "pre_maya_include.h"
00040 #include <maya/MArgList.h>
00041 #include <maya/MColor.h>
00042 #include <maya/MDagPath.h>
00043 #include <maya/MFnCamera.h>
00044 #include <maya/MFnDagNode.h>
00045 #include <maya/MFnTransform.h>
00046 #include <maya/MFnLight.h>
00047 #include <maya/MFnNurbsSurface.h>
00048 #include <maya/MFnNurbsCurve.h>
00049 #include <maya/MFnMesh.h>
00050 #include <maya/MFnMeshData.h>
00051 #include <maya/MItMeshPolygon.h>
00052 #include <maya/MFnPlugin.h>
00053 #include <maya/MItDag.h>
00054 #include <maya/MLibrary.h>
00055 #include <maya/MMatrix.h>
00056 #include <maya/MObject.h>
00057 #include <maya/MPoint.h>
00058 #include <maya/MPointArray.h>
00059 #include <maya/MDoubleArray.h>
00060 #include <maya/MIntArray.h>
00061 #include <maya/MPxCommand.h>
00062 #include <maya/MStatus.h>
00063 #include <maya/MString.h>
00064 #include <maya/MTransformationMatrix.h>
00065 #include <maya/MVector.h>
00066 #include <maya/MTesselationParams.h>
00067 #include <maya/MAnimControl.h>
00068 #include <maya/MGlobal.h>
00069 #include <maya/MAnimUtil.h>
00070 #include <maya/MFnSkinCluster.h>
00071 #include <maya/MFnSingleIndexedComponent.h>
00072 #include <maya/MItDependencyGraph.h>
00073 #include <maya/MDagPathArray.h>
00074 #include <maya/MSelectionList.h>
00075 #include "post_maya_include.h"
00076
00077
00078
00079
00080
00081
00082 MayaToEggConverter::
00083 MayaToEggConverter(const string &program_name) :
00084 _program_name(program_name)
00085 {
00086 _from_selection = false;
00087 _polygon_output = false;
00088 _polygon_tolerance = 0.01;
00089 _transform_type = TT_model;
00090 }
00091
00092
00093
00094
00095
00096
00097 MayaToEggConverter::
00098 MayaToEggConverter(const MayaToEggConverter ©) :
00099 _maya(copy._maya)
00100 {
00101 }
00102
00103
00104
00105
00106
00107
00108 MayaToEggConverter::
00109 ~MayaToEggConverter() {
00110 close_api();
00111 }
00112
00113
00114
00115
00116
00117
00118 SomethingToEggConverter *MayaToEggConverter::
00119 make_copy() {
00120 return new MayaToEggConverter(*this);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 string MayaToEggConverter::
00130 get_name() const {
00131 return "Maya";
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 string MayaToEggConverter::
00141 get_extension() const {
00142 return "mb";
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 bool MayaToEggConverter::
00157 convert_file(const Filename &filename) {
00158 if (!open_api()) {
00159 mayaegg_cat.error()
00160 << "Maya is not available.\n";
00161 return false;
00162 }
00163 if (!_maya->read(filename)) {
00164 mayaegg_cat.error()
00165 << "Unable to read " << filename << "\n";
00166 return false;
00167 }
00168
00169 if (_character_name.empty()) {
00170 _character_name = filename.get_basename_wo_extension();
00171 }
00172
00173 return convert_maya(false);
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 bool MayaToEggConverter::
00186 convert_maya(bool from_selection) {
00187 _from_selection = from_selection;
00188 _textures.clear();
00189 _shaders.clear();
00190 _groups.clear();
00191 _tables.clear();
00192
00193 if (!open_api()) {
00194 mayaegg_cat.error()
00195 << "Maya is not available.\n";
00196 return false;
00197 }
00198
00199 if (_egg_data->get_coordinate_system() == CS_default) {
00200 _egg_data->set_coordinate_system(_maya->get_coordinate_system());
00201 }
00202
00203 mayaegg_cat.info()
00204 << "Converting from Maya.\n";
00205
00206
00207 double start_frame, end_frame, frame_inc, input_frame_rate, output_frame_rate;
00208 if (has_start_frame()) {
00209 start_frame = get_start_frame();
00210 } else {
00211 start_frame = MAnimControl::minTime().value();
00212 }
00213 if (has_end_frame()) {
00214 end_frame = get_end_frame();
00215 } else {
00216 end_frame = MAnimControl::maxTime().value();
00217 }
00218 if (has_frame_inc()) {
00219 frame_inc = get_frame_inc();
00220 } else {
00221 frame_inc = 1.0;
00222 }
00223 if (has_input_frame_rate()) {
00224 input_frame_rate = get_input_frame_rate();
00225 } else {
00226 MTime time(1.0, MTime::kSeconds);
00227 input_frame_rate = time.as(MTime::uiUnit());
00228 }
00229 if (has_output_frame_rate()) {
00230 output_frame_rate = get_output_frame_rate();
00231 } else {
00232 output_frame_rate = input_frame_rate;
00233 }
00234
00235 bool all_ok = true;
00236
00237 switch (get_animation_convert()) {
00238 case AC_pose:
00239
00240 mayaegg_cat.info(false)
00241 << "frame " << start_frame << "\n";
00242 MGlobal::viewFrame(MTime(start_frame, MTime::uiUnit()));
00243
00244
00245 case AC_none:
00246
00247 all_ok = convert_hierarchy(&get_egg_data());
00248 break;
00249
00250 case AC_flip:
00251
00252
00253 all_ok = convert_flip(start_frame, end_frame, frame_inc,
00254 output_frame_rate);
00255 break;
00256
00257 case AC_model:
00258
00259
00260 all_ok = convert_char_model();
00261 break;
00262
00263 case AC_chan:
00264
00265 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
00266 output_frame_rate);
00267 break;
00268
00269 case AC_both:
00270
00271 _animation_convert = AC_model;
00272 if (!convert_char_model()) {
00273 all_ok = false;
00274 }
00275 _animation_convert = AC_chan;
00276 if (!convert_char_chan(start_frame, end_frame, frame_inc,
00277 output_frame_rate)) {
00278 all_ok = false;
00279 }
00280 break;
00281 };
00282
00283 reparent_decals(&get_egg_data());
00284
00285 if (all_ok) {
00286 mayaegg_cat.info()
00287 << "Converted, no errors.\n";
00288 } else {
00289 mayaegg_cat.info()
00290 << "Errors encountered in conversion.\n";
00291 }
00292
00293 return all_ok;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 bool MayaToEggConverter::
00304 open_api() {
00305 if (_maya == (MayaApi *)NULL || !_maya->is_valid()) {
00306 _maya = MayaApi::open_api(_program_name);
00307 }
00308 return _maya->is_valid();
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318 void MayaToEggConverter::
00319 close_api() {
00320
00321 _shaders.clear();
00322 _maya.clear();
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 bool MayaToEggConverter::
00337 convert_flip(double start_frame, double end_frame, double frame_inc,
00338 double output_frame_rate) {
00339 bool all_ok = true;
00340
00341 EggGroup *sequence_node = new EggGroup(_character_name);
00342 get_egg_data().add_child(sequence_node);
00343 sequence_node->set_switch_flag(true);
00344 sequence_node->set_switch_fps(output_frame_rate / frame_inc);
00345
00346 MTime frame(start_frame, MTime::uiUnit());
00347 MTime frame_stop(end_frame, MTime::uiUnit());
00348 while (frame <= frame_stop) {
00349 mayaegg_cat.info(false)
00350 << "frame " << frame.value() << "\n";
00351 ostringstream name_strm;
00352 name_strm << "frame" << frame.value();
00353 EggGroup *frame_root = new EggGroup(name_strm.str());
00354 sequence_node->add_child(frame_root);
00355
00356 MGlobal::viewFrame(frame);
00357 if (!convert_hierarchy(frame_root)) {
00358 all_ok = false;
00359 }
00360 _groups.clear();
00361
00362 frame += frame_inc;
00363 }
00364
00365 return all_ok;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 bool MayaToEggConverter::
00375 convert_char_model() {
00376 if (has_neutral_frame()) {
00377 MTime frame(get_neutral_frame(), MTime::uiUnit());
00378 mayaegg_cat.info(false)
00379 << "neutral frame " << frame.value() << "\n";
00380 MGlobal::viewFrame(frame);
00381 }
00382
00383 EggGroup *char_node = new EggGroup(_character_name);
00384 get_egg_data().add_child(char_node);
00385 char_node->set_dart_type(EggGroup::DT_default);
00386
00387 return convert_hierarchy(char_node);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397 bool MayaToEggConverter::
00398 convert_char_chan(double start_frame, double end_frame, double frame_inc,
00399 double output_frame_rate) {
00400 MStatus status;
00401
00402 EggTable *root_table_node = new EggTable();
00403 get_egg_data().add_child(root_table_node);
00404 EggTable *bundle_node = new EggTable(_character_name);
00405 bundle_node->set_table_type(EggTable::TT_bundle);
00406 root_table_node->add_child(bundle_node);
00407 EggTable *skeleton_node = new EggTable("<skeleton>");
00408 bundle_node->add_child(skeleton_node);
00409
00410
00411
00412 MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
00413 if (!status) {
00414 status.perror("MItDag constructor");
00415 return false;
00416 }
00417 bool all_ok = true;
00418 while (!dag_iterator.isDone()) {
00419 MDagPath dag_path;
00420 status = dag_iterator.getPath(dag_path);
00421 if (!status) {
00422 status.perror("MItDag::getPath");
00423 } else {
00424 if (!process_chan_node(dag_path, skeleton_node)) {
00425 all_ok = false;
00426 }
00427 }
00428
00429 dag_iterator.next();
00430 }
00431
00432
00433
00434 double fps = output_frame_rate / frame_inc;
00435 Tables::iterator ti;
00436 for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
00437 JointAnim *joint_anim = (*ti).second;
00438 nassertr(joint_anim != (JointAnim *)NULL &&
00439 joint_anim->_anim != (EggXfmSAnim *)NULL, false);
00440 joint_anim->_anim->set_fps(fps);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 PT(EggGroup) tgroup = new EggGroup;
00450
00451 MTime frame(start_frame, MTime::uiUnit());
00452 MTime frame_stop(end_frame, MTime::uiUnit());
00453 while (frame <= frame_stop) {
00454 if (mayaegg_cat.is_debug()) {
00455 mayaegg_cat.debug(false)
00456 << "frame " << frame.value() << "\n";
00457 } else {
00458 mayaegg_cat.info(false)
00459 << ".";
00460 }
00461 MGlobal::viewFrame(frame);
00462
00463 for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
00464 JointAnim *joint_anim = (*ti).second;
00465 get_transform(joint_anim->_dag_path, tgroup);
00466 joint_anim->_anim->add_data(tgroup->get_transform());
00467 }
00468
00469 frame += frame_inc;
00470 }
00471 mayaegg_cat.info(false)
00472 << "\n";
00473
00474
00475
00476 for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
00477 JointAnim *joint_anim = (*ti).second;
00478 delete joint_anim;
00479 }
00480 _tables.clear();
00481
00482 return all_ok;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492 bool MayaToEggConverter::
00493 convert_hierarchy(EggGroupNode *egg_root) {
00494 MStatus status;
00495
00496 MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
00497 if (!status) {
00498 status.perror("MItDag constructor");
00499 return false;
00500 }
00501
00502 if (_from_selection) {
00503
00504 MSelectionList selection;
00505 status = MGlobal::getActiveSelectionList(selection);
00506 if (!status) {
00507 status.perror("MGlobal::getActiveSelectionList");
00508 return false;
00509 }
00510
00511
00512
00513 if (!selection.isEmpty()) {
00514 bool all_ok = true;
00515 unsigned int length = selection.length();
00516 for (unsigned int i = 0; i < length; i++) {
00517 MDagPath root_path;
00518 status = selection.getDagPath(i, root_path);
00519 if (!status) {
00520 status.perror("MSelectionList::getDagPath");
00521 } else {
00522
00523
00524 dag_iterator.reset(root_path);
00525 while (!dag_iterator.isDone()) {
00526 MDagPath dag_path;
00527 status = dag_iterator.getPath(dag_path);
00528 if (!status) {
00529 status.perror("MItDag::getPath");
00530 } else {
00531 if (!process_model_node(dag_path, egg_root)) {
00532 all_ok = false;
00533 }
00534 }
00535
00536 dag_iterator.next();
00537 }
00538 }
00539 }
00540 return all_ok;
00541
00542 } else {
00543 mayaegg_cat.info()
00544 << "Selection list is empty.\n";
00545
00546 }
00547 }
00548
00549
00550
00551
00552
00553
00554
00555 bool all_ok = true;
00556 while (!dag_iterator.isDone()) {
00557 MDagPath dag_path;
00558 status = dag_iterator.getPath(dag_path);
00559 if (!status) {
00560 status.perror("MItDag::getPath");
00561 } else {
00562 if (!process_model_node(dag_path, egg_root)) {
00563 all_ok = false;
00564 }
00565 }
00566
00567 dag_iterator.next();
00568 }
00569
00570 return all_ok;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 bool MayaToEggConverter::
00582 process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
00583 MStatus status;
00584 MFnDagNode dag_node(dag_path, &status);
00585 if (!status) {
00586 status.perror("MFnDagNode constructor");
00587 return false;
00588 }
00589
00590 if (mayaegg_cat.is_debug()) {
00591 mayaegg_cat.debug()
00592 << dag_path.fullPathName().asChar() << ": " << dag_node.typeName();
00593
00594 if (MAnimUtil::isAnimated(dag_path)) {
00595 mayaegg_cat.debug(false)
00596 << " (animated)";
00597 }
00598
00599 mayaegg_cat.debug(false) << "\n";
00600 }
00601
00602 if (dag_node.inUnderWorld()) {
00603 if (mayaegg_cat.is_debug()) {
00604 mayaegg_cat.debug()
00605 << "Ignoring underworld node " << dag_path.fullPathName().asChar()
00606 << "\n";
00607 }
00608
00609 } else if (dag_node.isIntermediateObject()) {
00610 if (mayaegg_cat.is_debug()) {
00611 mayaegg_cat.debug()
00612 << "Ignoring intermediate object " << dag_path.fullPathName().asChar()
00613 << "\n";
00614 }
00615
00616 } else if (dag_path.hasFn(MFn::kCamera)) {
00617 if (mayaegg_cat.is_debug()) {
00618 mayaegg_cat.debug()
00619 << "Ignoring camera node " << dag_path.fullPathName().asChar()
00620 << "\n";
00621 }
00622
00623 } else if (dag_path.hasFn(MFn::kLight)) {
00624 if (mayaegg_cat.is_debug()) {
00625 mayaegg_cat.debug()
00626 << "Ignoring light node " << dag_path.fullPathName().asChar()
00627 << "\n";
00628 }
00629
00630 } else if (dag_path.hasFn(MFn::kJoint)) {
00631
00632
00633
00634
00635 if (_animation_convert == AC_model) {
00636 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00637
00638 if (egg_group != (EggGroup *)NULL) {
00639 egg_group->set_group_type(EggGroup::GT_joint);
00640 get_transform(dag_path, egg_group);
00641 }
00642 }
00643
00644 } else if (dag_path.hasFn(MFn::kNurbsSurface)) {
00645 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00646
00647 if (egg_group == (EggGroup *)NULL) {
00648 mayaegg_cat.error()
00649 << "Cannot determine group node.\n";
00650 return false;
00651
00652 } else {
00653 if (_animation_convert != AC_model) {
00654 get_transform(dag_path, egg_group);
00655 }
00656
00657 MFnNurbsSurface surface(dag_path, &status);
00658 if (!status) {
00659 mayaegg_cat.info()
00660 << "Error in node " << dag_path.fullPathName().asChar()
00661 << ":\n"
00662 << " it appears to have a NURBS surface, but does not.\n";
00663 } else {
00664 make_nurbs_surface(dag_path, surface, egg_group, egg_root);
00665 }
00666 }
00667
00668 } else if (dag_path.hasFn(MFn::kNurbsCurve)) {
00669
00670
00671
00672 if (_animation_convert != AC_model) {
00673 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00674
00675 if (egg_group == (EggGroup *)NULL) {
00676 mayaegg_cat.error()
00677 << "Cannot determine group node.\n";
00678
00679 } else {
00680 get_transform(dag_path, egg_group);
00681
00682 MFnNurbsCurve curve(dag_path, &status);
00683 if (!status) {
00684 mayaegg_cat.info()
00685 << "Error in node " << dag_path.fullPathName().asChar() << ":\n"
00686 << " it appears to have a NURBS curve, but does not.\n";
00687 } else {
00688 make_nurbs_curve(dag_path, curve, egg_group, egg_root);
00689 }
00690 }
00691 }
00692
00693 } else if (dag_path.hasFn(MFn::kMesh)) {
00694 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00695
00696 if (egg_group == (EggGroup *)NULL) {
00697 mayaegg_cat.error()
00698 << "Cannot determine group node.\n";
00699 return false;
00700
00701 } else {
00702 if (_animation_convert != AC_model) {
00703 get_transform(dag_path, egg_group);
00704 }
00705
00706 MFnMesh mesh(dag_path, &status);
00707 if (!status) {
00708 mayaegg_cat.info()
00709 << "Error in node " << dag_path.fullPathName().asChar() << ":\n"
00710 << " it appears to have a polygon mesh, but does not.\n";
00711 } else {
00712 make_polyset(dag_path, mesh, egg_group, egg_root);
00713 }
00714 }
00715
00716 } else if (dag_path.hasFn(MFn::kLocator)) {
00717 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00718
00719 if (egg_group == (EggGroup *)NULL) {
00720 mayaegg_cat.error()
00721 << "Cannot determine group node.\n";
00722 return false;
00723
00724 } else {
00725 if (_animation_convert != AC_model) {
00726 get_transform(dag_path, egg_group);
00727 }
00728 make_locator(dag_path, dag_node, egg_group, egg_root);
00729 }
00730
00731 } else {
00732
00733 EggGroup *egg_group = get_egg_group(dag_path, egg_root);
00734
00735 if (egg_group != (EggGroup *)NULL) {
00736 if (_animation_convert != AC_model) {
00737 get_transform(dag_path, egg_group);
00738 }
00739 }
00740 }
00741
00742 return true;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 bool MayaToEggConverter::
00754 process_chan_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
00755 MStatus status;
00756 MFnDagNode dag_node(dag_path, &status);
00757 if (!status) {
00758 status.perror("MFnDagNode constructor");
00759 return false;
00760 }
00761
00762 if (dag_path.hasFn(MFn::kJoint)) {
00763
00764
00765 if (mayaegg_cat.is_debug()) {
00766 mayaegg_cat.debug()
00767 << dag_path.fullPathName().asChar() << ": " << dag_node.typeName();
00768
00769 if (MAnimUtil::isAnimated(dag_path)) {
00770 mayaegg_cat.debug(false)
00771 << " (animated)";
00772 }
00773
00774 mayaegg_cat.debug(false) << "\n";
00775 }
00776
00777 get_egg_table(dag_path, egg_root);
00778 }
00779
00780 return true;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789 void MayaToEggConverter::
00790 get_transform(const MDagPath &dag_path, EggGroup *egg_group) {
00791 MStatus status;
00792 MObject transformNode = dag_path.transform(&status);
00793 if (!status && status.statusCode() == MStatus::kInvalidParameter) {
00794
00795 return;
00796 }
00797
00798
00799
00800
00801 if (egg_group->get_billboard_type() != EggGroup::BT_none) {
00802 MFnTransform transform(transformNode, &status);
00803 if (!status) {
00804 status.perror("MFnTransform constructor");
00805 return;
00806 }
00807
00808 MPoint pivot = transform.rotatePivot(MSpace::kObject, &status);
00809 if (!status) {
00810 status.perror("Can't get rotate pivot");
00811 return;
00812 }
00813
00814
00815
00816
00817 MMatrix mat = dag_path.inclusiveMatrix(&status);
00818 if (!status) {
00819 status.perror("Can't get coordinate space for pivot");
00820 return;
00821 }
00822 LMatrix4d n2w(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
00823 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
00824 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
00825 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
00826 LPoint3d p3d(pivot[0], pivot[1], pivot[2]);
00827 p3d = p3d * n2w;
00828
00829 if (egg_group->get_parent() != (EggGroupNode *)NULL) {
00830
00831 p3d = p3d * egg_group->get_parent()->get_vertex_frame_inv();
00832 }
00833
00834 egg_group->clear_transform();
00835 egg_group->add_translate(p3d);
00836 return;
00837 }
00838
00839 switch (_transform_type) {
00840 case TT_all:
00841 break;
00842
00843 case TT_model:
00844 if (!egg_group->get_model_flag() &&
00845 egg_group->get_dcs_type() == EggGroup::DC_none) {
00846 return;
00847 }
00848 break;
00849
00850 case TT_dcs:
00851 if (egg_group->get_dcs_type() == EggGroup::DC_none) {
00852 return;
00853 }
00854 break;
00855
00856 case TT_none:
00857 case TT_invalid:
00858 return;
00859 }
00860
00861
00862
00863 MMatrix mat = dag_path.inclusiveMatrix(&status);
00864 if (!status) {
00865 status.perror("Can't get transform matrix");
00866 return;
00867 }
00868 LMatrix4d m4d(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
00869 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
00870 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
00871 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
00872 m4d = m4d * egg_group->get_node_frame_inv();
00873 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
00874 egg_group->add_matrix(m4d);
00875 }
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885 void MayaToEggConverter::
00886 make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface,
00887 EggGroup *egg_group, EggGroupNode *egg_root) {
00888 MStatus status;
00889 string name = surface.name().asChar();
00890
00891 if (mayaegg_cat.is_spam()) {
00892 mayaegg_cat.spam()
00893 << " numCVs: "
00894 << surface.numCVsInU()
00895 << " * "
00896 << surface.numCVsInV()
00897 << "\n";
00898 mayaegg_cat.spam()
00899 << " numKnots: "
00900 << surface.numKnotsInU()
00901 << " * "
00902 << surface.numKnotsInV()
00903 << "\n";
00904 mayaegg_cat.spam()
00905 << " numSpans: "
00906 << surface.numSpansInU()
00907 << " * "
00908 << surface.numSpansInV()
00909 << "\n";
00910 }
00911
00912 MayaShader *shader = _shaders.find_shader_for_node(surface.object());
00913
00914 if (_polygon_output) {
00915
00916
00917 MTesselationParams params;
00918 params.setFormatType(MTesselationParams::kStandardFitFormat);
00919 params.setOutputType(MTesselationParams::kQuads);
00920 params.setStdFractionalTolerance(_polygon_tolerance);
00921
00922
00923
00924 MDagPath polyset_path = dag_path;
00925 MObject polyset_parent = polyset_path.node();
00926 MObject polyset =
00927 surface.tesselate(params, polyset_parent, &status);
00928 if (!status) {
00929 status.perror("MFnNurbsSurface::tesselate");
00930 return;
00931 }
00932
00933 status = polyset_path.push(polyset);
00934 if (!status) {
00935 status.perror("MDagPath::push");
00936 }
00937
00938 MFnMesh polyset_fn(polyset, &status);
00939 if (!status) {
00940 status.perror("MFnMesh constructor");
00941 return;
00942 }
00943 make_polyset(polyset_path, polyset_fn, egg_group, egg_root, shader);
00944
00945
00946 MFnDagNode parent_node(polyset_parent, &status);
00947 if (!status) {
00948 status.perror("MFnDagNode constructor");
00949 return;
00950 }
00951 status = parent_node.removeChild(polyset);
00952 if (!status) {
00953 status.perror("MFnDagNode::removeChild");
00954 }
00955
00956 return;
00957 }
00958
00959 MPointArray cv_array;
00960 status = surface.getCVs(cv_array, MSpace::kWorld);
00961 if (!status) {
00962 status.perror("MFnNurbsSurface::getCVs");
00963 return;
00964 }
00965 MDoubleArray u_knot_array, v_knot_array;
00966 status = surface.getKnotsInU(u_knot_array);
00967 if (!status) {
00968 status.perror("MFnNurbsSurface::getKnotsInU");
00969 return;
00970 }
00971 status = surface.getKnotsInV(v_knot_array);
00972 if (!status) {
00973 status.perror("MFnNurbsSurface::getKnotsInV");
00974 return;
00975 }
00976
00977
00978
00979
00980
00981
00982
00983 int u_degree = surface.degreeU();
00984 int v_degree = surface.degreeV();
00985
00986 int u_cvs = surface.numCVsInU();
00987 int v_cvs = surface.numCVsInV();
00988
00989 int u_knots = surface.numKnotsInU();
00990 int v_knots = surface.numKnotsInV();
00991
00992 assert(u_knots == u_cvs + u_degree - 1);
00993 assert(v_knots == v_cvs + v_degree - 1);
00994
00995 string vpool_name = name + ".cvs";
00996 EggVertexPool *vpool = new EggVertexPool(vpool_name);
00997 egg_group->add_child(vpool);
00998
00999 EggNurbsSurface *egg_nurbs = new EggNurbsSurface(name);
01000 egg_nurbs->setup(u_degree + 1, v_degree + 1,
01001 u_knots + 2, v_knots + 2);
01002
01003 int i;
01004
01005 egg_nurbs->set_u_knot(0, u_knot_array[0]);
01006 for (i = 0; i < u_knots; i++) {
01007 egg_nurbs->set_u_knot(i + 1, u_knot_array[i]);
01008 }
01009 egg_nurbs->set_u_knot(u_knots + 1, u_knot_array[u_knots - 1]);
01010
01011 egg_nurbs->set_v_knot(0, v_knot_array[0]);
01012 for (i = 0; i < v_knots; i++) {
01013 egg_nurbs->set_v_knot(i + 1, v_knot_array[i]);
01014 }
01015 egg_nurbs->set_v_knot(v_knots + 1, v_knot_array[v_knots - 1]);
01016
01017 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01018
01019 for (i = 0; i < egg_nurbs->get_num_cvs(); i++) {
01020 int ui = egg_nurbs->get_u_index(i);
01021 int vi = egg_nurbs->get_v_index(i);
01022
01023 double v[4];
01024 MStatus status = cv_array[v_cvs * ui + vi].get(v);
01025 if (!status) {
01026 status.perror("MPoint::get");
01027 } else {
01028 EggVertex vert;
01029 LPoint4d p4d(v[0], v[1], v[2], v[3]);
01030 p4d = p4d * vertex_frame_inv;
01031 vert.set_pos(p4d);
01032 egg_nurbs->add_vertex(vpool->create_unique_vertex(vert));
01033 }
01034 }
01035
01036
01037 unsigned num_trims = surface.numRegions();
01038 int trim_curve_index = 0;
01039 for (unsigned ti = 0; ti < num_trims; ti++) {
01040 unsigned num_loops = surface.numBoundaries(ti);
01041
01042 if (num_loops > 0) {
01043 egg_nurbs->_trims.push_back(EggNurbsSurface::Trim());
01044 EggNurbsSurface::Trim &egg_trim = egg_nurbs->_trims.back();
01045
01046 for (unsigned li = 0; li < num_loops; li++) {
01047 egg_trim.push_back(EggNurbsSurface::Loop());
01048 EggNurbsSurface::Loop &egg_loop = egg_trim.back();
01049
01050 MFnNurbsSurface::BoundaryType type =
01051 surface.boundaryType(ti, li, &status);
01052 bool keep_loop = false;
01053
01054 if (!status) {
01055 status.perror("MFnNurbsSurface::BoundaryType");
01056 } else {
01057 keep_loop = (type == MFnNurbsSurface::kInner ||
01058 type == MFnNurbsSurface::kOuter);
01059 }
01060
01061 if (keep_loop) {
01062 unsigned num_edges = surface.numEdges(ti, li);
01063 for (unsigned ei = 0; ei < num_edges; ei++) {
01064 MObjectArray edge = surface.edge(ti, li, ei, true, &status);
01065 if (!status) {
01066 status.perror("MFnNurbsSurface::edge");
01067 } else {
01068 unsigned num_segs = edge.length();
01069 for (unsigned si = 0; si < num_segs; si++) {
01070 MObject segment = edge[si];
01071 if (segment.hasFn(MFn::kNurbsCurve)) {
01072 MFnNurbsCurve curve(segment, &status);
01073 if (!status) {
01074 mayaegg_cat.error()
01075 << "Trim curve appears to be a nurbs curve, but isn't.\n";
01076 } else {
01077
01078 EggNurbsCurve *egg_curve =
01079 make_trim_curve(curve, name, egg_group, trim_curve_index);
01080 trim_curve_index++;
01081 if (egg_curve != (EggNurbsCurve *)NULL) {
01082 egg_loop.push_back(egg_curve);
01083 }
01084 }
01085 } else {
01086 mayaegg_cat.error()
01087 << "Trim curve segment is not a nurbs curve.\n";
01088 }
01089 }
01090 }
01091 }
01092 }
01093 }
01094 }
01095 }
01096
01097
01098
01099 egg_group->add_child(egg_nurbs);
01100
01101 if (shader != (MayaShader *)NULL) {
01102 set_shader_attributes(*egg_nurbs, *shader);
01103 }
01104 }
01105
01106
01107
01108
01109
01110
01111
01112
01113 EggNurbsCurve *MayaToEggConverter::
01114 make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
01115 EggGroupNode *egg_group, int trim_curve_index) {
01116 if (mayaegg_cat.is_spam()) {
01117 mayaegg_cat.spam()
01118 << "Trim curve:\n";
01119 mayaegg_cat.spam()
01120 << " numCVs: "
01121 << curve.numCVs()
01122 << "\n";
01123 mayaegg_cat.spam()
01124 << " numKnots: "
01125 << curve.numKnots()
01126 << "\n";
01127 mayaegg_cat.spam()
01128 << " numSpans: "
01129 << curve.numSpans()
01130 << "\n";
01131 }
01132
01133 MStatus status;
01134
01135 MPointArray cv_array;
01136 status = curve.getCVs(cv_array, MSpace::kWorld);
01137 if (!status) {
01138 status.perror("MFnNurbsCurve::getCVs");
01139 return (EggNurbsCurve *)NULL;
01140 }
01141 MDoubleArray knot_array;
01142 status = curve.getKnots(knot_array);
01143 if (!status) {
01144 status.perror("MFnNurbsCurve::getKnots");
01145 return (EggNurbsCurve *)NULL;
01146 }
01147
01148
01149
01150
01151
01152 int degree = curve.degree();
01153 int cvs = curve.numCVs();
01154 int knots = curve.numKnots();
01155
01156 assert(knots == cvs + degree - 1);
01157
01158 string trim_name = "trim" + format_string(trim_curve_index);
01159
01160 string vpool_name = nurbs_name + "." + trim_name;
01161 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01162 egg_group->add_child(vpool);
01163
01164 EggNurbsCurve *egg_curve = new EggNurbsCurve(trim_name);
01165 egg_curve->setup(degree + 1, knots + 2);
01166
01167 int i;
01168
01169 egg_curve->set_knot(0, knot_array[0]);
01170 for (i = 0; i < knots; i++) {
01171 egg_curve->set_knot(i + 1, knot_array[i]);
01172 }
01173 egg_curve->set_knot(knots + 1, knot_array[knots - 1]);
01174
01175 for (i = 0; i < egg_curve->get_num_cvs(); i++) {
01176 double v[4];
01177 MStatus status = cv_array[i].get(v);
01178 if (!status) {
01179 status.perror("MPoint::get");
01180 } else {
01181 EggVertex vert;
01182 vert.set_pos(LPoint3d(v[0], v[1], v[3]));
01183 egg_curve->add_vertex(vpool->create_unique_vertex(vert));
01184 }
01185 }
01186
01187 return egg_curve;
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197 void MayaToEggConverter::
01198 make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
01199 EggGroup *egg_group, EggGroupNode *) {
01200 MStatus status;
01201 string name = curve.name().asChar();
01202
01203 if (mayaegg_cat.is_spam()) {
01204 mayaegg_cat.spam()
01205 << " numCVs: "
01206 << curve.numCVs()
01207 << "\n";
01208 mayaegg_cat.spam()
01209 << " numKnots: "
01210 << curve.numKnots()
01211 << "\n";
01212 mayaegg_cat.spam()
01213 << " numSpans: "
01214 << curve.numSpans()
01215 << "\n";
01216 }
01217
01218 MPointArray cv_array;
01219 status = curve.getCVs(cv_array, MSpace::kWorld);
01220 if (!status) {
01221 status.perror("MFnNurbsCurve::getCVs");
01222 return;
01223 }
01224 MDoubleArray knot_array;
01225 status = curve.getKnots(knot_array);
01226 if (!status) {
01227 status.perror("MFnNurbsCurve::getKnots");
01228 return;
01229 }
01230
01231
01232
01233
01234
01235 int degree = curve.degree();
01236 int cvs = curve.numCVs();
01237 int knots = curve.numKnots();
01238
01239 assert(knots == cvs + degree - 1);
01240
01241 string vpool_name = name + ".cvs";
01242 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01243 egg_group->add_child(vpool);
01244
01245 EggNurbsCurve *egg_curve = new EggNurbsCurve(name);
01246 egg_group->add_child(egg_curve);
01247 egg_curve->setup(degree + 1, knots + 2);
01248
01249 int i;
01250
01251 egg_curve->set_knot(0, knot_array[0]);
01252 for (i = 0; i < knots; i++) {
01253 egg_curve->set_knot(i + 1, knot_array[i]);
01254 }
01255 egg_curve->set_knot(knots + 1, knot_array[knots - 1]);
01256
01257 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01258
01259 for (i = 0; i < egg_curve->get_num_cvs(); i++) {
01260 double v[4];
01261 MStatus status = cv_array[i].get(v);
01262 if (!status) {
01263 status.perror("MPoint::get");
01264 } else {
01265 EggVertex vert;
01266 LPoint4d p4d(v[0], v[1], v[2], v[3]);
01267 p4d = p4d * vertex_frame_inv;
01268 vert.set_pos(p4d);
01269 egg_curve->add_vertex(vpool->create_unique_vertex(vert));
01270 }
01271 }
01272
01273 MayaShader *shader = _shaders.find_shader_for_node(curve.object());
01274 if (shader != (MayaShader *)NULL) {
01275 set_shader_attributes(*egg_curve, *shader);
01276 }
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286 void MayaToEggConverter::
01287 make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
01288 EggGroup *egg_group, EggGroupNode *egg_root,
01289 MayaShader *default_shader) {
01290 MStatus status;
01291 string name = mesh.name().asChar();
01292
01293 MObject mesh_object = mesh.object();
01294 bool double_sided = false;
01295 get_bool_attribute(mesh_object, "doubleSided", double_sided);
01296
01297 if (mayaegg_cat.is_spam()) {
01298 mayaegg_cat.spam()
01299 << " numPolygons: "
01300 << mesh.numPolygons()
01301 << "\n";
01302 mayaegg_cat.spam()
01303 << " numVertices: "
01304 << mesh.numVertices()
01305 << "\n";
01306 }
01307
01308 if (mesh.numPolygons() == 0) {
01309 if (mayaegg_cat.is_debug()) {
01310 mayaegg_cat.debug()
01311 << "Ignoring empty mesh " << name << "\n";
01312 }
01313 return;
01314 }
01315
01316 string vpool_name = name + ".verts";
01317 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01318 egg_group->add_child(vpool);
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 MObject component_obj;
01333 MItMeshPolygon pi(dag_path, component_obj, &status);
01334 if (!status) {
01335 status.perror("MItMeshPolygon constructor");
01336 return;
01337 }
01338
01339 MObjectArray shaders;
01340 MIntArray poly_shader_indices;
01341
01342 status = mesh.getConnectedShaders(dag_path.instanceNumber(),
01343 shaders, poly_shader_indices);
01344 if (!status) {
01345 status.perror("MFnMesh::getConnectedShaders");
01346 }
01347
01348
01349
01350
01351
01352
01353
01354 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01355
01356 while (!pi.isDone()) {
01357 EggPolygon *egg_poly = new EggPolygon;
01358 egg_group->add_child(egg_poly);
01359
01360 egg_poly->set_bface_flag(double_sided);
01361
01362
01363 MayaShader *shader = NULL;
01364 int index = pi.index();
01365 nassertv(index >= 0 && index < (int)poly_shader_indices.length());
01366 int shader_index = poly_shader_indices[index];
01367 if (shader_index != -1) {
01368 nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
01369 MObject engine = shaders[shader_index];
01370 shader =
01371 _shaders.find_shader_for_shading_engine(engine);
01372
01373 } else if (default_shader != (MayaShader *)NULL) {
01374 shader = default_shader;
01375 }
01376
01377 const MayaShaderColorDef &color_def = shader->_color;
01378
01379
01380
01381 bool has_texture = false;
01382 if (shader != (MayaShader *)NULL) {
01383 has_texture = color_def._has_texture;
01384 }
01385
01386
01387 long num_verts = pi.polygonVertexCount();
01388 long i;
01389 LPoint3d centroid(0.0, 0.0, 0.0);
01390
01391 if (shader != (MayaShader *)NULL && color_def.has_projection()) {
01392
01393
01394 for (i = 0; i < num_verts; i++) {
01395 MPoint p = pi.point(i, MSpace::kWorld);
01396 LPoint3d p3d(p[0], p[1], p[2]);
01397 p3d = p3d * vertex_frame_inv;
01398 centroid += p3d;
01399 }
01400 centroid /= (double)num_verts;
01401 }
01402
01403 for (i = 0; i < num_verts; i++) {
01404 EggVertex vert;
01405
01406 MPoint p = pi.point(i, MSpace::kWorld);
01407 LPoint3d p3d(p[0], p[1], p[2]);
01408 p3d = p3d * vertex_frame_inv;
01409 vert.set_pos(p3d);
01410
01411 MVector n;
01412 status = pi.getNormal(i, n, MSpace::kWorld);
01413 if (!status) {
01414 status.perror("MItMeshPolygon::getNormal");
01415 } else {
01416 LVector3d n3d(n[0], n[1], n[2]);
01417 n3d = n3d * vertex_frame_inv;
01418 vert.set_normal(n3d);
01419 }
01420
01421 if (shader != (MayaShader *)NULL && color_def.has_projection()) {
01422
01423
01424 vert.set_uv(color_def.project_uv(p3d, centroid));
01425
01426 } else if (pi.hasUVs()) {
01427
01428 float2 uvs;
01429 status = pi.getUV(i, uvs);
01430 if (!status) {
01431 status.perror("MItMeshPolygon::getUV");
01432 } else {
01433 vert.set_uv(TexCoordd(uvs[0], uvs[1]));
01434 }
01435 }
01436
01437 if (pi.hasColor() && !has_texture) {
01438 MColor c;
01439 status = pi.getColor(c, i);
01440 if (!status) {
01441 status.perror("MItMeshPolygon::getColor");
01442 } else {
01443 vert.set_color(Colorf(c.r, c.g, c.b, 1.0));
01444 }
01445 }
01446
01447 vert.set_external_index(pi.vertexIndex(i, &status));
01448
01449 egg_poly->add_vertex(vpool->create_unique_vertex(vert));
01450 }
01451
01452
01453 if (shader != (MayaShader *)NULL) {
01454 set_shader_attributes(*egg_poly, *shader);
01455 }
01456
01457 pi.next();
01458 }
01459
01460
01461
01462
01463 bool got_weights = false;
01464
01465 pvector<EggGroup *> joints;
01466 MFloatArray weights;
01467 if (_animation_convert == AC_model) {
01468 got_weights =
01469 get_vertex_weights(dag_path, mesh, egg_root, joints, weights);
01470 }
01471
01472 if (got_weights) {
01473 int num_joints = joints.size();
01474 int num_weights = (int)weights.length();
01475 int num_verts = num_weights / num_joints;
01476
01477
01478 nassertv(num_weights == num_verts * num_joints);
01479
01480 EggVertexPool::iterator vi;
01481 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
01482 EggVertex *vert = (*vi);
01483 int maya_vi = vert->get_external_index();
01484 nassertv(maya_vi >= 0 && maya_vi < num_verts);
01485
01486 for (int ji = 0; ji < num_joints; ++ji) {
01487 float weight = weights[maya_vi * num_joints + ji];
01488 if (weight != 0.0f) {
01489 EggGroup *joint = joints[ji];
01490 if (joint != (EggGroup *)NULL) {
01491 joint->ref_vertex(vert, weight);
01492 }
01493 }
01494 }
01495 }
01496 }
01497 }
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509 void MayaToEggConverter::
01510 make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
01511 EggGroup *egg_group, EggGroupNode *egg_root) {
01512 MStatus status;
01513
01514 unsigned int num_children = dag_node.childCount();
01515 MObject locator;
01516 bool found_locator = false;
01517 for (unsigned int ci = 0; ci < num_children && !found_locator; ci++) {
01518 locator = dag_node.child(ci);
01519 found_locator = (locator.apiType() == MFn::kLocator);
01520 }
01521
01522 if (!found_locator) {
01523 mayaegg_cat.error()
01524 << "Couldn't find locator within locator node "
01525 << dag_path.fullPathName().asChar() << "\n";
01526 return;
01527 }
01528
01529 LPoint3d p3d;
01530 if (!get_vec3d_attribute(locator, "localPosition", p3d)) {
01531 mayaegg_cat.error()
01532 << "Couldn't get position of locator "
01533 << dag_path.fullPathName().asChar() << "\n";
01534 return;
01535 }
01536
01537
01538
01539 MMatrix mat = dag_path.inclusiveMatrix(&status);
01540 if (!status) {
01541 status.perror("Can't get coordinate space for locator");
01542 return;
01543 }
01544 LMatrix4d n2w(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
01545 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
01546 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
01547 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
01548 p3d = p3d * n2w;
01549
01550
01551 p3d = p3d * egg_group->get_node_frame_inv();
01552
01553 egg_group->add_translate(p3d);
01554
01555
01556
01557
01558 egg_group->set_dcs_type(EggGroup::DC_net);
01559 }
01560
01561
01562
01563
01564
01565
01566 bool MayaToEggConverter::
01567 get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
01568 EggGroupNode *egg_root,
01569 pvector<EggGroup *> &joints, MFloatArray &weights) {
01570 MStatus status;
01571
01572
01573
01574
01575 MObject attr = mesh.attribute("inMesh");
01576
01577
01578
01579
01580 MPlug history(mesh.object(), attr);
01581 MItDependencyGraph it(history, MFn::kDependencyNode,
01582 MItDependencyGraph::kUpstream,
01583 MItDependencyGraph::kDepthFirst,
01584 MItDependencyGraph::kNodeLevel);
01585
01586 while (!it.isDone()) {
01587
01588
01589
01590 MObject c_node = it.thisNode();
01591 if (c_node.hasFn(MFn::kSkinClusterFilter)) {
01592
01593
01594
01595 MFnSkinCluster cluster(c_node, &status);
01596 if (!status) {
01597 status.perror("MFnSkinCluster constructor");
01598 return false;
01599 }
01600
01601
01602
01603 MDagPathArray influence_objects;
01604 cluster.influenceObjects(influence_objects, &status);
01605 if (!status) {
01606 status.perror("MFnSkinCluster::influenceObjects");
01607
01608 } else {
01609
01610
01611 joints.clear();
01612 for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
01613 MDagPath joint_dag_path = influence_objects[oi];
01614 EggGroup *joint = get_egg_group(joint_dag_path, egg_root);
01615 joints.push_back(joint);
01616 }
01617
01618
01619
01620 MFnSingleIndexedComponent sic;
01621 MObject sic_object = sic.create(MFn::kMeshVertComponent);
01622 sic.setCompleteData(mesh.numVertices());
01623 unsigned influence_count;
01624
01625 status = cluster.getWeights(dag_path, sic_object,
01626 weights, influence_count);
01627 if (!status) {
01628 status.perror("MFnSkinCluster::getWeights");
01629 } else {
01630 if (influence_count != influence_objects.length()) {
01631 mayaegg_cat.error()
01632 << "MFnSkinCluster::influenceObjects() returns "
01633 << influence_objects.length()
01634 << " objects, but MFnSkinCluster::getWeights() reports "
01635 << influence_count << " objects.\n";
01636
01637 } else {
01638
01639
01640 return true;
01641 }
01642 }
01643 }
01644 }
01645
01646 it.next();
01647 }
01648
01649 mayaegg_cat.error()
01650 << "Unable to find a cluster handle for the DG node.\n";
01651 return false;
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 EggGroup *MayaToEggConverter::
01668 get_egg_group(const MDagPath &dag_path, EggGroupNode *egg_root) {
01669 return r_get_egg_group(dag_path.fullPathName().asChar(), dag_path, egg_root);
01670 }
01671
01672
01673
01674
01675
01676
01677 EggGroup *MayaToEggConverter::
01678 r_get_egg_group(const string &name, const MDagPath &dag_path,
01679 EggGroupNode *egg_root) {
01680
01681
01682 Groups::const_iterator gi = _groups.find(name);
01683 if (gi != _groups.end()) {
01684 return (*gi).second;
01685 }
01686
01687
01688
01689 EggGroup *egg_group;
01690
01691 if (name.empty()) {
01692
01693 egg_group = (EggGroup *)NULL;
01694
01695 } else {
01696
01697
01698
01699 size_t bar = name.rfind("|");
01700 string parent_name, local_name;
01701 if (bar != string::npos) {
01702 parent_name = name.substr(0, bar);
01703 local_name = name.substr(bar + 1);
01704 } else {
01705 local_name = name;
01706 }
01707
01708 EggGroup *parent_egg_group =
01709 r_get_egg_group(parent_name, dag_path, egg_root);
01710 egg_group = new EggGroup(local_name);
01711
01712 if (parent_egg_group != (EggGroup *)NULL) {
01713 parent_egg_group->add_child(egg_group);
01714 } else {
01715 egg_root->add_child(egg_group);
01716 }
01717
01718
01719 MObject dag_object = dag_path.node();
01720 string object_type;
01721 if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
01722 egg_group->add_object_type(object_type);
01723 }
01724 if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
01725 egg_group->add_object_type(object_type);
01726 }
01727 if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
01728 egg_group->add_object_type(object_type);
01729 }
01730
01731
01732
01733
01734 if (egg_group->has_object_type("billboard")) {
01735 egg_group->remove_object_type("billboard");
01736 egg_group->set_group_type(EggGroup::GT_instance);
01737 egg_group->set_billboard_type(EggGroup::BT_axis);
01738
01739 } else if (egg_group->has_object_type("billboard-point")) {
01740 egg_group->remove_object_type("billboard-point");
01741 egg_group->set_group_type(EggGroup::GT_instance);
01742 egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
01743 }
01744
01745
01746
01747 if (egg_group->has_object_type("dcs")) {
01748 egg_group->remove_object_type("dcs");
01749 egg_group->set_dcs_type(EggGroup::DC_default);
01750 }
01751 if (egg_group->has_object_type("model")) {
01752 egg_group->remove_object_type("model");
01753 egg_group->set_model_flag(true);
01754 }
01755 }
01756
01757 _groups.insert(Groups::value_type(name, egg_group));
01758 return egg_group;
01759 }
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770 MayaToEggConverter::JointAnim *MayaToEggConverter::
01771 get_egg_table(const MDagPath &dag_path, EggGroupNode *egg_root) {
01772 string name = dag_path.fullPathName().asChar();
01773
01774
01775
01776 Tables::const_iterator ti = _tables.find(name);
01777 if (ti != _tables.end()) {
01778 return (*ti).second;
01779 }
01780
01781
01782 JointAnim *joint_anim;
01783
01784 if (name.empty()) {
01785
01786 joint_anim = (JointAnim *)NULL;
01787
01788 } else {
01789
01790
01791
01792 size_t bar = name.rfind("|");
01793 string parent_name, local_name;
01794 if (bar != string::npos) {
01795 parent_name = name.substr(0, bar);
01796 local_name = name.substr(bar + 1);
01797 } else {
01798 local_name = name;
01799 }
01800
01801
01802
01803
01804 JointAnim *parent_joint_anim = NULL;
01805 if (!parent_name.empty()) {
01806 ti = _tables.find(parent_name);
01807 if (ti != _tables.end()) {
01808 parent_joint_anim = (*ti).second;
01809 }
01810 }
01811
01812 joint_anim = new JointAnim;
01813 joint_anim->_dag_path = dag_path;
01814 joint_anim->_table = new EggTable(local_name);
01815 joint_anim->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
01816 joint_anim->_table->add_child(joint_anim->_anim);
01817
01818 if (parent_joint_anim != (JointAnim *)NULL) {
01819 parent_joint_anim->_table->add_child(joint_anim->_table);
01820 } else {
01821 egg_root->add_child(joint_anim->_table);
01822 }
01823 }
01824
01825 _tables.insert(Tables::value_type(name, joint_anim));
01826 return joint_anim;
01827 }
01828
01829
01830
01831
01832
01833
01834
01835 void MayaToEggConverter::
01836 set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader) {
01837
01838
01839 const MayaShaderColorDef &color_def = shader._color;
01840 const MayaShaderColorDef &trans_def = shader._transparency;
01841 if (color_def._has_texture || trans_def._has_texture) {
01842 EggTexture tex(shader.get_name(), "");
01843
01844 if (color_def._has_texture) {
01845
01846 Filename filename = Filename::from_os_specific(color_def._texture);
01847 Filename fullpath =
01848 _path_replace->match_path(filename, get_texture_path());
01849 tex.set_filename(_path_replace->store_path(fullpath));
01850 tex.set_fullpath(fullpath);
01851 apply_texture_properties(tex, color_def);
01852
01853
01854
01855 if (trans_def._has_texture) {
01856 if (color_def._wrap_u != trans_def._wrap_u ||
01857 color_def._wrap_u != trans_def._wrap_u) {
01858 mayaegg_cat.warning()
01859 << "Shader " << shader.get_name()
01860 << " has contradictory wrap modes on color and texture.\n";
01861 }
01862
01863 if (!compare_texture_properties(tex, trans_def)) {
01864
01865 static pset<string> bad_shaders;
01866 if (bad_shaders.insert(shader.get_name()).second) {
01867 mayaegg_cat.error()
01868 << "Color and transparency texture properties differ on shader "
01869 << shader.get_name() << "\n";
01870 }
01871 }
01872 tex.set_format(EggTexture::F_rgba);
01873
01874
01875
01876
01877
01878
01879
01880
01881 if (trans_def._texture == color_def._texture) {
01882
01883
01884
01885 } else {
01886
01887
01888
01889
01890
01891 filename = Filename::from_os_specific(trans_def._texture);
01892 fullpath = _path_replace->match_path(filename, get_texture_path());
01893 tex.set_alpha_filename(_path_replace->store_path(fullpath));
01894 tex.set_alpha_fullpath(fullpath);
01895 }
01896
01897 } else {
01898
01899
01900
01901 tex.set_format(EggTexture::F_rgb);
01902 }
01903
01904 } else {
01905
01906
01907 Filename filename = Filename::from_os_specific(trans_def._texture);
01908 Filename fullpath =
01909 _path_replace->match_path(filename, get_texture_path());
01910 tex.set_filename(_path_replace->store_path(fullpath));
01911 tex.set_fullpath(fullpath);
01912 tex.set_format(EggTexture::F_alpha);
01913 apply_texture_properties(tex, trans_def);
01914 }
01915
01916 EggTexture *new_tex =
01917 _textures.create_unique_texture(tex, ~EggTexture::E_tref_name);
01918
01919 primitive.set_texture(new_tex);
01920
01921 }
01922
01923
01924 Colorf rgba = shader.get_rgba();
01925
01926
01927
01928 static const bool modulate = false;
01929
01930 if (!modulate) {
01931
01932
01933 if (color_def._has_texture) {
01934 rgba[0] = 1.0f;
01935 rgba[1] = 1.0f;
01936 rgba[2] = 1.0f;
01937 }
01938 if (trans_def._has_texture) {
01939 rgba[3] = 1.0f;
01940 }
01941 }
01942
01943
01944 rgba[0] *= color_def._color_gain[0];
01945 rgba[1] *= color_def._color_gain[1];
01946 rgba[2] *= color_def._color_gain[2];
01947
01948 primitive.set_color(rgba);
01949 }
01950
01951
01952
01953
01954
01955
01956
01957
01958 void MayaToEggConverter::
01959 apply_texture_properties(EggTexture &tex, const MayaShaderColorDef &color_def) {
01960
01961 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
01962 tex.set_magfilter(EggTexture::FT_linear);
01963
01964 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
01965 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
01966
01967 tex.set_wrap_u(wrap_u);
01968 tex.set_wrap_v(wrap_v);
01969
01970 LMatrix3d mat = color_def.compute_texture_matrix();
01971 if (!mat.almost_equal(LMatrix3d::ident_mat())) {
01972 tex.set_transform(mat);
01973 }
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985 bool MayaToEggConverter::
01986 compare_texture_properties(EggTexture &tex,
01987 const MayaShaderColorDef &color_def) {
01988 bool okflag = true;
01989
01990 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
01991 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
01992
01993 if (wrap_u != tex.determine_wrap_u()) {
01994
01995 if (wrap_u == EggTexture::WM_repeat) {
01996 tex.set_wrap_u(wrap_u);
01997 }
01998 okflag = false;
01999 }
02000 if (wrap_v != tex.determine_wrap_v()) {
02001 if (wrap_v == EggTexture::WM_repeat) {
02002 tex.set_wrap_v(wrap_v);
02003 }
02004 okflag = false;
02005 }
02006
02007 LMatrix3d mat = color_def.compute_texture_matrix();
02008 if (!mat.almost_equal(tex.get_transform())) {
02009 okflag = false;
02010 }
02011
02012 return okflag;
02013 }
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025 bool MayaToEggConverter::
02026 reparent_decals(EggGroupNode *egg_parent) {
02027 bool okflag = true;
02028
02029
02030
02031 EggGroup *decal_base = (EggGroup *)NULL;
02032 pvector<EggGroup *> decal_children;
02033
02034 EggGroupNode::iterator ci;
02035 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
02036 EggNode *child = (*ci);
02037 if (child->is_of_type(EggGroup::get_class_type())) {
02038 EggGroup *child_group = DCAST(EggGroup, child);
02039 if (child_group->has_object_type("decalbase")) {
02040 if (decal_base != (EggNode *)NULL) {
02041 mayaegg_cat.error()
02042 << "Two children of " << egg_parent->get_name()
02043 << " both have decalbase set: " << decal_base->get_name()
02044 << " and " << child_group->get_name() << "\n";
02045 okflag = false;
02046 }
02047 child_group->remove_object_type("decalbase");
02048 decal_base = child_group;
02049
02050 } else if (child_group->has_object_type("decal")) {
02051 child_group->remove_object_type("decal");
02052 decal_children.push_back(child_group);
02053 }
02054 }
02055 }
02056
02057 if (decal_base == (EggGroup *)NULL) {
02058 if (!decal_children.empty()) {
02059 mayaegg_cat.warning()
02060 << decal_children.front()->get_name()
02061 << " has decal, but no sibling node has decalbase.\n";
02062 }
02063
02064 } else {
02065 if (decal_children.empty()) {
02066 mayaegg_cat.warning()
02067 << decal_base->get_name()
02068 << " has decalbase, but no sibling nodes have decal.\n";
02069
02070 } else {
02071
02072
02073
02074
02075 pvector<EggGroup *>::iterator di;
02076 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
02077 EggGroup *child_group = (*di);
02078 decal_base->add_child(child_group);
02079 }
02080
02081
02082 decal_base->set_decal_flag(true);
02083 }
02084 }
02085
02086
02087 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
02088 EggNode *child = (*ci);
02089 if (child->is_of_type(EggGroupNode::get_class_type())) {
02090 EggGroupNode *child_group = DCAST(EggGroupNode, child);
02091 if (!reparent_decals(child_group)) {
02092 okflag = false;
02093 }
02094 }
02095 }
02096
02097 return okflag;
02098 }
02099
02100
02101
02102
02103
02104
02105
02106 MayaToEggConverter::TransformType MayaToEggConverter::
02107 string_transform_type(const string &arg) {
02108 if (cmp_nocase(arg, "all") == 0) {
02109 return TT_all;
02110 } else if (cmp_nocase(arg, "model") == 0) {
02111 return TT_model;
02112 } else if (cmp_nocase(arg, "dcs") == 0) {
02113 return TT_dcs;
02114 } else if (cmp_nocase(arg, "none") == 0) {
02115 return TT_none;
02116 } else {
02117 return TT_invalid;
02118 }
02119 }