00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mayaToEggConverter.h"
00019 #include "mayaShader.h"
00020 #include "maya_funcs.h"
00021 #include "config_mayaegg.h"
00022 #include "mayaEggGroupUserData.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 "eggSAnimData.h"
00037 #include "string_utils.h"
00038 #include "dcast.h"
00039
00040 #include "pre_maya_include.h"
00041 #include <maya/MArgList.h>
00042 #include <maya/MColor.h>
00043 #include <maya/MDagPath.h>
00044 #include <maya/MFnCamera.h>
00045 #include <maya/MFnDagNode.h>
00046 #include <maya/MFnTransform.h>
00047 #include <maya/MFnLight.h>
00048 #include <maya/MFnNurbsSurface.h>
00049 #include <maya/MFnNurbsCurve.h>
00050 #include <maya/MFnMesh.h>
00051 #include <maya/MFnMeshData.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/MFnWeightGeometryFilter.h>
00072 #include <maya/MFnIkJoint.h>
00073 #include <maya/MFnSingleIndexedComponent.h>
00074 #include <maya/MFnDoubleIndexedComponent.h>
00075 #include <maya/MFnBlendShapeDeformer.h>
00076 #include <maya/MItDependencyGraph.h>
00077 #include <maya/MDagPathArray.h>
00078 #include <maya/MSelectionList.h>
00079 #include "post_maya_include.h"
00080
00081
00082
00083
00084
00085
00086
00087 MayaToEggConverter::
00088 MayaToEggConverter(const string &program_name) :
00089 _program_name(program_name),
00090 _tree(this)
00091 {
00092
00093 init_libmayaegg();
00094
00095 _from_selection = false;
00096
00097 _polygon_output = false;
00098 _polygon_tolerance = 0.01;
00099 _respect_maya_double_sided = maya_default_double_sided;
00100 _always_show_vertex_color = maya_default_vertex_color;
00101 _keep_all_uvsets = false;
00102 _round_uvs = false;
00103 _legacy_shader = false;
00104
00105 _transform_type = TT_model;
00106 }
00107
00108
00109
00110
00111
00112
00113 MayaToEggConverter::
00114 MayaToEggConverter(const MayaToEggConverter ©) :
00115 _program_name(copy._program_name),
00116 _from_selection(copy._from_selection),
00117 _subsets(copy._subsets),
00118 _subroots(copy._subroots),
00119 _excludes(copy._excludes),
00120 _ignore_sliders(copy._ignore_sliders),
00121 _force_joints(copy._force_joints),
00122 _tree(this),
00123 _maya(copy._maya),
00124 _polygon_output(copy._polygon_output),
00125 _polygon_tolerance(copy._polygon_tolerance),
00126 _respect_maya_double_sided(copy._respect_maya_double_sided),
00127 _always_show_vertex_color(copy._always_show_vertex_color),
00128 _keep_all_uvsets(copy._keep_all_uvsets),
00129 _round_uvs(copy._round_uvs),
00130 _legacy_shader(copy._legacy_shader),
00131 _transform_type(copy._transform_type)
00132 {
00133 }
00134
00135
00136
00137
00138
00139
00140 MayaToEggConverter::
00141 ~MayaToEggConverter() {
00142 close_api();
00143 }
00144
00145
00146
00147
00148
00149
00150 SomethingToEggConverter *MayaToEggConverter::
00151 make_copy() {
00152 return new MayaToEggConverter(*this);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 string MayaToEggConverter::
00162 get_name() const {
00163 return "Maya";
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 string MayaToEggConverter::
00173 get_extension() const {
00174 return "mb";
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 string MayaToEggConverter::
00185 get_additional_extensions() const {
00186 return "ma";
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 bool MayaToEggConverter::
00201 convert_file(const Filename &filename) {
00202 if (!open_api()) {
00203 mayaegg_cat.error()
00204 << "Maya is not available.\n";
00205 return false;
00206 }
00207
00208
00209
00210
00211
00212 clear();
00213
00214 if (!_maya->read(filename)) {
00215 mayaegg_cat.error()
00216 << "Unable to read " << filename << "\n";
00217 return false;
00218 }
00219
00220 if (_character_name.empty()) {
00221 _character_name = filename.get_basename_wo_extension();
00222 }
00223
00224 return convert_maya();
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 void MayaToEggConverter::
00235 clear_subroots() {
00236 _subroots.clear();
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void MayaToEggConverter::
00249 add_subroot(const GlobPattern &glob) {
00250 _subroots.push_back(glob);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 void MayaToEggConverter::
00261 clear_subsets() {
00262 _subsets.clear();
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 void MayaToEggConverter::
00275 add_subset(const GlobPattern &glob) {
00276 _subsets.push_back(glob);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 void MayaToEggConverter::
00286 clear_excludes() {
00287 _excludes.clear();
00288 }
00289
00290
00291
00292
00293
00294
00295 void MayaToEggConverter::
00296 add_exclude(const GlobPattern &glob) {
00297 _excludes.push_back(glob);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 void MayaToEggConverter::
00307 clear_ignore_sliders() {
00308 _ignore_sliders.clear();
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void MayaToEggConverter::
00323 add_ignore_slider(const GlobPattern &glob) {
00324 _ignore_sliders.push_back(glob);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 bool MayaToEggConverter::
00334 ignore_slider(const string &name) const {
00335 Globs::const_iterator gi;
00336 for (gi = _ignore_sliders.begin(); gi != _ignore_sliders.end(); ++gi) {
00337 if ((*gi).matches(name)) {
00338 return true;
00339 }
00340 }
00341
00342 return false;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 void MayaToEggConverter::
00352 clear_force_joints() {
00353 _force_joints.clear();
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 void MayaToEggConverter::
00369 add_force_joint(const GlobPattern &glob) {
00370 _force_joints.push_back(glob);
00371 }
00372
00373
00374
00375
00376
00377
00378
00379 bool MayaToEggConverter::
00380 force_joint(const string &name) const {
00381 Globs::const_iterator gi;
00382 for (gi = _force_joints.begin(); gi != _force_joints.end(); ++gi) {
00383 if ((*gi).matches(name)) {
00384 return true;
00385 }
00386 }
00387
00388 return false;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 void MayaToEggConverter::
00401 set_from_selection(bool from_selection) {
00402 _from_selection = from_selection;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 DistanceUnit MayaToEggConverter::
00415 get_input_units() {
00416 return _maya->get_units();
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426 bool MayaToEggConverter::
00427 convert_maya() {
00428 clear();
00429 clear_error();
00430
00431 if (!open_api()) {
00432 mayaegg_cat.error()
00433 << "Maya is not available.\n";
00434 return false;
00435 }
00436
00437 if (_egg_data->get_coordinate_system() == CS_default) {
00438 _egg_data->set_coordinate_system(_maya->get_coordinate_system());
00439 }
00440
00441 mayaegg_cat.info()
00442 << "Converting from Maya.\n";
00443
00444
00445 double start_frame, end_frame, frame_inc, input_frame_rate, output_frame_rate;
00446 if (has_start_frame()) {
00447 start_frame = get_start_frame();
00448 } else {
00449 start_frame = MAnimControl::minTime().value();
00450 }
00451 if (has_end_frame()) {
00452 end_frame = get_end_frame();
00453 } else {
00454 end_frame = MAnimControl::maxTime().value();
00455
00456 }
00457 if (has_frame_inc()) {
00458 frame_inc = get_frame_inc();
00459 } else {
00460 frame_inc = 1.0;
00461 }
00462 if (has_input_frame_rate()) {
00463 input_frame_rate = get_input_frame_rate();
00464 } else {
00465 MTime time(1.0, MTime::kSeconds);
00466 input_frame_rate = time.as(MTime::uiUnit());
00467 }
00468 if (has_output_frame_rate()) {
00469 output_frame_rate = get_output_frame_rate();
00470 } else {
00471 output_frame_rate = input_frame_rate;
00472 }
00473
00474 frame_inc = frame_inc * input_frame_rate / output_frame_rate;
00475
00476 bool all_ok = _tree.build_hierarchy();
00477
00478 if (all_ok) {
00479 if (!_subroots.empty()) {
00480 Globs::const_iterator gi;
00481 for (gi = _subroots.begin(); gi != _subroots.end(); ++gi) {
00482 if (!_tree.tag_joint_named(*gi)) {
00483 mayaegg_cat.info()
00484 << "No node matching " << *gi << " found.\n";
00485 }
00486 }
00487
00488 } else {
00489
00490
00491 _tree.tag_joint_all();
00492 }
00493 }
00494
00495 if (all_ok) {
00496 if (_from_selection) {
00497 all_ok = _tree.tag_selected();
00498 } else if (!_subsets.empty()) {
00499 Globs::const_iterator gi;
00500 for (gi = _subsets.begin(); gi != _subsets.end(); ++gi) {
00501 if (!_tree.tag_named(*gi)) {
00502 mayaegg_cat.info()
00503 << "No node matching " << *gi << " found.\n";
00504 }
00505 }
00506
00507 } else {
00508 _tree.tag_all();
00509 }
00510 }
00511
00512 if (all_ok) {
00513 if (!_excludes.empty()) {
00514 Globs::const_iterator gi;
00515 for (gi = _excludes.begin(); gi != _excludes.end(); ++gi) {
00516 if (!_tree.untag_named(*gi)) {
00517 mayaegg_cat.info()
00518 << "No node matching " << *gi << " found.\n";
00519 }
00520 }
00521 }
00522 }
00523
00524 if (all_ok) {
00525 switch (get_animation_convert()) {
00526 case AC_pose:
00527
00528 mayaegg_cat.info(false)
00529 << "frame " << start_frame << "\n";
00530 MGlobal::viewFrame(MTime(start_frame, MTime::uiUnit()));
00531
00532
00533 case AC_none:
00534
00535 mayaegg_cat.info() << "ac_none" << endl;
00536 all_ok = convert_hierarchy(get_egg_data());
00537 break;
00538
00539 case AC_flip:
00540 case AC_strobe:
00541
00542
00543 all_ok = convert_flip(start_frame, end_frame, frame_inc,
00544 output_frame_rate);
00545 break;
00546
00547 case AC_model:
00548
00549
00550 all_ok = convert_char_model();
00551 break;
00552
00553 case AC_chan:
00554
00555 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
00556 output_frame_rate);
00557 break;
00558
00559 case AC_both:
00560
00561 _animation_convert = AC_model;
00562 if (!convert_char_model()) {
00563 all_ok = false;
00564 }
00565 _animation_convert = AC_chan;
00566 if (!convert_char_chan(start_frame, end_frame, frame_inc,
00567 output_frame_rate)) {
00568 all_ok = false;
00569 }
00570 break;
00571
00572 case AC_invalid:
00573 break;
00574 };
00575
00576 reparent_decals(get_egg_data());
00577 }
00578
00579 if (had_error()) {
00580 all_ok = false;
00581 }
00582
00583 if (all_ok) {
00584 mayaegg_cat.info()
00585 << "Converted, no errors.\n";
00586 } else {
00587 mayaegg_cat.info()
00588 << "Errors encountered in conversion.\n";
00589 }
00590
00591 return all_ok;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601 bool MayaToEggConverter::
00602 open_api(bool revert_directory) {
00603
00604 if (_maya == (MayaApi *)NULL || !_maya->is_valid()) {
00605
00606
00607 _maya = MayaApi::open_api(_program_name, true, revert_directory);
00608 }
00609 return _maya->is_valid();
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619 void MayaToEggConverter::
00620 close_api() {
00621
00622
00623 clear();
00624 _maya.clear();
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634 void MayaToEggConverter::
00635 clear() {
00636 _tree.clear();
00637 _textures.clear();
00638 _shaders.clear();
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 bool MayaToEggConverter::
00653 convert_flip(double start_frame, double end_frame, double frame_inc,
00654 double output_frame_rate) {
00655 bool all_ok = true;
00656
00657 EggGroup *sequence_node = new EggGroup(_character_name);
00658 get_egg_data()->add_child(sequence_node);
00659 if (_animation_convert == AC_flip) {
00660 sequence_node->set_switch_flag(true);
00661 sequence_node->set_switch_fps(output_frame_rate);
00662 }
00663
00664 MTime frame(start_frame, MTime::uiUnit());
00665 MTime frame_stop(end_frame, MTime::uiUnit());
00666 while (frame <= frame_stop) {
00667 mayaegg_cat.info(false)
00668 << "frame " << frame.value() << "\n";
00669 ostringstream name_strm;
00670 name_strm << "frame" << frame.value();
00671 EggGroup *frame_root = new EggGroup(name_strm.str());
00672 sequence_node->add_child(frame_root);
00673
00674 MGlobal::viewFrame(frame);
00675 if (!convert_hierarchy(frame_root)) {
00676 all_ok = false;
00677 }
00678
00679 frame += frame_inc;
00680 }
00681
00682 return all_ok;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 bool MayaToEggConverter::
00692 convert_char_model() {
00693 if (has_neutral_frame()) {
00694 MTime frame(get_neutral_frame(), MTime::uiUnit());
00695 mayaegg_cat.info(false)
00696 << "neutral frame " << frame.value() << "\n";
00697 MGlobal::viewFrame(frame);
00698 }
00699
00700
00701
00702
00703 _tree.reset_sliders();
00704
00705 EggGroup *char_node = new EggGroup(_character_name);
00706 get_egg_data()->add_child(char_node);
00707 char_node->set_dart_type(EggGroup::DT_default);
00708
00709 return convert_hierarchy(char_node);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719 bool MayaToEggConverter::
00720 convert_char_chan(double start_frame, double end_frame, double frame_inc,
00721 double output_frame_rate) {
00722
00723
00724 EggTable *root_table_node = new EggTable();
00725 get_egg_data()->add_child(root_table_node);
00726 EggTable *bundle_node = new EggTable(_character_name);
00727 bundle_node->set_table_type(EggTable::TT_bundle);
00728 root_table_node->add_child(bundle_node);
00729 EggTable *skeleton_node = new EggTable("<skeleton>");
00730 bundle_node->add_child(skeleton_node);
00731 EggTable *morph_node = new EggTable("morph");
00732 bundle_node->add_child(morph_node);
00733
00734
00735
00736 _tree._fps = output_frame_rate;
00737 _tree.clear_egg(get_egg_data(), NULL, skeleton_node, morph_node);
00738
00739
00740
00741
00742
00743
00744
00745 PT(EggGroup) tgroup = new EggGroup;
00746
00747 int num_nodes = _tree.get_num_nodes();
00748 int num_sliders = _tree.get_num_blend_descs();
00749 int i;
00750
00751 MTime frame(start_frame, MTime::uiUnit());
00752 MTime frame_stop(end_frame, MTime::uiUnit());
00753 while (frame <= frame_stop) {
00754 if (mayaegg_cat.is_spam()) {
00755 mayaegg_cat.spam(false)
00756 << "frame " << frame.value() << "\n";
00757 } else {
00758
00759
00760 cerr << "." << flush;
00761 }
00762 MGlobal::viewFrame(frame);
00763
00764 for (i = 0; i < num_nodes; i++) {
00765 MayaNodeDesc *node_desc = _tree.get_node(i);
00766 if (node_desc->is_joint()) {
00767 if (mayaegg_cat.is_spam()) {
00768 mayaegg_cat.spam()
00769 << "joint " << node_desc->get_name() << "\n";
00770 }
00771 get_joint_transform(node_desc->get_dag_path(), tgroup);
00772 EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
00773 if (!anim->add_data(tgroup->get_transform3d())) {
00774 mayaegg_cat.error()
00775 << "Invalid transform on " << node_desc->get_name()
00776 << " frame " << frame.value() << ".\n";
00777 }
00778 }
00779 }
00780
00781 for (i = 0; i < num_sliders; i++) {
00782 MayaBlendDesc *blend_desc = _tree.get_blend_desc(i);
00783 if (mayaegg_cat.is_spam()) {
00784 mayaegg_cat.spam()
00785 << "slider " << blend_desc->get_name() << "\n";
00786 }
00787 EggSAnimData *anim = _tree.get_egg_slider(blend_desc);
00788 anim->add_data(blend_desc->get_slider());
00789 }
00790
00791 frame += frame_inc;
00792 }
00793
00794
00795
00796
00797 for (i = 0; i < num_nodes; i++) {
00798 MayaNodeDesc *node_desc = _tree.get_node(i);
00799 if (node_desc->is_joint()) {
00800 _tree.get_egg_anim(node_desc)->optimize();
00801 }
00802 }
00803
00804 for (i = 0; i < num_sliders; i++) {
00805 MayaBlendDesc *blend_desc = _tree.get_blend_desc(i);
00806 EggSAnimData *anim = _tree.get_egg_slider(blend_desc);
00807 anim->optimize();
00808 }
00809
00810 mayaegg_cat.info(false)
00811 << "\n";
00812
00813 return true;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822 bool MayaToEggConverter::
00823 convert_hierarchy(EggGroupNode *egg_root) {
00824 int num_nodes = _tree.get_num_nodes();
00825
00826 if (_round_uvs) {
00827 mayaegg_cat.info() << "will round up uv coordinates" << endl;
00828 }
00829
00830 if (_keep_all_uvsets) {
00831 mayaegg_cat.info() << "will keep_all_uvsets" << endl;
00832 }
00833
00834 if (_legacy_shader) {
00835 mayaegg_cat.info() << "will disable modern Phong shader path. using legacy" << endl;
00836 }
00837 _tree.clear_egg(get_egg_data(), egg_root, NULL, NULL);
00838 for (int i = 0; i < num_nodes; i++) {
00839 MayaNodeDesc *node = _tree.get_node(i);
00840 if (!process_model_node(node)) {
00841 return false;
00842 }
00843 }
00844 return true;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 bool MayaToEggConverter::
00856 process_model_node(MayaNodeDesc *node_desc) {
00857 if (!node_desc->has_dag_path()) {
00858
00859 return true;
00860 }
00861
00862 MDagPath dag_path = node_desc->get_dag_path();
00863
00864 MStatus status;
00865 MFnDagNode dag_node(dag_path, &status);
00866 if (!status) {
00867 status.perror("MFnDagNode constructor");
00868 mayaegg_cat.error() << dag_path.fullPathName().asChar() << "\n";
00869 return false;
00870 }
00871
00872 MObject node = dag_path.transform(&status);
00873 if (!status) {
00874 status.perror("dag_path.transform()");
00875 return false;
00876 }
00877
00878 string path = dag_path.fullPathName().asChar();
00879
00880 if (mayaegg_cat.is_debug()) {
00881 mayaegg_cat.debug()
00882 << path << ": " << dag_node.typeName().asChar();
00883
00884 if (MAnimUtil::isAnimated(dag_path)) {
00885 mayaegg_cat.debug(false)
00886 << " (animated)";
00887 }
00888
00889 mayaegg_cat.debug(false) << "\n";
00890 }
00891
00892 if (dag_node.inUnderWorld()) {
00893 if (mayaegg_cat.is_debug()) {
00894 mayaegg_cat.debug()
00895 << "Ignoring underworld node " << path
00896 << "\n";
00897 }
00898
00899 } else if (dag_node.isIntermediateObject()) {
00900 if (mayaegg_cat.is_debug()) {
00901 mayaegg_cat.debug()
00902 << "Ignoring intermediate object " << path
00903 << "\n";
00904 }
00905
00906 } else if (dag_path.hasFn(MFn::kCamera)) {
00907 if (mayaegg_cat.is_debug()) {
00908 mayaegg_cat.debug()
00909 << "Ignoring camera node " << path
00910 << "\n";
00911 }
00912
00913 MFnCamera camera (dag_path, &status);
00914 if ( !status ) {
00915 status.perror("MFnCamera constructor");
00916 mayaegg_cat.error() << "camera extraction failed" << endl;
00917 return false;
00918 }
00919
00920
00921 if (mayaegg_cat.is_spam()) {
00922 MPoint eyePoint = camera.eyePoint(MSpace::kWorld);
00923 mayaegg_cat.spam() << " eyePoint: " << eyePoint.x << " "
00924 << eyePoint.y << " " << eyePoint.z << endl;
00925 mayaegg_cat.spam() << " upDirection: "
00926 << camera.upDirection(MSpace::kWorld) << endl;
00927 mayaegg_cat.spam() << " viewDirection: "
00928 << camera.viewDirection(MSpace::kWorld) << endl;
00929 mayaegg_cat.spam() << " aspectRatio: " << camera.aspectRatio() << endl;
00930 mayaegg_cat.spam() << " horizontalFilmAperture: "
00931 << camera.horizontalFilmAperture() << endl;
00932 mayaegg_cat.spam() << " verticalFilmAperture: "
00933 << camera.verticalFilmAperture() << endl;
00934 }
00935
00936 } else if (dag_path.hasFn(MFn::kLight)) {
00937 if (mayaegg_cat.is_debug()) {
00938 mayaegg_cat.debug()
00939 << "Ignoring light node " << path
00940 << "\n";
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 } else if (dag_path.hasFn(MFn::kNurbsSurface)) {
00971 EggGroup *egg_group = _tree.get_egg_group(node_desc);
00972 get_transform(node_desc, dag_path, egg_group);
00973
00974 if (node_desc->is_tagged()) {
00975 MFnNurbsSurface surface(dag_path, &status);
00976 if (!status) {
00977 mayaegg_cat.info()
00978 << "Error in node " << path
00979 << ":\n"
00980 << " it appears to have a NURBS surface, but does not.\n";
00981 } else {
00982 make_nurbs_surface(node_desc, dag_path, surface, egg_group);
00983 }
00984 }
00985 } else if (dag_path.hasFn(MFn::kNurbsCurve)) {
00986
00987
00988
00989 if (_animation_convert != AC_model) {
00990 EggGroup *egg_group = _tree.get_egg_group(node_desc);
00991 get_transform(node_desc, dag_path, egg_group);
00992
00993 if (node_desc->is_tagged()) {
00994 MFnNurbsCurve curve(dag_path, &status);
00995 if (!status) {
00996 mayaegg_cat.info()
00997 << "Error in node " << path << ":\n"
00998 << " it appears to have a NURBS curve, but does not.\n";
00999 } else {
01000 make_nurbs_curve(dag_path, curve, egg_group);
01001 }
01002 }
01003 }
01004
01005 } else if (dag_path.hasFn(MFn::kMesh)) {
01006 if (node_desc->is_tagged()) {
01007 EggGroup *egg_group = _tree.get_egg_group(node_desc);
01008 get_transform(node_desc, dag_path, egg_group);
01009 MFnMesh mesh(dag_path, &status);
01010 if (!status) {
01011 mayaegg_cat.info()
01012 << "Error in node " << path << ":\n"
01013 << " it appears to have a polygon mesh, but does not.\n";
01014 } else {
01015 make_polyset(node_desc, dag_path, mesh, egg_group);
01016 }
01017 }
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 } else if (dag_path.hasFn(MFn::kLocator)) {
01034 if (_animation_convert == AC_none) {
01035 if (!node_desc->is_tagged()) {
01036 return true;
01037 }
01038 }
01039 EggGroup *egg_group = _tree.get_egg_group(node_desc);
01040
01041 if (mayaegg_cat.is_debug()) {
01042 mayaegg_cat.debug()
01043 << "Locator at " << path << "\n";
01044 }
01045
01046 if (node_desc->is_tagged()) {
01047
01048
01049
01050 if (_animation_convert != AC_model) {
01051
01052
01053
01054
01055 egg_group->set_dcs_type(EggGroup::DC_net);
01056 }
01057 get_transform(node_desc, dag_path, egg_group);
01058 make_locator(dag_path, dag_node, egg_group);
01059 }
01060
01061 } else {
01062
01063 if (_animation_convert == AC_none) {
01064 if (!node_desc->is_tagged()) {
01065 return true;
01066 }
01067 }
01068 EggGroup *egg_group = _tree.get_egg_group(node_desc);
01069 get_transform(node_desc, dag_path, egg_group);
01070 }
01071
01072 return true;
01073 }
01074
01075
01076
01077
01078
01079
01080
01081 void MayaToEggConverter::
01082 get_transform(MayaNodeDesc *node_desc, const MDagPath &dag_path,
01083 EggGroup *egg_group) {
01084 if (_animation_convert == AC_model) {
01085
01086
01087
01088 if (node_desc->is_joint()) {
01089 if (mayaegg_cat.is_spam()) {
01090 mayaegg_cat.spam()
01091 << "gt: joint " << node_desc->get_name() << "\n";
01092 }
01093 get_joint_transform(dag_path, egg_group);
01094 }
01095 return;
01096 }
01097
01098 MStatus status;
01099 MObject transformNode = dag_path.transform(&status);
01100 if (!status && status.statusCode() == MStatus::kInvalidParameter) {
01101
01102 return;
01103 }
01104
01105
01106 if (egg_group->get_billboard_type() == EggGroup::BT_none) {
01107 switch (_transform_type) {
01108 case TT_all:
01109 break;
01110
01111 case TT_model:
01112 if (!egg_group->get_model_flag() && !egg_group->has_dcs_type()) {
01113 return;
01114 }
01115 break;
01116
01117 case TT_dcs:
01118 if (!egg_group->has_dcs_type()) {
01119 return;
01120 }
01121 break;
01122
01123 case TT_none:
01124 case TT_invalid:
01125 return;
01126 }
01127 }
01128
01129
01130 MMatrix mat = dag_path.inclusiveMatrix(&status);
01131 if (!status) {
01132 status.perror("Can't get transform matrix");
01133 return;
01134 }
01135 LMatrix4d m4d(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
01136 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
01137 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
01138 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
01139
01140
01141
01142
01143 MFnTransform transform(transformNode, &status);
01144 if (!status) {
01145 status.perror("MFnTransform constructor");
01146 return;
01147 }
01148 MPoint pivot = transform.rotatePivot(MSpace::kObject, &status);
01149 if (!status) {
01150 status.perror("Can't get rotate pivot");
01151 return;
01152 }
01153
01154
01155
01156 LPoint3d p3d(pivot[0], pivot[1], pivot[2]);
01157 p3d = p3d * m4d;
01158
01159
01160 m4d.set_row(3, p3d);
01161
01162
01163
01164 m4d = m4d * egg_group->get_node_frame_inv();
01165 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
01166 egg_group->add_matrix4(m4d);
01167 }
01168 return;
01169 }
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 void MayaToEggConverter::
01182 get_joint_transform(const MDagPath &dag_path, EggGroup *egg_group) {
01183
01184 egg_group->clear_transform();
01185
01186 MStatus status;
01187 MObject transformNode = dag_path.transform(&status);
01188
01189 if (!status && status.statusCode() == MStatus::kInvalidParameter) {
01190 return;
01191 }
01192
01193 MFnDagNode transform(transformNode, &status);
01194 if (!status) {
01195 status.perror("MFnDagNode constructor");
01196 return;
01197 }
01198
01199 MTransformationMatrix matrix(transform.transformationMatrix());
01200
01201 if (mayaegg_cat.is_spam()) {
01202 MVector t = matrix.translation(MSpace::kWorld);
01203 mayaegg_cat.spam()
01204 << " translation: ["
01205 << t[0] << ", "
01206 << t[1] << ", "
01207 << t[2] << "]\n";
01208 double d[3];
01209 MTransformationMatrix::RotationOrder rOrder;
01210
01211 matrix.getRotation(d, rOrder, MSpace::kWorld);
01212 mayaegg_cat.spam()
01213 << " rotation: ["
01214 << d[0] << ", "
01215 << d[1] << ", "
01216 << d[2] << "]\n";
01217 matrix.getScale(d, MSpace::kWorld);
01218 mayaegg_cat.spam()
01219 << " scale: ["
01220 << d[0] << ", "
01221 << d[1] << ", "
01222 << d[2] << "]\n";
01223 matrix.getShear(d, MSpace::kWorld);
01224 mayaegg_cat.spam()
01225 << " shear: ["
01226 << d[0] << ", "
01227 << d[1] << ", "
01228 << d[2] << "]\n";
01229 }
01230
01231 MMatrix mat = matrix.asMatrix();
01232 MMatrix ident_mat;
01233 ident_mat.setToIdentity();
01234
01235 if (!mat.isEquivalent(ident_mat, 0.0001)) {
01236 egg_group->set_transform3d
01237 (LMatrix4d(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
01238 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
01239 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
01240 mat[3][0], mat[3][1], mat[3][2], mat[3][3]));
01241 }
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251 void MayaToEggConverter::
01252 make_nurbs_surface(MayaNodeDesc *node_desc, const MDagPath &dag_path,
01253 MFnNurbsSurface &surface, EggGroup *egg_group) {
01254 MStatus status;
01255 string name = surface.name().asChar();
01256
01257 if (mayaegg_cat.is_spam()) {
01258 mayaegg_cat.spam()
01259 << " numCVs: "
01260 << surface.numCVsInU()
01261 << " * "
01262 << surface.numCVsInV()
01263 << "\n";
01264 mayaegg_cat.spam()
01265 << " numKnots: "
01266 << surface.numKnotsInU()
01267 << " * "
01268 << surface.numKnotsInV()
01269 << "\n";
01270 mayaegg_cat.spam()
01271 << " numSpans: "
01272 << surface.numSpansInU()
01273 << " * "
01274 << surface.numSpansInV()
01275 << "\n";
01276 }
01277 MayaShader *shader = _shaders.find_shader_for_node(surface.object(), _legacy_shader);
01278
01279 if (_polygon_output) {
01280
01281
01282 MTesselationParams params;
01283 params.setFormatType(MTesselationParams::kStandardFitFormat);
01284 params.setOutputType(MTesselationParams::kQuads);
01285 params.setStdFractionalTolerance(_polygon_tolerance);
01286
01287
01288
01289 MDagPath polyset_path = dag_path;
01290 MObject polyset_parent = polyset_path.node();
01291 MObject polyset =
01292 surface.tesselate(params, polyset_parent, &status);
01293 if (!status) {
01294 status.perror("MFnNurbsSurface::tesselate");
01295 return;
01296 }
01297
01298 status = polyset_path.push(polyset);
01299 if (!status) {
01300 status.perror("MDagPath::push");
01301 }
01302
01303 MFnMesh polyset_fn(polyset, &status);
01304 if (!status) {
01305 status.perror("MFnMesh constructor");
01306 return;
01307 }
01308 make_polyset(node_desc, polyset_path, polyset_fn, egg_group, shader);
01309
01310
01311 MFnDagNode parent_node(polyset_parent, &status);
01312 if (!status) {
01313 status.perror("MFnDagNode constructor");
01314 return;
01315 }
01316 status = parent_node.removeChild(polyset);
01317 if (!status) {
01318 status.perror("MFnDagNode::removeChild");
01319 }
01320
01321 return;
01322 }
01323
01324 MPointArray cv_array;
01325 status = surface.getCVs(cv_array, MSpace::kWorld);
01326 if (!status) {
01327 status.perror("MFnNurbsSurface::getCVs");
01328 return;
01329 }
01330
01331
01332
01333 pvector<MPointArray> morph_cvs;
01334 if (_animation_convert == AC_model) {
01335 int num_sliders = node_desc->get_num_blend_descs();
01336 morph_cvs.reserve(num_sliders);
01337 for (int i = 0; i < num_sliders; i++) {
01338 MayaBlendDesc *blend_desc = node_desc->get_blend_desc(i);
01339
01340
01341
01342 blend_desc->set_slider(1.0);
01343 MPointArray cv_array;
01344 status = surface.getCVs(cv_array, MSpace::kWorld);
01345 blend_desc->set_slider(0.0);
01346
01347 if (!status) {
01348 status.perror("MFnNurbsSurface::getCVs");
01349 return;
01350 }
01351 morph_cvs.push_back(cv_array);
01352 }
01353 }
01354
01355 MDoubleArray u_knot_array, v_knot_array;
01356 status = surface.getKnotsInU(u_knot_array);
01357 if (!status) {
01358 status.perror("MFnNurbsSurface::getKnotsInU");
01359 return;
01360 }
01361 status = surface.getKnotsInV(v_knot_array);
01362 if (!status) {
01363 status.perror("MFnNurbsSurface::getKnotsInV");
01364 return;
01365 }
01366
01367 MFnNurbsSurface::Form u_form = surface.formInU();
01368 MFnNurbsSurface::Form v_form = surface.formInV();
01369
01370 int u_degree = surface.degreeU();
01371 int v_degree = surface.degreeV();
01372
01373 int u_cvs = surface.numCVsInU();
01374 int v_cvs = surface.numCVsInV();
01375
01376
01377
01378 int maya_u_cvs = (u_form == MFnNurbsSurface::kPeriodic) ? u_cvs - u_degree : u_cvs;
01379 int maya_v_cvs = (v_form == MFnNurbsSurface::kPeriodic) ? v_cvs - v_degree : v_cvs;
01380
01381 int u_knots = surface.numKnotsInU();
01382 int v_knots = surface.numKnotsInV();
01383
01384 assert(u_knots == u_cvs + u_degree - 1);
01385 assert(v_knots == v_cvs + v_degree - 1);
01386
01387 string vpool_name = name + ".cvs";
01388 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01389 egg_group->add_child(vpool);
01390
01391 EggNurbsSurface *egg_nurbs = new EggNurbsSurface(name);
01392 egg_nurbs->setup(u_degree + 1, v_degree + 1,
01393 u_knots + 2, v_knots + 2);
01394
01395 int i;
01396
01397 egg_nurbs->set_u_knot(0, u_knot_array[0]);
01398 for (i = 0; i < u_knots; i++) {
01399 egg_nurbs->set_u_knot(i + 1, u_knot_array[i]);
01400 }
01401 egg_nurbs->set_u_knot(u_knots + 1, u_knot_array[u_knots - 1]);
01402
01403 egg_nurbs->set_v_knot(0, v_knot_array[0]);
01404 for (i = 0; i < v_knots; i++) {
01405 egg_nurbs->set_v_knot(i + 1, v_knot_array[i]);
01406 }
01407 egg_nurbs->set_v_knot(v_knots + 1, v_knot_array[v_knots - 1]);
01408
01409 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01410
01411 for (i = 0; i < egg_nurbs->get_num_cvs(); i++) {
01412 int ui = egg_nurbs->get_u_index(i);
01413 int vi = egg_nurbs->get_v_index(i);
01414 int maya_vi = v_cvs * ui + vi;
01415
01416 double v[4];
01417 status = cv_array[maya_vi].get(v);
01418 if (!status) {
01419 status.perror("MPoint::get");
01420 } else {
01421 EggVertex *vert = vpool->add_vertex(new EggVertex, i);
01422 LPoint4d p4d(v[0], v[1], v[2], v[3]);
01423 p4d = p4d * vertex_frame_inv;
01424 vert->set_pos(p4d);
01425
01426
01427 if (!morph_cvs.empty()) {
01428
01429
01430 LPoint3d p3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
01431
01432 for (unsigned int si = 0; si < morph_cvs.size(); si++) {
01433 MayaBlendDesc *blend_desc = node_desc->get_blend_desc(si);
01434 status = morph_cvs[si][maya_vi].get(v);
01435 if (!status) {
01436 status.perror("MPoint::get");
01437 } else {
01438 LPoint3d m3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
01439 LVector3d delta = m3d - p3d;
01440 if (!delta.almost_equal(LVector3d::zero())) {
01441 EggMorphVertex dxyz(blend_desc->get_name(), delta);
01442 vert->_dxyzs.insert(dxyz);
01443 }
01444 }
01445 }
01446 }
01447
01448 egg_nurbs->add_vertex(vert);
01449 }
01450 }
01451
01452
01453 unsigned num_trims = surface.numRegions();
01454 int trim_curve_index = 0;
01455 for (unsigned ti = 0; ti < num_trims; ti++) {
01456 unsigned num_loops = surface.numBoundaries(ti);
01457
01458 if (num_loops > 0) {
01459 egg_nurbs->_trims.push_back(EggNurbsSurface::Trim());
01460 EggNurbsSurface::Trim &egg_trim = egg_nurbs->_trims.back();
01461
01462 for (unsigned li = 0; li < num_loops; li++) {
01463 egg_trim.push_back(EggNurbsSurface::Loop());
01464 EggNurbsSurface::Loop &egg_loop = egg_trim.back();
01465
01466 MFnNurbsSurface::BoundaryType type =
01467 surface.boundaryType(ti, li, &status);
01468 bool keep_loop = false;
01469
01470 if (!status) {
01471 status.perror("MFnNurbsSurface::BoundaryType");
01472 } else {
01473 keep_loop = (type == MFnNurbsSurface::kInner ||
01474 type == MFnNurbsSurface::kOuter);
01475 }
01476
01477 if (keep_loop) {
01478 unsigned num_edges = surface.numEdges(ti, li);
01479 for (unsigned ei = 0; ei < num_edges; ei++) {
01480 MObjectArray edge = surface.edge(ti, li, ei, true, &status);
01481 if (!status) {
01482 status.perror("MFnNurbsSurface::edge");
01483 } else {
01484 unsigned num_segs = edge.length();
01485 for (unsigned si = 0; si < num_segs; si++) {
01486 MObject segment = edge[si];
01487 if (segment.hasFn(MFn::kNurbsCurve)) {
01488 MFnNurbsCurve curve(segment, &status);
01489 if (!status) {
01490 mayaegg_cat.error()
01491 << "Trim curve appears to be a nurbs curve, but isn't.\n";
01492 } else {
01493
01494 EggNurbsCurve *egg_curve =
01495 make_trim_curve(curve, name, egg_group, trim_curve_index);
01496 trim_curve_index++;
01497 if (egg_curve != (EggNurbsCurve *)NULL) {
01498 egg_loop.push_back(egg_curve);
01499 }
01500 }
01501 } else {
01502 mayaegg_cat.error()
01503 << "Trim curve segment is not a nurbs curve.\n";
01504 }
01505 }
01506 }
01507 }
01508 }
01509 }
01510 }
01511 }
01512
01513
01514
01515 egg_group->add_child(egg_nurbs);
01516
01517 if (shader != (MayaShader *)NULL) {
01518 set_shader_attributes(*egg_nurbs, *shader);
01519 }
01520
01521
01522 bool got_weights = false;
01523
01524 pvector<EggGroup *> joints;
01525 MFloatArray weights;
01526 if (_animation_convert == AC_model) {
01527 got_weights =
01528 get_vertex_weights(dag_path, surface, joints, weights);
01529 }
01530
01531 if (got_weights && !joints.empty()) {
01532 int num_joints = joints.size();
01533 int num_weights = (int)weights.length();
01534 int num_verts = num_weights / num_joints;
01535
01536
01537 nassertv(num_weights == num_verts * num_joints);
01538
01539 for (i = 0; i < egg_nurbs->get_num_cvs(); i++) {
01540 int ui = egg_nurbs->get_u_index(i) % maya_u_cvs;
01541 int vi = egg_nurbs->get_v_index(i) % maya_v_cvs;
01542
01543 int maya_vi = maya_v_cvs * ui + vi;
01544 nassertv(maya_vi < num_verts);
01545 EggVertex *vert = vpool->get_vertex(i);
01546
01547 for (int ji = 0; ji < num_joints; ++ji) {
01548 PN_stdfloat weight = weights[maya_vi * num_joints + ji];
01549 if (weight != 0.0f) {
01550 EggGroup *joint = joints[ji];
01551 if (joint != (EggGroup *)NULL) {
01552 joint->ref_vertex(vert, weight);
01553 }
01554 }
01555 }
01556 }
01557 }
01558 }
01559
01560
01561
01562
01563
01564
01565
01566
01567 EggNurbsCurve *MayaToEggConverter::
01568 make_trim_curve(const MFnNurbsCurve &curve, const string &nurbs_name,
01569 EggGroupNode *egg_group, int trim_curve_index) {
01570 if (mayaegg_cat.is_spam()) {
01571 mayaegg_cat.spam()
01572 << "Trim curve:\n";
01573 mayaegg_cat.spam()
01574 << " numCVs: "
01575 << curve.numCVs()
01576 << "\n";
01577 mayaegg_cat.spam()
01578 << " numKnots: "
01579 << curve.numKnots()
01580 << "\n";
01581 mayaegg_cat.spam()
01582 << " numSpans: "
01583 << curve.numSpans()
01584 << "\n";
01585 }
01586
01587 MStatus status;
01588
01589 MPointArray cv_array;
01590 status = curve.getCVs(cv_array, MSpace::kWorld);
01591 if (!status) {
01592 status.perror("MFnNurbsCurve::getCVs");
01593 return (EggNurbsCurve *)NULL;
01594 }
01595 MDoubleArray knot_array;
01596 status = curve.getKnots(knot_array);
01597 if (!status) {
01598 status.perror("MFnNurbsCurve::getKnots");
01599 return (EggNurbsCurve *)NULL;
01600 }
01601
01602
01603
01604
01605
01606 int degree = curve.degree();
01607 int cvs = curve.numCVs();
01608 int knots = curve.numKnots();
01609
01610 assert(knots == cvs + degree - 1);
01611
01612 string trim_name = "trim" + format_string(trim_curve_index);
01613
01614 string vpool_name = nurbs_name + "." + trim_name;
01615 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01616 egg_group->add_child(vpool);
01617
01618 EggNurbsCurve *egg_curve = new EggNurbsCurve(trim_name);
01619 egg_curve->setup(degree + 1, knots + 2);
01620
01621 int i;
01622
01623 egg_curve->set_knot(0, knot_array[0]);
01624 for (i = 0; i < knots; i++) {
01625 egg_curve->set_knot(i + 1, knot_array[i]);
01626 }
01627 egg_curve->set_knot(knots + 1, knot_array[knots - 1]);
01628
01629 for (i = 0; i < egg_curve->get_num_cvs(); i++) {
01630 double v[4];
01631 MStatus status = cv_array[i].get(v);
01632 if (!status) {
01633 status.perror("MPoint::get");
01634 } else {
01635 EggVertex vert;
01636 vert.set_pos(LPoint3d(v[0], v[1], v[3]));
01637 egg_curve->add_vertex(vpool->create_unique_vertex(vert));
01638 }
01639 }
01640
01641 return egg_curve;
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651 void MayaToEggConverter::
01652 make_nurbs_curve(const MDagPath &, const MFnNurbsCurve &curve,
01653 EggGroup *egg_group) {
01654 MStatus status;
01655 string name = curve.name().asChar();
01656
01657 if (mayaegg_cat.is_spam()) {
01658 mayaegg_cat.spam()
01659 << " numCVs: "
01660 << curve.numCVs()
01661 << "\n";
01662 mayaegg_cat.spam()
01663 << " numKnots: "
01664 << curve.numKnots()
01665 << "\n";
01666 mayaegg_cat.spam()
01667 << " numSpans: "
01668 << curve.numSpans()
01669 << "\n";
01670 }
01671
01672 MPointArray cv_array;
01673 status = curve.getCVs(cv_array, MSpace::kWorld);
01674 if (!status) {
01675 status.perror("MFnNurbsCurve::getCVs");
01676 return;
01677 }
01678 MDoubleArray knot_array;
01679 status = curve.getKnots(knot_array);
01680 if (!status) {
01681 status.perror("MFnNurbsCurve::getKnots");
01682 return;
01683 }
01684
01685
01686
01687
01688
01689 int degree = curve.degree();
01690 int cvs = curve.numCVs();
01691 int knots = curve.numKnots();
01692
01693 assert(knots == cvs + degree - 1);
01694
01695 string vpool_name = name + ".cvs";
01696 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01697 egg_group->add_child(vpool);
01698
01699 EggNurbsCurve *egg_curve = new EggNurbsCurve(name);
01700 egg_group->add_child(egg_curve);
01701 egg_curve->setup(degree + 1, knots + 2);
01702
01703 int i;
01704
01705 egg_curve->set_knot(0, knot_array[0]);
01706 for (i = 0; i < knots; i++) {
01707 egg_curve->set_knot(i + 1, knot_array[i]);
01708 }
01709 egg_curve->set_knot(knots + 1, knot_array[knots - 1]);
01710
01711 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01712
01713 for (i = 0; i < egg_curve->get_num_cvs(); i++) {
01714 double v[4];
01715 MStatus status = cv_array[i].get(v);
01716 if (!status) {
01717 status.perror("MPoint::get");
01718 } else {
01719 EggVertex vert;
01720 LPoint4d p4d(v[0], v[1], v[2], v[3]);
01721 p4d = p4d * vertex_frame_inv;
01722 vert.set_pos(p4d);
01723 egg_curve->add_vertex(vpool->create_unique_vertex(vert));
01724 }
01725 }
01726 MayaShader *shader = _shaders.find_shader_for_node(curve.object(), _legacy_shader);
01727 if (shader != (MayaShader *)NULL) {
01728 set_shader_attributes(*egg_curve, *shader);
01729 }
01730 }
01731
01732
01733
01734
01735
01736
01737 int MayaToEggConverter::
01738 round(double value) {
01739 if (value < 0)
01740 return -(floor(-value + 0.5));
01741
01742
01743 else
01744 return floor( value + 0.5);
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754 void MayaToEggConverter::
01755 make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path,
01756 const MFnMesh &mesh, EggGroup *egg_group,
01757 MayaShader *default_shader) {
01758 MStatus status;
01759 string name = mesh.name().asChar();
01760
01761 MObject mesh_object = mesh.object();
01762 bool maya_double_sided = false;
01763 get_bool_attribute(mesh_object, "doubleSided", maya_double_sided);
01764
01765 if (mayaegg_cat.is_spam()) {
01766 mayaegg_cat.spam()
01767 << " numPolygons: "
01768 << mesh.numPolygons()
01769 << "\n";
01770 mayaegg_cat.spam()
01771 << " numVertices: "
01772 << mesh.numVertices()
01773 << "\n";
01774 }
01775
01776 if (mesh.numPolygons() == 0) {
01777 if (mayaegg_cat.is_debug()) {
01778 mayaegg_cat.debug()
01779 << "Ignoring empty mesh " << name << "\n";
01780 }
01781 return;
01782 }
01783
01784 string vpool_name = name + ".verts";
01785 EggVertexPool *vpool = new EggVertexPool(vpool_name);
01786 egg_group->add_child(vpool);
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800 MObject component_obj;
01801 MItMeshPolygon pi(dag_path, component_obj, &status);
01802 if (!status) {
01803 status.perror("MItMeshPolygon constructor");
01804 return;
01805 }
01806
01807 MObjectArray shaders;
01808 MIntArray poly_shader_indices;
01809
01810 status = mesh.getConnectedShaders(dag_path.instanceNumber(),
01811 shaders, poly_shader_indices);
01812 if (!status) {
01813 status.perror("MFnMesh::getConnectedShaders");
01814 }
01815
01816
01817
01818
01819
01820
01821
01822 LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
01823
01824
01825 bool egg_vertex_color = false;
01826 bool egg_double_sided = false;
01827 if (egg_group->has_user_data(MayaEggGroupUserData::get_class_type())) {
01828 MayaEggGroupUserData *user_data =
01829 DCAST(MayaEggGroupUserData, egg_group->get_user_data());
01830 egg_vertex_color = user_data->_vertex_color;
01831 egg_double_sided = user_data->_double_sided;
01832 }
01833
01834 bool double_sided = maya_double_sided;
01835 if (!_respect_maya_double_sided) {
01836
01837
01838 if (!egg_double_sided) {
01839 double_sided = false;
01840 }
01841 }
01842
01843 bool keep_all_uvsets = _keep_all_uvsets || node_desc->has_object_type("keep-all-uvsets");
01844 if (node_desc->has_object_type("keep-all-uvsets")) {
01845 mayaegg_cat.info() << "will keep_all_uvsets" << endl;
01846 }
01847
01848 _shaders.bind_uvsets(mesh.object());
01849
01850 while (!pi.isDone()) {
01851 EggPolygon *egg_poly = new EggPolygon;
01852 egg_group->add_child(egg_poly);
01853
01854 egg_poly->set_bface_flag(double_sided);
01855
01856
01857
01858
01859 MayaShader *shader = NULL;
01860 int index = pi.index();
01861 nassertv(index >= 0 && index < (int)poly_shader_indices.length());
01862 int shader_index = poly_shader_indices[index];
01863
01864 if (shader_index != -1) {
01865 nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
01866 MObject engine = shaders[shader_index];
01867 shader =
01868 _shaders.find_shader_for_shading_engine(engine, _legacy_shader);
01869
01870 } else if (default_shader != (MayaShader *)NULL) {
01871 shader = default_shader;
01872 }
01873
01874 const MayaShaderColorDef *default_color_def = NULL;
01875
01876
01877 if (shader != (MayaShader *)NULL) {
01878 set_shader_attributes(*egg_poly, *shader, true);
01879 default_color_def = shader->get_color_def();
01880 }
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894 bool ignore_vertex_color = false;
01895 if ( default_color_def != (MayaShaderColorDef *)NULL) {
01896 ignore_vertex_color = default_color_def->_has_texture && !(egg_vertex_color || _always_show_vertex_color);
01897 }
01898
01899 LColor poly_color(1.0f, 1.0f, 1.0f, 1.0f);
01900 if (!ignore_vertex_color) {
01901
01902
01903
01904 poly_color = egg_poly->get_color();
01905 egg_poly->clear_color();
01906 }
01907
01908
01909 long num_verts = pi.polygonVertexCount();
01910 long i;
01911 LPoint3d centroid(0.0, 0.0, 0.0);
01912
01913 if (default_color_def != (MayaShaderColorDef *)NULL && default_color_def->has_projection()) {
01914
01915
01916 for (i = 0; i < num_verts; i++) {
01917 MPoint p = pi.point(i, MSpace::kWorld);
01918 LPoint3d p3d(p[0], p[1], p[2]);
01919 p3d = p3d * vertex_frame_inv;
01920 centroid += p3d;
01921 }
01922 centroid /= (double)num_verts;
01923 }
01924 for (i = 0; i < num_verts; i++) {
01925 EggVertex vert;
01926
01927 MPoint p = pi.point(i, MSpace::kWorld);
01928 LPoint3d p3d(p[0] / p[3], p[1] / p[3], p[2] / p[3]);
01929 p3d = p3d * vertex_frame_inv;
01930 vert.set_pos(p3d);
01931
01932 MVector n;
01933 status = pi.getNormal(i, n, MSpace::kWorld);
01934 if (!status) {
01935 status.perror("MItMeshPolygon::getNormal");
01936 } else {
01937 LNormald n3d(n[0], n[1], n[2]);
01938 n3d = n3d * vertex_frame_inv;
01939 vert.set_normal(n3d);
01940 }
01941
01942
01943 if (mayaegg_cat.is_spam()) {
01944 if (shader != (MayaShader *)NULL) {
01945 mayaegg_cat.spam() << "shader->_color.size is " << shader->_color.size() << endl;
01946 }
01947 mayaegg_cat.spam() << "primitive->tref.size is " << egg_poly->get_num_textures() << endl;
01948 }
01949 for (size_t ti=0; ti< _shaders._uvset_names.size(); ++ti) {
01950
01951 string uvset_name(_shaders._uvset_names[ti]);
01952 string panda_uvset_name = uvset_name;
01953 if (panda_uvset_name == "map1") {
01954 panda_uvset_name = "default";
01955 }
01956 if (mayaegg_cat.is_spam()) {
01957 mayaegg_cat.spam() << "--uvset_name :" << uvset_name << endl;
01958 }
01959
01960
01961
01962
01963
01964 bool keep_uv = keep_all_uvsets;
01965 bool project_uv = false;
01966 LTexCoordd uv_projection;
01967
01968 if (shader != (MayaShader *)NULL) {
01969 for (size_t tj = 0; tj < shader->_all_maps.size(); ++tj) {
01970 MayaShaderColorDef *def = shader->_all_maps[tj];
01971 if (def->_uvset_name == uvset_name) {
01972 if (mayaegg_cat.is_spam()) {
01973 mayaegg_cat.spam() << "matched colordef idx: " << tj << endl;
01974 }
01975 keep_uv = true;
01976 if (def->has_projection()) {
01977 project_uv = true;
01978 uv_projection = def->project_uv(p3d, centroid);
01979 }
01980 break;
01981 }
01982 }
01983 }
01984
01985
01986 if (!keep_uv) {
01987 if (mayaegg_cat.is_spam()) {
01988 mayaegg_cat.spam() << "discarding unused uvset " << uvset_name << endl;
01989 }
01990 continue;
01991 }
01992
01993 if (project_uv) {
01994
01995
01996 vert.set_uv(panda_uvset_name, uv_projection);
01997 } else {
01998
01999 float2 uvs;
02000 MString uv_mstring(uvset_name.c_str());
02001 if (pi.hasUVs(uv_mstring, &status)) {
02002 status = pi.getUV(i, uvs, &uv_mstring);
02003 if (!status) {
02004 status.perror("MItMeshPolygon::getUV");
02005 } else {
02006 if (_round_uvs) {
02007 if (uvs[0] > 1.0 || uvs[0] < -1.0) {
02008
02009 uvs[0] = (long)(uvs[0]*1000);
02010 mayaegg_cat.debug() << "before rounding uvs[0]: " << uvs[0] << endl;
02011 uvs[0] = (double)(round((double)uvs[0]/10.0)*10.0)/1000.0;
02012 mayaegg_cat.debug() << "after rounding uvs[0]: " << uvs[0] << endl;
02013 }
02014 if (uvs[1] > 1.0 || uvs[1] < -1.0) {
02015 uvs[1] = (long)(uvs[1]*1000);
02016 mayaegg_cat.debug() << "before rounding uvs[1]: " << uvs[1] << endl;
02017 uvs[1] = (double)(round((double)uvs[1]/10.0)*10.0)/1000.0;
02018 mayaegg_cat.debug() << "after rounding uvs[1]: " << uvs[1] << endl;
02019 }
02020 }
02021 vert.set_uv(panda_uvset_name, LTexCoordd(uvs[0], uvs[1]));
02022 }
02023 }
02024 }
02025 }
02026
02027 if (!ignore_vertex_color) {
02028 if (mayaegg_cat.is_spam()) {
02029 mayaegg_cat.spam() << "poly_color = " << poly_color << endl;
02030 }
02031 set_vertex_color(vert,pi,i,shader,poly_color);
02032 }
02033
02034 vert.set_external_index(pi.vertexIndex(i, &status));
02035 vert.set_external_index2(pi.normalIndex(i, &status));
02036
02037 egg_poly->add_vertex(vpool->create_unique_vertex(vert));
02038 }
02039
02040
02041 LNormald face_normal;
02042 bool got_face_normal = false;
02043
02044 MVector n;
02045 status = pi.getNormal(n, MSpace::kWorld);
02046 if (!status) {
02047 status.perror("MItMeshPolygon::getNormal face");
02048 } else {
02049 face_normal.set(n[0], n[1], n[2]);
02050 face_normal = face_normal * vertex_frame_inv;
02051 got_face_normal = true;
02052 egg_poly->set_normal(face_normal);
02053 }
02054
02055
02056
02057
02058
02059 LNormald order_normal;
02060 if (got_face_normal && egg_poly->calculate_normal(order_normal)) {
02061 if (order_normal.dot(face_normal) < 0.0) {
02062 egg_poly->reverse_vertex_ordering();
02063 if (mayaegg_cat.is_debug()) {
02064 mayaegg_cat.debug()
02065 << "reversing polygon\n";
02066 }
02067 }
02068 }
02069
02070 pi.next();
02071 }
02072 if (mayaegg_cat.is_spam()) {
02073 mayaegg_cat.spam() << "done traversing polys" << endl;
02074 }
02075
02076
02077
02078
02079 bool got_weights = false;
02080
02081 pvector<EggGroup *> joints;
02082 MFloatArray weights;
02083 if (_animation_convert == AC_model) {
02084 got_weights =
02085 get_vertex_weights(dag_path, mesh, joints, weights);
02086 }
02087
02088 if (got_weights && !joints.empty()) {
02089 int num_joints = joints.size();
02090 int num_weights = (int)weights.length();
02091 int num_verts = num_weights / num_joints;
02092
02093
02094 nassertv(num_weights == num_verts * num_joints);
02095
02096 EggVertexPool::iterator vi;
02097 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
02098 EggVertex *vert = (*vi);
02099 int maya_vi = vert->get_external_index();
02100 nassertv(maya_vi >= 0 && maya_vi < num_verts);
02101
02102 for (int ji = 0; ji < num_joints; ++ji) {
02103 PN_stdfloat weight = weights[maya_vi * num_joints + ji];
02104 if (weight != 0.0f) {
02105 EggGroup *joint = joints[ji];
02106 if (joint != (EggGroup *)NULL) {
02107 joint->ref_vertex(vert, weight);
02108 }
02109 }
02110 }
02111 }
02112 }
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 if (_animation_convert == AC_model) {
02123 int num_orig_mesh_verts = mesh.numVertices();
02124
02125 int num_sliders = node_desc->get_num_blend_descs();
02126 for (int i = 0; i < num_sliders; i++) {
02127 MayaBlendDesc *blend_desc = node_desc->get_blend_desc(i);
02128
02129
02130
02131 blend_desc->set_slider(1.0);
02132
02133
02134
02135 MFnMesh blend_mesh(dag_path, &status);
02136 if (!status) {
02137 mayaegg_cat.warning()
02138 << name << " no longer has a mesh after applying "
02139 << blend_desc->get_name() << "\n";
02140
02141 } else {
02142 if (blend_mesh.numVertices() != num_orig_mesh_verts) {
02143 mayaegg_cat.warning()
02144 << "Ignoring " << blend_desc->get_name() << " for "
02145 << name << "; blend shape has " << blend_mesh.numVertices()
02146 << " vertices while original shape has "
02147 << num_orig_mesh_verts << ".\n";
02148
02149 } else {
02150 MPointArray verts;
02151 status = blend_mesh.getPoints(verts, MSpace::kWorld);
02152 if (!status) {
02153 status.perror("MFnMesh::getPoints");
02154 } else {
02155 int num_verts = (int)verts.length();
02156 EggVertexPool::iterator vi;
02157 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
02158 EggVertex *vert = (*vi);
02159 int maya_vi = vert->get_external_index();
02160 nassertv(maya_vi >= 0 && maya_vi < num_verts);
02161
02162 const MPoint &m = verts[maya_vi];
02163 LPoint3d m3d(m[0] / m[3], m[1] / m[3], m[2] / m[3]);
02164 m3d = m3d * vertex_frame_inv;
02165
02166 LVector3d delta = m3d - vert->get_pos3();
02167 if (!delta.almost_equal(LVector3d::zero())) {
02168 EggMorphVertex dxyz(blend_desc->get_name(), delta);
02169 vert->_dxyzs.insert(dxyz);
02170 }
02171 }
02172 }
02173
02174 MFloatVectorArray norms;
02175 status = blend_mesh.getNormals(norms, MSpace::kWorld);
02176 if (!status) {
02177 status.perror("MFnMesh::getNormals");
02178 } else {
02179 int num_norms = (int)norms.length();
02180 EggVertexPool::iterator vi;
02181 for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
02182 EggVertex *vert = (*vi);
02183 int maya_vi = vert->get_external_index2();
02184 nassertv(maya_vi >= 0 && maya_vi < num_norms);
02185
02186 const MFloatVector &m = norms[maya_vi];
02187 LVector3d m3d(m[0], m[1], m[2]);
02188 m3d = m3d * vertex_frame_inv;
02189
02190 LNormald delta = m3d - vert->get_normal();
02191 if (!delta.almost_equal(LVector3d::zero())) {
02192 EggMorphNormal dnormal(blend_desc->get_name(), delta);
02193 vert->_dnormals.insert(dnormal);
02194 }
02195 }
02196 }
02197 }
02198 }
02199
02200 blend_desc->set_slider(0.0);
02201 }
02202 }
02203 }
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215 void MayaToEggConverter::
02216 make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
02217 EggGroup *egg_group) {
02218 MStatus status;
02219
02220 unsigned int num_children = dag_node.childCount();
02221 MObject locator;
02222 bool found_locator = false;
02223 for (unsigned int ci = 0; ci < num_children && !found_locator; ci++) {
02224 locator = dag_node.child(ci);
02225 found_locator = (locator.apiType() == MFn::kLocator);
02226 }
02227
02228 if (!found_locator) {
02229 mayaegg_cat.error()
02230 << "Couldn't find locator within locator node "
02231 << dag_path.fullPathName().asChar() << "\n";
02232 return;
02233 }
02234
02235 LPoint3d p3d;
02236 if (!get_vec3d_attribute(locator, "localPosition", p3d)) {
02237 mayaegg_cat.error()
02238 << "Couldn't get position of locator "
02239 << dag_path.fullPathName().asChar() << "\n";
02240 return;
02241 }
02242
02243
02244
02245 MMatrix mat = dag_path.inclusiveMatrix(&status);
02246 if (!status) {
02247 status.perror("Can't get coordinate space for locator");
02248 return;
02249 }
02250 LMatrix4d n2w(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
02251 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
02252 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
02253 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
02254 p3d = p3d * n2w;
02255
02256
02257 p3d = p3d * egg_group->get_node_frame_inv();
02258
02259 egg_group->add_translate3d(p3d);
02260 }
02261
02262
02263
02264
02265
02266
02267
02268 bool MayaToEggConverter::
02269 get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
02270 pvector<EggGroup *> &joints, MFloatArray &weights) {
02271 MStatus status;
02272
02273
02274
02275
02276 MObject attr = mesh.attribute("inMesh");
02277
02278
02279
02280
02281 MPlug history(mesh.object(), attr);
02282 MItDependencyGraph it(history, MFn::kDependencyNode,
02283 MItDependencyGraph::kUpstream,
02284 MItDependencyGraph::kDepthFirst,
02285 MItDependencyGraph::kNodeLevel);
02286
02287 while (!it.isDone()) {
02288
02289
02290
02291 MObject c_node = it.thisNode();
02292 if (c_node.hasFn(MFn::kSkinClusterFilter)) {
02293
02294
02295
02296 MFnSkinCluster cluster(c_node, &status);
02297 if (!status) {
02298 status.perror("MFnSkinCluster constructor");
02299 return false;
02300 }
02301
02302
02303
02304 MDagPathArray influence_objects;
02305 cluster.influenceObjects(influence_objects, &status);
02306 if (!status) {
02307 status.perror("MFnSkinCluster::influenceObjects");
02308
02309 } else {
02310
02311
02312 joints.clear();
02313 for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
02314 MDagPath joint_dag_path = influence_objects[oi];
02315 MayaNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
02316 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
02317 joints.push_back(joint);
02318 }
02319
02320
02321
02322 MFnSingleIndexedComponent sic;
02323 MObject sic_object = sic.create(MFn::kMeshVertComponent);
02324 sic.setCompleteData(mesh.numVertices());
02325 unsigned influence_count;
02326
02327 status = cluster.getWeights(dag_path, sic_object,
02328 weights, influence_count);
02329 if (!status) {
02330 status.perror("MFnSkinCluster::getWeights");
02331 } else {
02332 if (influence_count != influence_objects.length()) {
02333 mayaegg_cat.error()
02334 << "MFnSkinCluster::influenceObjects() returns "
02335 << influence_objects.length()
02336 << " objects, but MFnSkinCluster::getWeights() reports "
02337 << influence_count << " objects.\n";
02338
02339 } else {
02340
02341
02342 return true;
02343 }
02344 }
02345 }
02346 } else if (c_node.hasFn(MFn::kWeightGeometryFilt)) {
02347
02348
02349 MFnWeightGeometryFilter cluster(c_node, &status);
02350 if (!status) {
02351 status.perror("MFnWeightGeometryFilter constructor");
02352 return false;
02353 }
02354
02355 MPlug matrix_plug = cluster.findPlug("matrix");
02356 if (!matrix_plug.isNull()) {
02357 MPlugArray matrix_pa;
02358 matrix_plug.connectedTo(matrix_pa, true, false, &status);
02359 if (!status) {
02360 status.perror("Can't find connected Joint");
02361 } else {
02362 MObject jointObj = matrix_pa[0].node();
02363 MFnIkJoint jointFn(jointObj, &status);
02364 if (!status) {
02365 status.perror("Can't find connected JointDag");
02366 } else {
02367 joints.clear();
02368 MDagPath joint_dag_path = MDagPath();
02369 status = jointFn.getPath(joint_dag_path);
02370 if (!status) {
02371 status.perror("MFnIkJoint::dagPath");
02372 } else {
02373 MayaNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
02374 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
02375 joints.push_back(joint);
02376
02377
02378
02379 MFnSingleIndexedComponent sic;
02380 MObject sic_object = sic.create(MFn::kMeshVertComponent);
02381 sic.setCompleteData(mesh.numVertices());
02382
02383 status = cluster.getWeights(dag_path, sic_object,
02384 weights);
02385 if (!status) {
02386 status.perror("MFnWeightGeometryFilter::getWeights");
02387 } else {
02388
02389
02390 return true;
02391 }
02392 }
02393 }
02394 }
02395 }
02396 }
02397
02398 it.next();
02399 }
02400
02401
02402 return false;
02403 }
02404
02405
02406
02407
02408
02409
02410
02411 bool MayaToEggConverter::
02412 get_vertex_weights(const MDagPath &dag_path, const MFnNurbsSurface &surface,
02413 pvector<EggGroup *> &joints, MFloatArray &weights) {
02414 MStatus status;
02415
02416
02417
02418
02419 MObject attr = surface.attribute("create");
02420
02421
02422
02423
02424 MPlug history(surface.object(), attr);
02425 MItDependencyGraph it(history, MFn::kDependencyNode,
02426 MItDependencyGraph::kUpstream,
02427 MItDependencyGraph::kDepthFirst,
02428 MItDependencyGraph::kNodeLevel);
02429
02430 while (!it.isDone()) {
02431
02432
02433
02434 MObject c_node = it.thisNode();
02435 if (c_node.hasFn(MFn::kSkinClusterFilter)) {
02436
02437
02438
02439 MFnSkinCluster cluster(c_node, &status);
02440 if (!status) {
02441 status.perror("MFnSkinCluster constructor");
02442 return false;
02443 }
02444
02445
02446
02447 MDagPathArray influence_objects;
02448 cluster.influenceObjects(influence_objects, &status);
02449 if (!status) {
02450 status.perror("MFnSkinCluster::influenceObjects");
02451
02452 } else {
02453
02454
02455 joints.clear();
02456 for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
02457 MDagPath joint_dag_path = influence_objects[oi];
02458 MayaNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
02459 EggGroup *joint = _tree.get_egg_group(joint_node_desc);
02460 joints.push_back(joint);
02461 }
02462
02463
02464
02465 MFnDoubleIndexedComponent dic;
02466 MObject dic_object = dic.create(MFn::kSurfaceCVComponent);
02467 dic.setCompleteData(surface.numCVsInU(), surface.numCVsInV());
02468 unsigned influence_count;
02469
02470 status = cluster.getWeights(dag_path, dic_object,
02471 weights, influence_count);
02472 if (!status) {
02473 status.perror("MFnSkinCluster::getWeights");
02474 } else {
02475 if (influence_count != influence_objects.length()) {
02476 mayaegg_cat.error()
02477 << "MFnSkinCluster::influenceObjects() returns "
02478 << influence_objects.length()
02479 << " objects, but MFnSkinCluster::getWeights() reports "
02480 << influence_count << " objects.\n";
02481
02482 } else {
02483
02484
02485 return true;
02486 }
02487 }
02488 }
02489 }
02490
02491 it.next();
02492 }
02493
02494
02495 return false;
02496 }
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507 void MayaToEggConverter::
02508 set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader,
02509 bool mesh) {
02510 if (shader._legacy_mode) {
02511 set_shader_legacy(primitive, shader, mesh);
02512 } else {
02513 set_shader_modern(primitive, shader, mesh);
02514 }
02515 }
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528 void MayaToEggConverter::
02529 set_shader_modern(EggPrimitive &primitive, const MayaShader &shader,
02530 bool mesh) {
02531
02532 for (size_t idx=0; idx < shader._all_maps.size(); idx++) {
02533 MayaShaderColorDef *def = shader._all_maps[idx];
02534 if ((def->_is_alpha)&&(def->_opposite != 0)) {
02535
02536 continue;
02537 }
02538
02539 EggTexture tex(shader.get_name(), "");
02540 tex.set_format(def->_is_alpha ? EggTexture::F_alpha : EggTexture::F_rgb);
02541 apply_texture_filename(tex, *def);
02542 if (def->_opposite) {
02543 apply_texture_alpha_filename(tex, *def);
02544 }
02545 apply_texture_uvprops(tex, *def);
02546 apply_texture_blendtype(tex, *def);
02547 tex.set_uv_name(def->get_panda_uvset_name());
02548
02549 EggTexture *new_tex =
02550 _textures.create_unique_texture(tex, ~0);
02551 primitive.add_texture(new_tex);
02552 }
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573 void MayaToEggConverter::
02574 set_shader_legacy(EggPrimitive &primitive, const MayaShader &shader,
02575 bool mesh) {
02576
02577
02578 MayaShaderColorDef *color_def = NULL;
02579 bool is_rgb = false;
02580 bool is_decal = false;
02581 bool is_interpolate = false;
02582 int i;
02583
02584 for (i=0; i<(int)shader._color.size()-1; ++i) {
02585 color_def = shader.get_color_def(i);
02586 if (color_def->_has_texture) {
02587 if ((EggTexture::EnvType)color_def->_interpolate) {
02588 is_interpolate = true;
02589 }
02590 else if ((EggTexture::EnvType)color_def->_blend_type == EggTexture::ET_modulate) {
02591
02592
02593 if (!color_def->_keep_alpha)
02594 is_rgb = true;
02595 }
02596 else if ((EggTexture::EnvType)color_def->_blend_type == EggTexture::ET_decal) {
02597 is_decal = true;
02598 }
02599 }
02600 }
02601
02602
02603 if (is_interpolate)
02604 is_decal = false;
02605
02606
02607 EggTexture *dummy_tex = (EggTexture *)NULL;
02608 string dummy_uvset_name;
02609
02610
02611
02612 const MayaShaderColorDef &trans_def = shader._transparency;
02613 for (i=shader._color.size()-1; i>=0; --i) {
02614 color_def = shader.get_color_def(i);
02615 if (mayaegg_cat.is_spam()) {
02616 mayaegg_cat.spam() << "slot " << i << ":got color_def: " << color_def << endl;
02617 }
02618 if (color_def->_has_texture || trans_def._has_texture) {
02619 EggTexture tex(shader.get_name(), "");
02620 if (mayaegg_cat.is_debug()) {
02621 mayaegg_cat.debug() << "got shader name:" << shader.get_name() << endl;
02622 mayaegg_cat.debug() << "ssa:texture name[" << i << "]: " << color_def->_texture_name << endl;
02623 }
02624
02625 string uvset_name = _shaders.find_uv_link(color_def->_texture_name);
02626 if (mayaegg_cat.is_debug()) {
02627 mayaegg_cat.debug() << "ssa:corresponding uvset name is " << uvset_name << endl;
02628 }
02629
02630 if (color_def->_has_texture) {
02631
02632
02633
02634
02635 Filename filename = Filename::from_os_specific(color_def->_texture_filename);
02636 Filename fullpath, outpath;
02637 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
02638 tex.set_filename(outpath);
02639 tex.set_fullpath(fullpath);
02640 apply_texture_uvprops(tex, *color_def);
02641
02642
02643
02644 if (trans_def._has_texture) {
02645 if (color_def->_wrap_u != trans_def._wrap_u ||
02646 color_def->_wrap_u != trans_def._wrap_u) {
02647 mayaegg_cat.warning()
02648 << "Shader " << shader.get_name()
02649 << " has contradictory wrap modes on color and texture.\n";
02650 }
02651
02652 if (!compare_texture_uvprops(tex, trans_def)) {
02653
02654 static pset<string> bad_shaders;
02655 if (bad_shaders.insert(shader.get_name()).second) {
02656 mayaegg_cat.error()
02657 << "Color and transparency texture properties differ on shader "
02658 << shader.get_name() << "\n";
02659 }
02660 }
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670 if (trans_def._texture_filename == color_def->_texture_filename) {
02671
02672
02673
02674 } else {
02675
02676
02677
02678
02679
02680 filename = Filename::from_os_specific(trans_def._texture_filename);
02681 _path_replace->full_convert_path(filename, get_model_path(),
02682 fullpath, outpath);
02683 tex.set_alpha_filename(outpath);
02684 tex.set_alpha_fullpath(fullpath);
02685 }
02686 } else {
02687
02688
02689
02690
02691 }
02692
02693 if (shader._color.size() > 1) {
02694
02695
02696
02697 if (i!=shader._color.size()-1) {
02698 if (!i && is_interpolate) {
02699
02700
02701
02702 tex.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_interpolate);
02703 tex.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_previous);
02704 tex.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
02705 tex.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_last_saved_result);
02706 tex.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
02707 tex.set_combine_source(EggTexture::CC_rgb, 2, EggTexture::CS_texture);
02708 tex.set_combine_operand(EggTexture::CC_rgb, 2, EggTexture::CO_src_alpha);
02709
02710 tex.set_combine_mode(EggTexture::CC_alpha, EggTexture::CM_interpolate);
02711 tex.set_combine_source(EggTexture::CC_alpha, 0, EggTexture::CS_previous);
02712 tex.set_combine_operand(EggTexture::CC_alpha, 0, EggTexture::CO_src_alpha);
02713 tex.set_combine_source(EggTexture::CC_alpha, 1, EggTexture::CS_last_saved_result);
02714 tex.set_combine_operand(EggTexture::CC_alpha, 1, EggTexture::CO_src_alpha);
02715 tex.set_combine_source(EggTexture::CC_alpha, 2, EggTexture::CS_texture);
02716 tex.set_combine_operand(EggTexture::CC_alpha, 2, EggTexture::CO_src_alpha);
02717 }
02718 else {
02719 if (is_interpolate) {
02720 tex.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_modulate);
02721 tex.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_primary_color);
02722 tex.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
02723 tex.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_texture);
02724 tex.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
02725 }
02726 else {
02727 tex.set_env_type((EggTexture::EnvType)color_def->_blend_type);
02728 if (tex.get_env_type() == EggTexture::ET_modulate) {
02729 if (color_def->_has_alpha_channel) {
02730
02731
02732 if (mayaegg_cat.is_spam()) {
02733 maya_cat.spam()
02734 << color_def->_texture_name
02735 << " should not have alpha channel in multiply mode: ignoring\n";
02736 }
02737 }
02738 if (is_rgb) {
02739
02740 tex.set_format(EggTexture::F_rgb);
02741 }
02742 }
02743 }
02744 }
02745 }
02746 else {
02747 if (is_interpolate) {
02748
02749 tex.set_saved_result(true);
02750 }
02751 else if (is_decal) {
02752
02753
02754
02755
02756 EggTexture texDummy(shader.get_name()+".dummy", "");
02757 if (mayaegg_cat.is_debug()) {
02758 mayaegg_cat.debug() << "creating dummy shader: " << texDummy.get_name() << endl;
02759 }
02760 texDummy.set_filename(outpath);
02761 texDummy.set_fullpath(fullpath);
02762 apply_texture_uvprops(texDummy, *color_def);
02763 texDummy.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_modulate);
02764 texDummy.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_primary_color);
02765 texDummy.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
02766 texDummy.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_previous);
02767 texDummy.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
02768 dummy_tex = _textures.create_unique_texture(texDummy, ~0);
02769
02770
02771 tex.set_env_type(EggTexture::ET_replace);
02772 }
02773 }
02774 }
02775 } else {
02776
02777
02778 Filename filename = Filename::from_os_specific(trans_def._texture_filename);
02779 Filename fullpath,outpath;
02780 _path_replace->full_convert_path(filename, get_model_path(),
02781 fullpath, outpath);
02782 tex.set_filename(outpath);
02783 tex.set_fullpath(fullpath);
02784 tex.set_format(EggTexture::F_alpha);
02785 apply_texture_uvprops(tex, trans_def);
02786 }
02787
02788 if (mayaegg_cat.is_debug()) {
02789 mayaegg_cat.debug() << "ssa:tref_name:" << tex.get_name() << endl;
02790 }
02791 if (is_rgb && i == (int)shader._color.size()-1) {
02792
02793 tex.set_format(EggTexture::F_rgb);
02794 }
02795 EggTexture *new_tex =
02796 _textures.create_unique_texture(tex, ~0);
02797
02798 if (mesh) {
02799 if (uvset_name.find("not found") == -1) {
02800 primitive.add_texture(new_tex);
02801 color_def->_uvset_name.assign(uvset_name.c_str());
02802 if (uvset_name != "map1") {
02803 new_tex->set_uv_name(uvset_name);
02804 }
02805 if (i == (int)shader._color.size()-1 && is_decal) {
02806 dummy_uvset_name.assign(color_def->_uvset_name);
02807 }
02808 }
02809 } else {
02810 primitive.add_texture(new_tex);
02811 if (color_def->_uvset_name != "map1") {
02812 new_tex->set_uv_name(color_def->_uvset_name);
02813 }
02814 }
02815 }
02816 }
02817 if (dummy_tex != (EggTexture *)NULL) {
02818 primitive.add_texture(dummy_tex);
02819 dummy_tex->set_uv_name(dummy_uvset_name);
02820 }
02821
02822 LColor rgba = shader.get_rgba();
02823 if (mayaegg_cat.is_spam()) {
02824 mayaegg_cat.spam() << "ssa:rgba = " << rgba << endl;
02825 }
02826
02827
02828
02829 if (color_def && color_def->_has_texture) {
02830 rgba[0] = 1.0f;
02831 rgba[1] = 1.0f;
02832 rgba[2] = 1.0f;
02833 }
02834 if (trans_def._has_texture) {
02835 rgba[3] = 1.0f;
02836 }
02837
02838
02839 if (color_def) {
02840 rgba[0] *= color_def->_color_gain[0];
02841 rgba[1] *= color_def->_color_gain[1];
02842 rgba[2] *= color_def->_color_gain[2];
02843 rgba[3] *= color_def->_color_gain[3];
02844 if (mayaegg_cat.is_spam()) {
02845 mayaegg_cat.spam() << "ssa:rgba = " << rgba << endl;
02846 }
02847 }
02848
02849 primitive.set_color(rgba);
02850
02851 if (mayaegg_cat.is_spam()) {
02852 mayaegg_cat.spam() << " set_shader_attributes : end\n";
02853 }
02854 }
02855
02856
02857
02858
02859
02860
02861
02862
02863 void MayaToEggConverter::
02864 apply_texture_uvprops(EggTexture &tex, const MayaShaderColorDef &color_def) {
02865
02866 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
02867 tex.set_magfilter(EggTexture::FT_linear);
02868
02869 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
02870 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
02871
02872 tex.set_wrap_u(wrap_u);
02873 tex.set_wrap_v(wrap_v);
02874
02875 LMatrix3d mat = color_def.compute_texture_matrix();
02876 if (!mat.almost_equal(LMatrix3d::ident_mat())) {
02877 tex.set_transform2d(mat);
02878 }
02879 }
02880
02881
02882
02883
02884
02885
02886 void MayaToEggConverter::
02887 apply_texture_blendtype(EggTexture &tex, const MayaShaderColorDef &color_def) {
02888 switch (color_def._blend_type) {
02889 case MayaShaderColorDef::BT_unspecified:
02890 tex.set_env_type(EggTexture::ET_unspecified);
02891 return;
02892 case MayaShaderColorDef::BT_modulate:
02893 tex.set_env_type(EggTexture::ET_modulate);
02894 return;
02895 case MayaShaderColorDef::BT_decal:
02896 tex.set_env_type(EggTexture::ET_decal);
02897 return;
02898 case MayaShaderColorDef::BT_blend:
02899 tex.set_env_type(EggTexture::ET_blend);
02900 return;
02901 case MayaShaderColorDef::BT_replace:
02902 tex.set_env_type(EggTexture::ET_replace);
02903 return;
02904 case MayaShaderColorDef::BT_add:
02905 tex.set_env_type(EggTexture::ET_add);
02906 return;
02907 case MayaShaderColorDef::BT_blend_color_scale:
02908 tex.set_env_type(EggTexture::ET_blend_color_scale);
02909 return;
02910 case MayaShaderColorDef::BT_modulate_glow:
02911 tex.set_env_type(EggTexture::ET_modulate_glow);
02912 return;
02913 case MayaShaderColorDef::BT_modulate_gloss:
02914 tex.set_env_type(EggTexture::ET_modulate_gloss);
02915 return;
02916 case MayaShaderColorDef::BT_normal:
02917 tex.set_env_type(EggTexture::ET_normal);
02918 return;
02919 case MayaShaderColorDef::BT_normal_height:
02920 tex.set_env_type(EggTexture::ET_normal_height);
02921 return;
02922 case MayaShaderColorDef::BT_glow:
02923 tex.set_env_type(EggTexture::ET_glow);
02924 return;
02925 case MayaShaderColorDef::BT_gloss:
02926 tex.set_env_type(EggTexture::ET_gloss);
02927 return;
02928 case MayaShaderColorDef::BT_height:
02929 tex.set_env_type(EggTexture::ET_height);
02930 return;
02931 case MayaShaderColorDef::BT_selector:
02932 tex.set_env_type(EggTexture::ET_selector);
02933 return;
02934 }
02935 }
02936
02937
02938
02939
02940
02941
02942 void MayaToEggConverter::
02943 apply_texture_filename(EggTexture &tex, const MayaShaderColorDef &def) {
02944 Filename filename = Filename::from_os_specific(def._texture_filename);
02945 Filename fullpath, outpath;
02946 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
02947 tex.set_filename(outpath);
02948 tex.set_fullpath(fullpath);
02949 }
02950
02951
02952
02953
02954
02955
02956 void MayaToEggConverter::
02957 apply_texture_alpha_filename(EggTexture &tex, const MayaShaderColorDef &def) {
02958 if (def._opposite) {
02959 tex.set_format(EggTexture::F_rgba);
02960 if (def._opposite->_texture_filename != def._texture_filename) {
02961 Filename filename = Filename::from_os_specific(def._opposite->_texture_filename);
02962 Filename fullpath, outpath;
02963 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
02964 tex.set_alpha_filename(outpath);
02965 tex.set_alpha_fullpath(fullpath);
02966 }
02967 }
02968 }
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979 bool MayaToEggConverter::
02980 compare_texture_uvprops(EggTexture &tex,
02981 const MayaShaderColorDef &color_def) {
02982 bool okflag = true;
02983
02984 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
02985 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
02986
02987 if (wrap_u != tex.determine_wrap_u()) {
02988
02989 if (wrap_u == EggTexture::WM_repeat) {
02990 tex.set_wrap_u(wrap_u);
02991 }
02992 okflag = false;
02993 }
02994 if (wrap_v != tex.determine_wrap_v()) {
02995 if (wrap_v == EggTexture::WM_repeat) {
02996 tex.set_wrap_v(wrap_v);
02997 }
02998 okflag = false;
02999 }
03000
03001 LMatrix3d m = color_def.compute_texture_matrix();
03002 LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
03003 m(1, 0), m(1, 1), 0.0, m(1, 2),
03004 0.0, 0.0, 1.0, 0.0,
03005 m(2, 0), m(2, 1), 0.0, m(2, 2));
03006 if (!mat4.almost_equal(tex.get_transform3d())) {
03007 okflag = false;
03008 }
03009
03010 return okflag;
03011 }
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023 bool MayaToEggConverter::
03024 reparent_decals(EggGroupNode *egg_parent) {
03025 bool okflag = true;
03026
03027
03028
03029 EggGroup *decal_base = (EggGroup *)NULL;
03030 pvector<EggGroup *> decal_children;
03031
03032 EggGroupNode::iterator ci;
03033 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
03034 EggNode *child = (*ci);
03035 if (child->is_of_type(EggGroup::get_class_type())) {
03036 EggGroup *child_group = DCAST(EggGroup, child);
03037 if (child_group->has_object_type("decalbase")) {
03038 if (decal_base != (EggNode *)NULL) {
03039 mayaegg_cat.error()
03040 << "Two children of " << egg_parent->get_name()
03041 << " both have decalbase set: " << decal_base->get_name()
03042 << " and " << child_group->get_name() << "\n";
03043 okflag = false;
03044 }
03045 child_group->remove_object_type("decalbase");
03046 decal_base = child_group;
03047
03048 } else if (child_group->has_object_type("decal")) {
03049 child_group->remove_object_type("decal");
03050 decal_children.push_back(child_group);
03051 }
03052 }
03053 }
03054
03055 if (decal_base == (EggGroup *)NULL) {
03056 if (!decal_children.empty()) {
03057 mayaegg_cat.warning()
03058 << decal_children.front()->get_name()
03059 << " has decal, but no sibling node has decalbase.\n";
03060 }
03061
03062 } else {
03063 if (decal_children.empty()) {
03064 mayaegg_cat.warning()
03065 << decal_base->get_name()
03066 << " has decalbase, but no sibling nodes have decal.\n";
03067
03068 } else {
03069
03070
03071
03072
03073 pvector<EggGroup *>::iterator di;
03074 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
03075 EggGroup *child_group = (*di);
03076 decal_base->add_child(child_group);
03077 }
03078
03079
03080 decal_base->set_decal_flag(true);
03081 }
03082 }
03083
03084
03085 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
03086 EggNode *child = (*ci);
03087 if (child->is_of_type(EggGroupNode::get_class_type())) {
03088 EggGroupNode *child_group = DCAST(EggGroupNode, child);
03089 if (!reparent_decals(child_group)) {
03090 okflag = false;
03091 }
03092 }
03093 }
03094
03095 return okflag;
03096 }
03097
03098
03099
03100
03101
03102
03103
03104 MayaToEggConverter::TransformType MayaToEggConverter::
03105 string_transform_type(const string &arg) {
03106 if (cmp_nocase(arg, "all") == 0) {
03107 return TT_all;
03108 } else if (cmp_nocase(arg, "model") == 0) {
03109 return TT_model;
03110 } else if (cmp_nocase(arg, "dcs") == 0) {
03111 return TT_dcs;
03112 } else if (cmp_nocase(arg, "none") == 0) {
03113 return TT_none;
03114 } else {
03115 return TT_invalid;
03116 }
03117 }
03118
03119
03120
03121
03122
03123
03124
03125
03126 void MayaToEggConverter::
03127 set_vertex_color(EggVertex &vert, MItMeshPolygon &pi, int vert_index, const MayaShader *shader, const LColor &color) {
03128 if (shader == (MayaShader *)NULL || shader->_legacy_mode) {
03129 set_vertex_color_legacy(vert, pi, vert_index, shader, color);
03130 } else {
03131 set_vertex_color_modern(vert, pi, vert_index, shader, color);
03132 }
03133 }
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143 void MayaToEggConverter::
03144 set_vertex_color_legacy(EggVertex &vert, MItMeshPolygon &pi, int vert_index, const MayaShader *shader, const LColor &color){
03145 if (pi.hasColor()) {
03146 MColor c;
03147 MStatus status = pi.getColor(c, vert_index);
03148 if (!status) {
03149 status.perror("MItMeshPolygon::getColor");
03150 } else {
03151
03152
03153 c /= 1.0;
03154
03155
03156 vert.set_color(LColor(c.r * color[0], c.g * color[1], c.b * color[2], c.a * color[3]));
03157
03158 if (mayaegg_cat.is_spam()) {
03159 mayaegg_cat.spam() << "maya_color = " << c.r << " " << c.g << " " << c.b << " " << c.a << endl;
03160 mayaegg_cat.spam() << "vert_color = " << vert.get_color() << endl;
03161 }
03162 }
03163 } else {
03164 vert.set_color(color);
03165 }
03166
03167 }
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177 void MayaToEggConverter::
03178 set_vertex_color_modern(EggVertex &vert, MItMeshPolygon &pi, int vert_index, const MayaShader *shader, const LColor &color) {
03179
03180 if (pi.hasColor(vert_index)) {
03181 MColor c;
03182 MStatus status = pi.getColor(c, vert_index);
03183 if (status) {
03184 vert.set_color(LColor(c.r, c.g, c.b, c.a));
03185 return;
03186 }
03187 }
03188
03189
03190 if (shader->_color_maps.empty()) {
03191 const LColord &c = shader->_flat_color;
03192 vert.set_color(LColor((PN_stdfloat)c[0], (PN_stdfloat)c[1], (PN_stdfloat)c[2], (PN_stdfloat)c[3]));
03193 } else {
03194
03195 vert.set_color(LColor(1.0f, 1.0f, 1.0f, 1.0f));
03196 }
03197 }