18 #include "mayaToEggConverter.h"
19 #include "mayaShader.h"
20 #include "maya_funcs.h"
21 #include "config_mayaegg.h"
22 #include "mayaEggGroupUserData.h"
27 #include "eggVertex.h"
28 #include "eggVertexPool.h"
29 #include "eggNurbsSurface.h"
30 #include "eggNurbsCurve.h"
31 #include "eggPolygon.h"
32 #include "eggPrimitive.h"
33 #include "eggTexture.h"
34 #include "eggTextureCollection.h"
35 #include "eggXfmSAnim.h"
36 #include "eggSAnimData.h"
37 #include "string_utils.h"
40 #include "pre_maya_include.h"
41 #include <maya/MArgList.h>
42 #include <maya/MColor.h>
43 #include <maya/MDagPath.h>
44 #include <maya/MFnCamera.h>
45 #include <maya/MFnDagNode.h>
46 #include <maya/MFnTransform.h>
47 #include <maya/MFnLight.h>
48 #include <maya/MFnNurbsSurface.h>
49 #include <maya/MFnNurbsCurve.h>
50 #include <maya/MFnMesh.h>
51 #include <maya/MFnMeshData.h>
52 #include <maya/MFnPlugin.h>
53 #include <maya/MItDag.h>
54 #include <maya/MMatrix.h>
55 #include <maya/MObject.h>
56 #include <maya/MPoint.h>
57 #include <maya/MPointArray.h>
58 #include <maya/MDoubleArray.h>
59 #include <maya/MIntArray.h>
60 #include <maya/MPxCommand.h>
61 #include <maya/MStatus.h>
62 #include <maya/MString.h>
63 #include <maya/MTransformationMatrix.h>
64 #include <maya/MVector.h>
65 #include <maya/MTesselationParams.h>
66 #include <maya/MAnimControl.h>
67 #include <maya/MGlobal.h>
68 #include <maya/MAnimUtil.h>
69 #include <maya/MFnSkinCluster.h>
70 #include <maya/MFnWeightGeometryFilter.h>
71 #include <maya/MFnIkJoint.h>
72 #include <maya/MFnSingleIndexedComponent.h>
73 #include <maya/MFnDoubleIndexedComponent.h>
74 #include <maya/MFnBlendShapeDeformer.h>
75 #include <maya/MItDependencyGraph.h>
76 #include <maya/MDagPathArray.h>
77 #include <maya/MSelectionList.h>
78 #include "post_maya_include.h"
87 MayaToEggConverter(
const string &program_name) :
88 _program_name(program_name),
94 _from_selection =
false;
96 _polygon_output =
false;
97 _polygon_tolerance = 0.01;
98 _respect_maya_double_sided = maya_default_double_sided;
99 _always_show_vertex_color = maya_default_vertex_color;
100 _keep_all_uvsets =
false;
102 _legacy_shader =
false;
103 _convert_cameras =
false;
104 _convert_lights =
false;
106 _transform_type = TT_model;
116 _program_name(copy._program_name),
117 _from_selection(copy._from_selection),
118 _subsets(copy._subsets),
119 _subroots(copy._subroots),
120 _excludes(copy._excludes),
121 _ignore_sliders(copy._ignore_sliders),
122 _force_joints(copy._force_joints),
125 _polygon_output(copy._polygon_output),
126 _polygon_tolerance(copy._polygon_tolerance),
127 _respect_maya_double_sided(copy._respect_maya_double_sided),
128 _always_show_vertex_color(copy._always_show_vertex_color),
129 _keep_all_uvsets(copy._keep_all_uvsets),
130 _convert_cameras(copy._convert_cameras),
131 _convert_lights(copy._convert_lights),
132 _round_uvs(copy._round_uvs),
133 _legacy_shader(copy._legacy_shader),
134 _transform_type(copy._transform_type)
144 ~MayaToEggConverter() {
207 <<
"Maya is not available.\n";
217 if (!_maya->read(filename)) {
219 <<
"Unable to read " << filename <<
"\n";
223 if (_character_name.empty()) {
253 _subroots.push_back(glob);
279 _subsets.push_back(glob);
300 _excludes.push_back(glob);
311 _ignore_sliders.clear();
327 _ignore_sliders.push_back(glob);
338 Globs::const_iterator gi;
339 for (gi = _ignore_sliders.begin(); gi != _ignore_sliders.end(); ++gi) {
340 if ((*gi).matches(name)) {
356 _force_joints.clear();
373 _force_joints.push_back(glob);
384 Globs::const_iterator gi;
385 for (gi = _force_joints.begin(); gi != _force_joints.end(); ++gi) {
386 if ((*gi).matches(name)) {
405 _from_selection = from_selection;
419 return _maya->get_units();
436 <<
"Maya is not available.\n";
440 if (_egg_data->get_coordinate_system() == CS_default) {
441 _egg_data->set_coordinate_system(_maya->get_coordinate_system());
445 <<
"Converting from Maya.\n";
448 double start_frame, end_frame, frame_inc, input_frame_rate, output_frame_rate;
452 start_frame = MAnimControl::minTime().value();
457 end_frame = MAnimControl::maxTime().value();
468 MTime time(1.0, MTime::kSeconds);
469 input_frame_rate = time.as(MTime::uiUnit());
474 output_frame_rate = input_frame_rate;
477 frame_inc = frame_inc * input_frame_rate / output_frame_rate;
482 if (!_subroots.empty()) {
483 Globs::const_iterator gi;
484 for (gi = _subroots.begin(); gi != _subroots.end(); ++gi) {
487 <<
"No node matching " << *gi <<
" found.\n";
499 if (_from_selection) {
501 }
else if (!_subsets.empty()) {
502 Globs::const_iterator gi;
503 for (gi = _subsets.begin(); gi != _subsets.end(); ++gi) {
506 <<
"No node matching " << *gi <<
" found.\n";
516 if (!_excludes.empty()) {
517 Globs::const_iterator gi;
518 for (gi = _excludes.begin(); gi != _excludes.end(); ++gi) {
521 <<
"No node matching " << *gi <<
" found.\n";
531 mayaegg_cat.info(
false)
532 <<
"frame " << start_frame <<
"\n";
533 MGlobal::viewFrame(MTime(start_frame, MTime::uiUnit()));
538 mayaegg_cat.info() <<
"ac_none" << endl;
546 all_ok = convert_flip(start_frame, end_frame, frame_inc,
553 all_ok = convert_char_model();
558 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
564 _animation_convert = AC_model;
565 if (!convert_char_model()) {
568 _animation_convert = AC_chan;
569 if (!convert_char_chan(start_frame, end_frame, frame_inc,
570 output_frame_rate)) {
588 <<
"Converted, no errors.\n";
591 <<
"Errors encountered in conversion.\n";
607 if (_maya == (
MayaApi *)NULL || !_maya->is_valid()) {
610 _maya = MayaApi::open_api(_program_name,
true, revert_directory);
612 return _maya->is_valid();
655 bool MayaToEggConverter::
656 convert_flip(
double start_frame,
double end_frame,
double frame_inc,
657 double output_frame_rate) {
662 if (_animation_convert == AC_flip) {
663 sequence_node->set_switch_flag(
true);
664 sequence_node->set_switch_fps(output_frame_rate);
667 MTime frame(start_frame, MTime::uiUnit());
668 MTime frame_stop(end_frame, MTime::uiUnit());
669 while (frame <= frame_stop) {
670 mayaegg_cat.info(
false)
671 <<
"frame " << frame.value() <<
"\n";
673 name_strm <<
"frame" << frame.value();
677 MGlobal::viewFrame(frame);
678 if (!convert_hierarchy(frame_root)) {
694 bool MayaToEggConverter::
695 convert_char_model() {
698 mayaegg_cat.info(
false)
699 <<
"neutral frame " << frame.value() <<
"\n";
700 MGlobal::viewFrame(frame);
710 char_node->set_dart_type(EggGroup::DT_default);
712 return convert_hierarchy(char_node);
722 bool MayaToEggConverter::
723 convert_char_chan(
double start_frame,
double end_frame,
double frame_inc,
724 double output_frame_rate) {
730 bundle_node->set_table_type(EggTable::TT_bundle);
739 _tree._fps = output_frame_rate;
750 int num_nodes = _tree.get_num_nodes();
751 int num_sliders = _tree.get_num_blend_descs();
754 MTime frame(start_frame, MTime::uiUnit());
755 MTime frame_stop(end_frame, MTime::uiUnit());
756 while (frame <= frame_stop) {
757 if (mayaegg_cat.is_spam()) {
758 mayaegg_cat.spam(
false)
759 <<
"frame " << frame.value() <<
"\n";
763 cerr <<
"." << flush;
765 MGlobal::viewFrame(frame);
767 for (i = 0; i < num_nodes; i++) {
770 if (mayaegg_cat.is_spam()) {
772 <<
"joint " << node_desc->get_name() <<
"\n";
776 if (!anim->add_data(tgroup->get_transform3d())) {
778 <<
"Invalid transform on " << node_desc->get_name()
779 <<
" frame " << frame.value() <<
".\n";
784 for (i = 0; i < num_sliders; i++) {
786 if (mayaegg_cat.is_spam()) {
788 <<
"slider " << blend_desc->get_name() <<
"\n";
800 for (i = 0; i < num_nodes; i++) {
807 for (i = 0; i < num_sliders; i++) {
813 mayaegg_cat.info(
false)
825 bool MayaToEggConverter::
830 mayaegg_cat.info() <<
"will round up uv coordinates" << endl;
833 if (_keep_all_uvsets) {
834 mayaegg_cat.info() <<
"will keep_all_uvsets" << endl;
836 if (_polygon_output) {
837 mayaegg_cat.info() <<
"will convert NURBS to polys" << endl;
839 if (_convert_cameras) {
840 mayaegg_cat.info() <<
"will convert camera nodes to locators" << endl;
842 if (_convert_lights) {
843 mayaegg_cat.info() <<
"will convert light nodes to locators" << endl;
846 if (_legacy_shader) {
847 mayaegg_cat.info() <<
"will disable modern Phong shader path. using legacy" << endl;
850 for (
int i = 0; i < num_nodes; i++) {
852 if (!process_model_node(node)) {
867 bool MayaToEggConverter::
877 MFnDagNode dag_node(dag_path, &status);
879 status.perror(
"MFnDagNode constructor");
880 mayaegg_cat.error() << dag_path.fullPathName().asChar() <<
"\n";
884 MObject node = dag_path.transform(&status);
886 status.perror(
"dag_path.transform()");
890 string path = dag_path.fullPathName().asChar();
892 if (mayaegg_cat.is_debug()) {
894 << path <<
": " << dag_node.typeName().asChar();
896 if (MAnimUtil::isAnimated(dag_path)) {
897 mayaegg_cat.debug(
false)
901 mayaegg_cat.debug(
false) <<
"\n";
904 if (dag_node.inUnderWorld()) {
905 if (mayaegg_cat.is_debug()) {
907 <<
"Ignoring underworld node " << path
911 }
else if (dag_node.isIntermediateObject()) {
912 if (mayaegg_cat.is_debug()) {
914 <<
"Ignoring intermediate object " << path
918 }
else if (dag_path.hasFn(MFn::kCamera)) {
919 if (_convert_cameras) {
920 MFnCamera camera (dag_path, &status);
922 status.perror(
"MFnCamera constructor");
927 if (mayaegg_cat.is_spam()) {
928 MPoint eyePoint = camera.eyePoint(MSpace::kWorld);
929 mayaegg_cat.spam() <<
" eyePoint: " << eyePoint.x <<
" "
930 << eyePoint.y <<
" " << eyePoint.z << endl;
931 mayaegg_cat.spam() <<
" upDirection: "
932 << camera.upDirection(MSpace::kWorld) << endl;
933 mayaegg_cat.spam() <<
" viewDirection: "
934 << camera.viewDirection(MSpace::kWorld) << endl;
935 mayaegg_cat.spam() <<
" aspectRatio: " << camera.aspectRatio() << endl;
936 mayaegg_cat.spam() <<
" horizontalFilmAperture: "
937 << camera.horizontalFilmAperture() << endl;
938 mayaegg_cat.spam() <<
" verticalFilmAperture: "
939 << camera.verticalFilmAperture() << endl;
944 if (mayaegg_cat.is_debug()) {
945 mayaegg_cat.warning()
946 <<
"Saving camera nodes as a locator: " << path <<
"\n";
953 if (_animation_convert != AC_model) {
958 egg_group->set_dcs_type(EggGroup::DC_net);
960 get_transform(node_desc, dag_path, egg_group);
961 make_camera_locator(dag_path, dag_node, egg_group);
963 if (mayaegg_cat.is_debug()) {
965 <<
"Ignoring camera node " << path
971 }
else if (dag_path.hasFn(MFn::kLight)) {
972 if (_convert_lights) {
973 MFnLight light (dag_path, &status);
975 status.perror(
"MFnLight constructor");
981 if (mayaegg_cat.is_debug()) {
982 mayaegg_cat.warning() <<
"Saving light node as a locator: " << path << endl;
989 if (_animation_convert != AC_model) {
994 egg_group->set_dcs_type(EggGroup::DC_net);
996 get_transform(node_desc, dag_path, egg_group);
997 make_light_locator(dag_path, dag_node, egg_group);
999 if (mayaegg_cat.is_debug()) {
1001 <<
"Ignoring light node " << path
1007 MFnLight light (dag_path, &status);
1009 status.perror(
"MFnLight constructor");
1010 mayaegg_cat.error() <<
"light extraction failed" << endl;
1013 mayaegg_cat.info() <<
"-- Light found -- tranlations in cm, rotations in rads\n";
1015 mayaegg_cat.info() <<
"\"" << dag_path.partialPathName() <<
"\" : \n";
1018 MObject transformNode = dag_path.transform(&status);
1020 if (!status && status.statusCode () == MStatus::kInvalidParameter)
1022 MFnDagNode transform (transformNode, &status);
1024 status.perror(
"MFnDagNode constructor");
1027 MTransformationMatrix matrix (transform.transformationMatrix());
1028 MVector tl = matrix.translation(MSpace::kWorld);
1030 if (tl.x < 0.0001) {
1033 if (tl.y < 0.0001) {
1036 if (tl.z < 0.0001) {
1040 mayaegg_cat.info() <<
" \"translation\" : (" << tl.x <<
", " << tl.z <<
", " << tl.y <<
")"
1042 double threeDoubles[3];
1043 MTransformationMatrix::RotationOrder rOrder;
1045 matrix.getRotation (threeDoubles, rOrder, MSpace::kWorld);
1046 mayaegg_cat.info() <<
" \"rotation\": ("
1047 << threeDoubles[0] <<
", "
1048 << threeDoubles[2] <<
", "
1049 << threeDoubles[1] <<
")\n";
1050 matrix.getScale (threeDoubles, MSpace::kWorld);
1051 mayaegg_cat.info() <<
" \"scale\" : ("
1052 << threeDoubles[0] <<
", "
1053 << threeDoubles[2] <<
", "
1054 << threeDoubles[1] <<
")\n";
1058 color = light.color();
1059 mayaegg_cat.info() <<
" \"color\" : ("
1062 << color.b <<
")\n";
1063 color = light.shadowColor();
1064 mayaegg_cat.info() <<
" \"intensity\" : " << light.intensity() << endl;
1066 }
else if (dag_path.hasFn(MFn::kNurbsSurface)) {
1068 get_transform(node_desc, dag_path, egg_group);
1071 MFnNurbsSurface surface(dag_path, &status);
1074 <<
"Error in node " << path
1076 <<
" it appears to have a NURBS surface, but does not.\n";
1078 make_nurbs_surface(node_desc, dag_path, surface, egg_group);
1081 }
else if (dag_path.hasFn(MFn::kNurbsCurve)) {
1085 if (_animation_convert != AC_model) {
1087 get_transform(node_desc, dag_path, egg_group);
1090 MFnNurbsCurve curve(dag_path, &status);
1093 <<
"Error in node " << path <<
":\n"
1094 <<
" it appears to have a NURBS curve, but does not.\n";
1096 make_nurbs_curve(dag_path, curve, egg_group);
1101 }
else if (dag_path.hasFn(MFn::kMesh)) {
1104 get_transform(node_desc, dag_path, egg_group);
1105 MFnMesh mesh(dag_path, &status);
1108 <<
"Error in node " << path <<
":\n"
1109 <<
" it appears to have a polygon mesh, but does not.\n";
1111 make_polyset(node_desc, dag_path, mesh, egg_group);
1129 }
else if (dag_path.hasFn(MFn::kLocator)) {
1130 if (_animation_convert == AC_none) {
1137 if (mayaegg_cat.is_debug()) {
1139 <<
"Locator at " << path <<
"\n";
1146 if (_animation_convert != AC_model) {
1151 egg_group->set_dcs_type(EggGroup::DC_net);
1153 get_transform(node_desc, dag_path, egg_group);
1154 make_locator(dag_path, dag_node, egg_group);
1159 if (_animation_convert == AC_none) {
1165 get_transform(node_desc, dag_path, egg_group);
1177 void MayaToEggConverter::
1178 get_transform(
MayaNodeDesc *node_desc,
const MDagPath &dag_path,
1179 EggGroup *egg_group) {
1180 if (_animation_convert == AC_model) {
1185 if (mayaegg_cat.is_spam()) {
1187 <<
"gt: joint " << node_desc->get_name() <<
"\n";
1189 get_joint_transform(dag_path, egg_group);
1195 MObject transformNode = dag_path.transform(&status);
1196 if (!status && status.statusCode() == MStatus::kInvalidParameter) {
1202 if (egg_group->get_billboard_type() == EggGroup::BT_none) {
1203 switch (_transform_type) {
1208 if (!egg_group->get_model_flag() && !egg_group->
has_dcs_type()) {
1226 MMatrix mat = dag_path.inclusiveMatrix(&status);
1228 status.perror(
"Can't get transform matrix");
1231 LMatrix4d m4d(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
1232 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
1233 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
1234 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
1239 MFnTransform transform(transformNode, &status);
1241 status.perror(
"MFnTransform constructor");
1244 MPoint pivot = transform.rotatePivot(MSpace::kObject, &status);
1246 status.perror(
"Can't get rotate pivot");
1252 LPoint3d p3d(pivot[0], pivot[1], pivot[2]);
1256 m4d.set_row(3, p3d);
1277 void MayaToEggConverter::
1278 get_joint_transform(
const MDagPath &dag_path, EggGroup *egg_group) {
1283 MObject transformNode = dag_path.transform(&status);
1285 if (!status && status.statusCode() == MStatus::kInvalidParameter) {
1289 MFnDagNode transform(transformNode, &status);
1291 status.perror(
"MFnDagNode constructor");
1295 MTransformationMatrix matrix(transform.transformationMatrix());
1297 if (mayaegg_cat.is_spam()) {
1298 MVector t = matrix.translation(MSpace::kWorld);
1300 <<
" translation: ["
1305 MTransformationMatrix::RotationOrder rOrder;
1307 matrix.getRotation(d, rOrder, MSpace::kWorld);
1313 matrix.getScale(d, MSpace::kWorld);
1319 matrix.getShear(d, MSpace::kWorld);
1327 MMatrix mat = matrix.asMatrix();
1329 ident_mat.setToIdentity();
1331 if (!mat.isEquivalent(ident_mat, 0.0001)) {
1333 (
LMatrix4d(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
1334 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
1335 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
1336 mat[3][0], mat[3][1], mat[3][2], mat[3][3]));
1347 void MayaToEggConverter::
1348 make_nurbs_surface(
MayaNodeDesc *node_desc,
const MDagPath &dag_path,
1349 MFnNurbsSurface &surface, EggGroup *egg_group) {
1351 string name = surface.name().asChar();
1353 if (mayaegg_cat.is_spam()) {
1356 << surface.numCVsInU()
1358 << surface.numCVsInV()
1362 << surface.numKnotsInU()
1364 << surface.numKnotsInV()
1368 << surface.numSpansInU()
1370 << surface.numSpansInV()
1375 if (_polygon_output) {
1378 MTesselationParams params;
1379 params.setFormatType(MTesselationParams::kStandardFitFormat);
1380 params.setOutputType(MTesselationParams::kQuads);
1381 params.setStdFractionalTolerance(_polygon_tolerance);
1385 MDagPath polyset_path = dag_path;
1386 MObject polyset_parent = polyset_path.node();
1388 surface.tesselate(params, polyset_parent, &status);
1390 status.perror(
"MFnNurbsSurface::tesselate");
1394 status = polyset_path.push(polyset);
1396 status.perror(
"MDagPath::push");
1399 MFnMesh polyset_fn(polyset, &status);
1401 status.perror(
"MFnMesh constructor");
1404 make_polyset(node_desc, polyset_path, polyset_fn, egg_group, shader);
1407 MFnDagNode parent_node(polyset_parent, &status);
1409 status.perror(
"MFnDagNode constructor");
1412 status = parent_node.removeChild(polyset);
1414 status.perror(
"MFnDagNode::removeChild");
1420 MPointArray cv_array;
1421 status = surface.getCVs(cv_array, MSpace::kWorld);
1423 status.perror(
"MFnNurbsSurface::getCVs");
1430 if (_animation_convert == AC_model) {
1432 morph_cvs.reserve(num_sliders);
1433 for (
int i = 0; i < num_sliders; i++) {
1439 MPointArray cv_array;
1440 status = surface.getCVs(cv_array, MSpace::kWorld);
1444 status.perror(
"MFnNurbsSurface::getCVs");
1447 morph_cvs.push_back(cv_array);
1451 MDoubleArray u_knot_array, v_knot_array;
1452 status = surface.getKnotsInU(u_knot_array);
1454 status.perror(
"MFnNurbsSurface::getKnotsInU");
1457 status = surface.getKnotsInV(v_knot_array);
1459 status.perror(
"MFnNurbsSurface::getKnotsInV");
1463 MFnNurbsSurface::Form u_form = surface.formInU();
1464 MFnNurbsSurface::Form v_form = surface.formInV();
1466 int u_degree = surface.degreeU();
1467 int v_degree = surface.degreeV();
1469 int u_cvs = surface.numCVsInU();
1470 int v_cvs = surface.numCVsInV();
1474 int maya_u_cvs = (u_form == MFnNurbsSurface::kPeriodic) ? u_cvs - u_degree : u_cvs;
1475 int maya_v_cvs = (v_form == MFnNurbsSurface::kPeriodic) ? v_cvs - v_degree : v_cvs;
1477 int u_knots = surface.numKnotsInU();
1478 int v_knots = surface.numKnotsInV();
1480 assert(u_knots == u_cvs + u_degree - 1);
1481 assert(v_knots == v_cvs + v_degree - 1);
1483 string vpool_name = name +
".cvs";
1488 egg_nurbs->
setup(u_degree + 1, v_degree + 1,
1489 u_knots + 2, v_knots + 2);
1494 for (i = 0; i < u_knots; i++) {
1495 egg_nurbs->
set_u_knot(i + 1, u_knot_array[i]);
1497 egg_nurbs->
set_u_knot(u_knots + 1, u_knot_array[u_knots - 1]);
1500 for (i = 0; i < v_knots; i++) {
1501 egg_nurbs->
set_v_knot(i + 1, v_knot_array[i]);
1503 egg_nurbs->
set_v_knot(v_knots + 1, v_knot_array[v_knots - 1]);
1510 int maya_vi = v_cvs * ui + vi;
1513 status = cv_array[maya_vi].get(v);
1515 status.perror(
"MPoint::get");
1518 LPoint4d p4d(v[0], v[1], v[2], v[3]);
1519 p4d = p4d * vertex_frame_inv;
1523 if (!morph_cvs.empty()) {
1526 LPoint3d p3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
1528 for (
unsigned int si = 0; si < morph_cvs.size(); si++) {
1530 status = morph_cvs[si][maya_vi].get(v);
1532 status.perror(
"MPoint::get");
1534 LPoint3d m3d(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
1538 vert->_dxyzs.
insert(dxyz);
1549 unsigned num_trims = surface.numRegions();
1550 int trim_curve_index = 0;
1551 for (
unsigned ti = 0; ti < num_trims; ti++) {
1552 unsigned num_loops = surface.numBoundaries(ti);
1554 if (num_loops > 0) {
1558 for (
unsigned li = 0; li < num_loops; li++) {
1562 MFnNurbsSurface::BoundaryType type =
1563 surface.boundaryType(ti, li, &status);
1564 bool keep_loop =
false;
1567 status.perror(
"MFnNurbsSurface::BoundaryType");
1569 keep_loop = (type == MFnNurbsSurface::kInner ||
1570 type == MFnNurbsSurface::kOuter);
1574 unsigned num_edges = surface.numEdges(ti, li);
1575 for (
unsigned ei = 0; ei < num_edges; ei++) {
1576 MObjectArray edge = surface.edge(ti, li, ei,
true, &status);
1578 status.perror(
"MFnNurbsSurface::edge");
1580 unsigned num_segs = edge.length();
1581 for (
unsigned si = 0; si < num_segs; si++) {
1582 MObject segment = edge[si];
1583 if (segment.hasFn(MFn::kNurbsCurve)) {
1584 MFnNurbsCurve curve(segment, &status);
1587 <<
"Trim curve appears to be a nurbs curve, but isn't.\n";
1591 make_trim_curve(curve, name, egg_group, trim_curve_index);
1594 egg_loop.push_back(egg_curve);
1599 <<
"Trim curve segment is not a nurbs curve.\n";
1614 set_shader_attributes(*egg_nurbs, *shader);
1618 bool got_weights =
false;
1621 MFloatArray weights;
1622 if (_animation_convert == AC_model) {
1624 get_vertex_weights(dag_path, surface, joints, weights);
1627 if (got_weights && !joints.empty()) {
1628 int num_joints = joints.size();
1629 int num_weights = (int)weights.length();
1630 int num_verts = num_weights / num_joints;
1633 nassertv(num_weights == num_verts * num_joints);
1639 int maya_vi = maya_v_cvs * ui + vi;
1640 nassertv(maya_vi < num_verts);
1643 for (
int ji = 0; ji < num_joints; ++ji) {
1644 PN_stdfloat weight = weights[maya_vi * num_joints + ji];
1645 if (weight != 0.0f) {
1646 EggGroup *joint = joints[ji];
1647 if (joint != (EggGroup *)NULL) {
1664 make_trim_curve(
const MFnNurbsCurve &curve,
const string &nurbs_name,
1666 if (mayaegg_cat.is_spam()) {
1685 MPointArray cv_array;
1686 status = curve.getCVs(cv_array, MSpace::kWorld);
1688 status.perror(
"MFnNurbsCurve::getCVs");
1691 MDoubleArray knot_array;
1692 status = curve.getKnots(knot_array);
1694 status.perror(
"MFnNurbsCurve::getKnots");
1702 int degree = curve.degree();
1703 int cvs = curve.numCVs();
1704 int knots = curve.numKnots();
1706 assert(knots == cvs + degree - 1);
1708 string trim_name =
"trim" + format_string(trim_curve_index);
1710 string vpool_name = nurbs_name +
"." + trim_name;
1715 egg_curve->
setup(degree + 1, knots + 2);
1719 egg_curve->
set_knot(0, knot_array[0]);
1720 for (i = 0; i < knots; i++) {
1721 egg_curve->
set_knot(i + 1, knot_array[i]);
1723 egg_curve->
set_knot(knots + 1, knot_array[knots - 1]);
1727 MStatus status = cv_array[i].get(v);
1729 status.perror(
"MPoint::get");
1747 void MayaToEggConverter::
1748 make_nurbs_curve(
const MDagPath &,
const MFnNurbsCurve &curve,
1749 EggGroup *egg_group) {
1751 string name = curve.name().asChar();
1753 if (mayaegg_cat.is_spam()) {
1768 MPointArray cv_array;
1769 status = curve.getCVs(cv_array, MSpace::kWorld);
1771 status.perror(
"MFnNurbsCurve::getCVs");
1774 MDoubleArray knot_array;
1775 status = curve.getKnots(knot_array);
1777 status.perror(
"MFnNurbsCurve::getKnots");
1785 int degree = curve.degree();
1786 int cvs = curve.numCVs();
1787 int knots = curve.numKnots();
1789 assert(knots == cvs + degree - 1);
1791 string vpool_name = name +
".cvs";
1797 egg_curve->
setup(degree + 1, knots + 2);
1801 egg_curve->
set_knot(0, knot_array[0]);
1802 for (i = 0; i < knots; i++) {
1803 egg_curve->
set_knot(i + 1, knot_array[i]);
1805 egg_curve->
set_knot(knots + 1, knot_array[knots - 1]);
1811 MStatus status = cv_array[i].get(v);
1813 status.perror(
"MPoint::get");
1816 LPoint4d p4d(v[0], v[1], v[2], v[3]);
1817 p4d = p4d * vertex_frame_inv;
1824 set_shader_attributes(*egg_curve, *shader);
1833 int MayaToEggConverter::
1834 round(
double value) {
1836 return -(floor(-value + 0.5));
1840 return floor( value + 0.5);
1850 void MayaToEggConverter::
1851 make_polyset(
MayaNodeDesc *node_desc,
const MDagPath &dag_path,
1852 const MFnMesh &mesh, EggGroup *egg_group,
1855 string name = mesh.name().asChar();
1857 MObject mesh_object = mesh.object();
1858 bool maya_double_sided =
false;
1859 get_bool_attribute(mesh_object,
"doubleSided", maya_double_sided);
1861 if (mayaegg_cat.is_spam()) {
1864 << mesh.numPolygons()
1868 << mesh.numVertices()
1872 if (mesh.numPolygons() == 0) {
1873 if (mayaegg_cat.is_debug()) {
1875 <<
"Ignoring empty mesh " << name <<
"\n";
1880 string vpool_name = name +
".verts";
1896 MObject component_obj;
1897 MItMeshPolygon pi(dag_path, component_obj, &status);
1899 status.perror(
"MItMeshPolygon constructor");
1903 MObjectArray shaders;
1904 MIntArray poly_shader_indices;
1906 status = mesh.getConnectedShaders(dag_path.instanceNumber(),
1907 shaders, poly_shader_indices);
1909 status.perror(
"MFnMesh::getConnectedShaders");
1921 bool egg_vertex_color =
false;
1922 bool egg_double_sided =
false;
1923 if (egg_group->
has_user_data(MayaEggGroupUserData::get_class_type())) {
1926 egg_vertex_color = user_data->_vertex_color;
1927 egg_double_sided = user_data->_double_sided;
1930 bool double_sided = maya_double_sided;
1931 if (!_respect_maya_double_sided) {
1934 if (!egg_double_sided) {
1935 double_sided =
false;
1939 bool keep_all_uvsets = _keep_all_uvsets || node_desc->
has_object_type(
"keep-all-uvsets");
1941 mayaegg_cat.info() <<
"will keep_all_uvsets" << endl;
1946 while (!pi.isDone()) {
1956 int index = pi.index();
1957 nassertv(index >= 0 && index < (
int)poly_shader_indices.length());
1958 int shader_index = poly_shader_indices[index];
1960 if (shader_index != -1) {
1961 nassertv(shader_index >= 0 && shader_index < (
int)shaders.length());
1962 MObject engine = shaders[shader_index];
1966 }
else if (default_shader != (
MayaShader *)NULL) {
1967 shader = default_shader;
1974 set_shader_attributes(*egg_poly, *shader,
true);
1990 bool ignore_vertex_color =
false;
1992 ignore_vertex_color = default_color_def->_has_texture && !(egg_vertex_color || _always_show_vertex_color);
1995 LColor poly_color(1.0f, 1.0f, 1.0f, 1.0f);
1996 if (!ignore_vertex_color) {
2001 egg_poly->clear_color();
2005 long num_verts = pi.polygonVertexCount();
2012 for (i = 0; i < num_verts; i++) {
2013 MPoint p = pi.point(i, MSpace::kWorld);
2015 p3d = p3d * vertex_frame_inv;
2018 centroid /= (double)num_verts;
2020 for (i = 0; i < num_verts; i++) {
2023 MPoint p = pi.point(i, MSpace::kWorld);
2024 LPoint3d p3d(p[0] / p[3], p[1] / p[3], p[2] / p[3]);
2025 p3d = p3d * vertex_frame_inv;
2029 status = pi.getNormal(i, n, MSpace::kWorld);
2031 status.perror(
"MItMeshPolygon::getNormal");
2034 n3d = n3d * vertex_frame_inv;
2035 vert.set_normal(n3d);
2039 if (mayaegg_cat.is_spam()) {
2041 mayaegg_cat.spam() <<
"shader->_color.size is " << shader->_color.size() << endl;
2043 mayaegg_cat.spam() <<
"primitive->tref.size is " << egg_poly->
get_num_textures() << endl;
2045 for (
size_t ti=0; ti< _shaders._uvset_names.size(); ++ti) {
2047 string uvset_name(_shaders._uvset_names[ti]);
2048 string panda_uvset_name = uvset_name;
2049 if (panda_uvset_name ==
"map1") {
2050 panda_uvset_name =
"default";
2052 if (mayaegg_cat.is_spam()) {
2053 mayaegg_cat.spam() <<
"--uvset_name :" << uvset_name << endl;
2060 bool keep_uv = keep_all_uvsets;
2061 bool project_uv =
false;
2065 for (
size_t tj = 0; tj < shader->_all_maps.size(); ++tj) {
2067 if (def->_uvset_name == uvset_name) {
2068 if (mayaegg_cat.is_spam()) {
2069 mayaegg_cat.spam() <<
"matched colordef idx: " << tj << endl;
2074 uv_projection = def->
project_uv(p3d, centroid);
2083 if (mayaegg_cat.is_spam()) {
2084 mayaegg_cat.spam() <<
"discarding unused uvset " << uvset_name << endl;
2092 vert.
set_uv(panda_uvset_name, uv_projection);
2096 MString uv_mstring(uvset_name.c_str());
2097 if (pi.hasUVs(uv_mstring, &status)) {
2098 status = pi.getUV(i, uvs, &uv_mstring);
2100 status.perror(
"MItMeshPolygon::getUV");
2103 if (uvs[0] > 1.0 || uvs[0] < -1.0) {
2105 uvs[0] = (long)(uvs[0]*1000);
2106 mayaegg_cat.debug() <<
"before rounding uvs[0]: " << uvs[0] << endl;
2107 uvs[0] = (double)(round((
double)uvs[0]/10.0)*10.0)/1000.0;
2108 mayaegg_cat.debug() <<
"after rounding uvs[0]: " << uvs[0] << endl;
2110 if (uvs[1] > 1.0 || uvs[1] < -1.0) {
2111 uvs[1] = (long)(uvs[1]*1000);
2112 mayaegg_cat.debug() <<
"before rounding uvs[1]: " << uvs[1] << endl;
2113 uvs[1] = (double)(round((
double)uvs[1]/10.0)*10.0)/1000.0;
2114 mayaegg_cat.debug() <<
"after rounding uvs[1]: " << uvs[1] << endl;
2123 if (!ignore_vertex_color) {
2124 if (mayaegg_cat.is_spam()) {
2125 mayaegg_cat.spam() <<
"poly_color = " << poly_color << endl;
2127 set_vertex_color(vert,pi,i,shader,poly_color);
2138 bool got_face_normal =
false;
2141 status = pi.getNormal(n, MSpace::kWorld);
2143 status.perror(
"MItMeshPolygon::getNormal face");
2145 face_normal.set(n[0], n[1], n[2]);
2146 face_normal = face_normal * vertex_frame_inv;
2147 got_face_normal =
true;
2148 egg_poly->set_normal(face_normal);
2157 if (order_normal.dot(face_normal) < 0.0) {
2159 if (mayaegg_cat.is_debug()) {
2161 <<
"reversing polygon\n";
2168 if (mayaegg_cat.is_spam()) {
2169 mayaegg_cat.spam() <<
"done traversing polys" << endl;
2175 bool got_weights =
false;
2178 MFloatArray weights;
2179 if (_animation_convert == AC_model) {
2181 get_vertex_weights(dag_path, mesh, joints, weights);
2184 if (got_weights && !joints.empty()) {
2185 int num_joints = joints.size();
2186 int num_weights = (int)weights.length();
2187 int num_verts = num_weights / num_joints;
2190 nassertv(num_weights == num_verts * num_joints);
2193 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
2196 nassertv(maya_vi >= 0 && maya_vi < num_verts);
2198 for (
int ji = 0; ji < num_joints; ++ji) {
2199 PN_stdfloat weight = weights[maya_vi * num_joints + ji];
2200 if (weight != 0.0f) {
2201 EggGroup *joint = joints[ji];
2202 if (joint != (EggGroup *)NULL) {
2218 if (_animation_convert == AC_model) {
2219 int num_orig_mesh_verts = mesh.numVertices();
2222 for (
int i = 0; i < num_sliders; i++) {
2231 MFnMesh blend_mesh(dag_path, &status);
2233 mayaegg_cat.warning()
2234 << name <<
" no longer has a mesh after applying "
2235 << blend_desc->get_name() <<
"\n";
2238 if (blend_mesh.numVertices() != num_orig_mesh_verts) {
2239 mayaegg_cat.warning()
2240 <<
"Ignoring " << blend_desc->get_name() <<
" for "
2241 << name <<
"; blend shape has " << blend_mesh.numVertices()
2242 <<
" vertices while original shape has "
2243 << num_orig_mesh_verts <<
".\n";
2247 status = blend_mesh.getPoints(verts, MSpace::kWorld);
2249 status.perror(
"MFnMesh::getPoints");
2251 int num_verts = (int)verts.length();
2253 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
2256 nassertv(maya_vi >= 0 && maya_vi < num_verts);
2258 const MPoint &m = verts[maya_vi];
2259 LPoint3d m3d(m[0] / m[3], m[1] / m[3], m[2] / m[3]);
2260 m3d = m3d * vertex_frame_inv;
2265 vert->_dxyzs.
insert(dxyz);
2270 MFloatVectorArray norms;
2271 status = blend_mesh.getNormals(norms, MSpace::kWorld);
2273 status.perror(
"MFnMesh::getNormals");
2275 int num_norms = (int)norms.length();
2277 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
2280 nassertv(maya_vi >= 0 && maya_vi < num_norms);
2282 const MFloatVector &m = norms[maya_vi];
2284 m3d = m3d * vertex_frame_inv;
2286 LNormald delta = m3d - vert->get_normal();
2289 vert->_dnormals.
insert(dnormal);
2311 void MayaToEggConverter::
2312 make_locator(
const MDagPath &dag_path,
const MFnDagNode &dag_node,
2313 EggGroup *egg_group) {
2316 unsigned int num_children = dag_node.childCount();
2318 bool found_locator =
false;
2319 for (
unsigned int ci = 0; ci < num_children && !found_locator; ci++) {
2320 locator = dag_node.child(ci);
2321 found_locator = (locator.apiType() == MFn::kLocator);
2324 if (!found_locator) {
2326 <<
"Couldn't find locator within locator node "
2327 << dag_path.fullPathName().asChar() <<
"\n";
2332 if (!get_vec3d_attribute(locator,
"localPosition", p3d)) {
2334 <<
"Couldn't get position of locator "
2335 << dag_path.fullPathName().asChar() <<
"\n";
2341 MMatrix mat = dag_path.inclusiveMatrix(&status);
2343 status.perror(
"Can't get coordinate space for locator");
2346 LMatrix4d n2w(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
2347 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
2348 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
2349 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
2368 void MayaToEggConverter::
2369 make_camera_locator(
const MDagPath &dag_path,
const MFnDagNode &dag_node,
2370 EggGroup *egg_group) {
2373 unsigned int num_children = dag_node.childCount();
2375 bool found_camera =
false;
2376 for (
unsigned int ci = 0; ci < num_children && !found_camera; ci++) {
2377 locator = dag_node.child(ci);
2378 found_camera = (locator.apiType() == MFn::kCamera);
2381 if (!found_camera) {
2383 <<
"Couldn't find camera"
2384 << dag_path.fullPathName().asChar() <<
"\n";
2387 MFnCamera camera (dag_path, &status);
2389 status.perror(
"MFnCamera constructor");
2392 MPoint eyePoint = camera.eyePoint(MSpace::kWorld);
2393 LPoint3d p3d (eyePoint.x, eyePoint.y, eyePoint.z);
2412 void MayaToEggConverter::
2413 make_light_locator(
const MDagPath &dag_path,
const MFnDagNode &dag_node,
2414 EggGroup *egg_group) {
2417 unsigned int num_children = dag_node.childCount();
2419 bool found_alight =
false;
2420 bool found_dlight =
false;
2421 bool found_plight =
false;
2422 for (
unsigned int ci = 0; ci < num_children && !found_alight && !found_dlight && !found_plight; ci++) {
2423 locator = dag_node.child(ci);
2424 found_alight = (locator.apiType() == MFn::kAmbientLight);
2425 found_dlight = (locator.apiType() == MFn::kDirectionalLight);
2426 found_plight = (locator.apiType() == MFn::kPointLight);
2429 if (!found_alight && !found_dlight && !found_plight) {
2431 <<
"Couldn't find light within locator node "
2432 << dag_path.fullPathName().asChar() <<
"\n";
2440 MMatrix mat = dag_path.inclusiveMatrix(&status);
2442 status.perror(
"Can't get coordinate space for light");
2445 LMatrix4d n2w(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
2446 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
2447 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
2448 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
2463 bool MayaToEggConverter::
2464 get_vertex_weights(
const MDagPath &dag_path,
const MFnMesh &mesh,
2471 MObject attr = mesh.attribute(
"inMesh");
2476 MPlug history(mesh.object(), attr);
2477 MItDependencyGraph it(history, MFn::kDependencyNode,
2478 MItDependencyGraph::kUpstream,
2479 MItDependencyGraph::kDepthFirst,
2480 MItDependencyGraph::kNodeLevel);
2482 while (!it.isDone()) {
2486 MObject c_node = it.thisNode();
2487 if (c_node.hasFn(MFn::kSkinClusterFilter)) {
2491 MFnSkinCluster cluster(c_node, &status);
2493 status.perror(
"MFnSkinCluster constructor");
2499 MDagPathArray influence_objects;
2500 cluster.influenceObjects(influence_objects, &status);
2502 status.perror(
"MFnSkinCluster::influenceObjects");
2508 for (
unsigned oi = 0; oi < influence_objects.length(); oi++) {
2509 MDagPath joint_dag_path = influence_objects[oi];
2512 joints.push_back(joint);
2517 MFnSingleIndexedComponent sic;
2518 MObject sic_object = sic.create(MFn::kMeshVertComponent);
2519 sic.setCompleteData(mesh.numVertices());
2520 unsigned influence_count;
2522 status = cluster.getWeights(dag_path, sic_object,
2523 weights, influence_count);
2525 status.perror(
"MFnSkinCluster::getWeights");
2527 if (influence_count != influence_objects.length()) {
2529 <<
"MFnSkinCluster::influenceObjects() returns "
2530 << influence_objects.length()
2531 <<
" objects, but MFnSkinCluster::getWeights() reports "
2532 << influence_count <<
" objects.\n";
2541 }
else if (c_node.hasFn(MFn::kWeightGeometryFilt)) {
2544 MFnWeightGeometryFilter cluster(c_node, &status);
2546 status.perror(
"MFnWeightGeometryFilter constructor");
2550 MPlug matrix_plug = cluster.findPlug(
"matrix");
2551 if (!matrix_plug.isNull()) {
2552 MPlugArray matrix_pa;
2553 matrix_plug.connectedTo(matrix_pa,
true,
false, &status);
2555 status.perror(
"Can't find connected Joint");
2557 MObject jointObj = matrix_pa[0].node();
2558 MFnIkJoint jointFn(jointObj, &status);
2560 status.perror(
"Can't find connected JointDag");
2563 MDagPath joint_dag_path = MDagPath();
2564 status = jointFn.getPath(joint_dag_path);
2566 status.perror(
"MFnIkJoint::dagPath");
2570 joints.push_back(joint);
2574 MFnSingleIndexedComponent sic;
2575 MObject sic_object = sic.create(MFn::kMeshVertComponent);
2576 sic.setCompleteData(mesh.numVertices());
2578 status = cluster.getWeights(dag_path, sic_object,
2581 status.perror(
"MFnWeightGeometryFilter::getWeights");
2606 bool MayaToEggConverter::
2607 get_vertex_weights(
const MDagPath &dag_path,
const MFnNurbsSurface &surface,
2614 MObject attr = surface.attribute(
"create");
2619 MPlug history(surface.object(), attr);
2620 MItDependencyGraph it(history, MFn::kDependencyNode,
2621 MItDependencyGraph::kUpstream,
2622 MItDependencyGraph::kDepthFirst,
2623 MItDependencyGraph::kNodeLevel);
2625 while (!it.isDone()) {
2629 MObject c_node = it.thisNode();
2630 if (c_node.hasFn(MFn::kSkinClusterFilter)) {
2634 MFnSkinCluster cluster(c_node, &status);
2636 status.perror(
"MFnSkinCluster constructor");
2642 MDagPathArray influence_objects;
2643 cluster.influenceObjects(influence_objects, &status);
2645 status.perror(
"MFnSkinCluster::influenceObjects");
2651 for (
unsigned oi = 0; oi < influence_objects.length(); oi++) {
2652 MDagPath joint_dag_path = influence_objects[oi];
2655 joints.push_back(joint);
2660 MFnDoubleIndexedComponent dic;
2661 MObject dic_object = dic.create(MFn::kSurfaceCVComponent);
2662 dic.setCompleteData(surface.numCVsInU(), surface.numCVsInV());
2663 unsigned influence_count;
2665 status = cluster.getWeights(dag_path, dic_object,
2666 weights, influence_count);
2668 status.perror(
"MFnSkinCluster::getWeights");
2670 if (influence_count != influence_objects.length()) {
2672 <<
"MFnSkinCluster::influenceObjects() returns "
2673 << influence_objects.length()
2674 <<
" objects, but MFnSkinCluster::getWeights() reports "
2675 << influence_count <<
" objects.\n";
2702 void MayaToEggConverter::
2705 if (shader._legacy_mode) {
2706 set_shader_legacy(primitive, shader, mesh);
2708 set_shader_modern(primitive, shader, mesh);
2723 void MayaToEggConverter::
2727 for (
size_t idx=0; idx < shader._all_maps.size(); idx++) {
2729 if ((def->_is_alpha)&&(def->_opposite != 0)) {
2735 tex.set_format(def->_is_alpha ? EggTexture::F_alpha : EggTexture::F_rgb);
2736 apply_texture_filename(tex, *def);
2737 if (def->_opposite) {
2738 apply_texture_alpha_filename(tex, *def);
2740 apply_texture_uvprops(tex, *def);
2741 apply_texture_blendtype(tex, *def);
2768 void MayaToEggConverter::
2774 bool is_rgb =
false;
2775 bool is_decal =
false;
2776 bool is_interpolate =
false;
2779 for (i=0; i<(int)shader._color.size()-1; ++i) {
2781 if (color_def->_has_texture) {
2782 if ((EggTexture::EnvType)color_def->_interpolate) {
2783 is_interpolate =
true;
2785 else if ((EggTexture::EnvType)color_def->_blend_type == EggTexture::ET_modulate) {
2788 if (!color_def->_keep_alpha)
2791 else if ((EggTexture::EnvType)color_def->_blend_type == EggTexture::ET_decal) {
2803 string dummy_uvset_name;
2808 for (i=shader._color.size()-1; i>=0; --i) {
2810 if (mayaegg_cat.is_spam()) {
2811 mayaegg_cat.spam() <<
"slot " << i <<
":got color_def: " << color_def << endl;
2813 if (color_def->_has_texture || trans_def._has_texture) {
2815 if (mayaegg_cat.is_spam()) {
2816 mayaegg_cat.spam() <<
"got shader name:" << shader.get_name() << endl;
2817 mayaegg_cat.spam() <<
"ssa:texture name[" << i <<
"]: " << color_def->_texture_name << endl;
2820 string uvset_name = _shaders.
find_uv_link(color_def->_texture_name);
2821 if (mayaegg_cat.is_spam()) {
2822 mayaegg_cat.spam() <<
"ssa:corresponding uvset name is " << uvset_name << endl;
2825 if (color_def->_has_texture) {
2832 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
2833 tex.set_filename(outpath);
2834 tex.set_fullpath(fullpath);
2835 apply_texture_uvprops(tex, *color_def);
2839 if (trans_def._has_texture) {
2840 if (color_def->_wrap_u != trans_def._wrap_u ||
2841 color_def->_wrap_u != trans_def._wrap_u) {
2842 mayaegg_cat.warning()
2843 <<
"Shader " << shader.get_name()
2844 <<
" has contradictory wrap modes on color and texture.\n";
2847 if (!compare_texture_uvprops(tex, trans_def)) {
2850 if (bad_shaders.insert(shader.get_name()).second) {
2852 <<
"Color and transparency texture properties differ on shader "
2853 << shader.get_name() <<
"\n";
2865 if (trans_def._texture_filename == color_def->_texture_filename) {
2876 _path_replace->full_convert_path(filename, get_model_path(),
2878 tex.set_alpha_filename(outpath);
2879 tex.set_alpha_fullpath(fullpath);
2888 if (shader._color.size() > 1) {
2892 if (i!=shader._color.size()-1) {
2893 if (!i && is_interpolate) {
2897 tex.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_interpolate);
2898 tex.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_previous);
2899 tex.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
2900 tex.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_last_saved_result);
2901 tex.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
2902 tex.set_combine_source(EggTexture::CC_rgb, 2, EggTexture::CS_texture);
2903 tex.set_combine_operand(EggTexture::CC_rgb, 2, EggTexture::CO_src_alpha);
2905 tex.set_combine_mode(EggTexture::CC_alpha, EggTexture::CM_interpolate);
2906 tex.set_combine_source(EggTexture::CC_alpha, 0, EggTexture::CS_previous);
2907 tex.set_combine_operand(EggTexture::CC_alpha, 0, EggTexture::CO_src_alpha);
2908 tex.set_combine_source(EggTexture::CC_alpha, 1, EggTexture::CS_last_saved_result);
2909 tex.set_combine_operand(EggTexture::CC_alpha, 1, EggTexture::CO_src_alpha);
2910 tex.set_combine_source(EggTexture::CC_alpha, 2, EggTexture::CS_texture);
2911 tex.set_combine_operand(EggTexture::CC_alpha, 2, EggTexture::CO_src_alpha);
2914 if (is_interpolate) {
2915 tex.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_modulate);
2916 tex.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_primary_color);
2917 tex.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
2918 tex.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_texture);
2919 tex.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
2922 tex.set_env_type((EggTexture::EnvType)color_def->_blend_type);
2923 if (tex.get_env_type() == EggTexture::ET_modulate) {
2924 if (color_def->_has_alpha_channel) {
2927 if (mayaegg_cat.is_spam()) {
2929 << color_def->_texture_name
2930 <<
" should not have alpha channel in multiply mode: ignoring\n";
2935 tex.set_format(EggTexture::F_rgb);
2942 if (is_interpolate) {
2944 tex.set_saved_result(
true);
2946 else if (is_decal) {
2951 EggTexture texDummy(shader.get_name()+
".dummy",
"");
2952 if (mayaegg_cat.is_debug()) {
2953 mayaegg_cat.debug() <<
"creating dummy shader: " << texDummy.get_name() << endl;
2955 texDummy.set_filename(outpath);
2956 texDummy.set_fullpath(fullpath);
2957 apply_texture_uvprops(texDummy, *color_def);
2958 texDummy.set_combine_mode(EggTexture::CC_rgb, EggTexture::CM_modulate);
2959 texDummy.set_combine_source(EggTexture::CC_rgb, 0, EggTexture::CS_primary_color);
2960 texDummy.set_combine_operand(EggTexture::CC_rgb, 0, EggTexture::CO_src_color);
2961 texDummy.set_combine_source(EggTexture::CC_rgb, 1, EggTexture::CS_previous);
2962 texDummy.set_combine_operand(EggTexture::CC_rgb, 1, EggTexture::CO_src_color);
2966 tex.set_env_type(EggTexture::ET_replace);
2975 _path_replace->full_convert_path(filename, get_model_path(),
2977 tex.set_filename(outpath);
2978 tex.set_fullpath(fullpath);
2979 tex.set_format(EggTexture::F_alpha);
2980 apply_texture_uvprops(tex, trans_def);
2983 if (mayaegg_cat.is_debug()) {
2984 mayaegg_cat.debug() <<
"ssa:tref_name:" << tex.get_name() << endl;
2986 if (is_rgb && i == (
int)shader._color.size()-1) {
2988 tex.set_format(EggTexture::F_rgb);
2994 if (uvset_name.find(
"not found") == -1) {
2996 color_def->_uvset_name.assign(uvset_name.c_str());
2997 if (uvset_name !=
"map1") {
3000 if (i == (
int)shader._color.size()-1 && is_decal) {
3001 dummy_uvset_name.assign(color_def->_uvset_name);
3006 if (color_def->_uvset_name !=
"map1") {
3018 if (mayaegg_cat.is_spam()) {
3019 mayaegg_cat.spam() <<
"ssa:rgba = " << rgba << endl;
3024 if (color_def && color_def->_has_texture) {
3029 if (trans_def._has_texture) {
3035 rgba[0] *= color_def->_color_gain[0];
3036 rgba[1] *= color_def->_color_gain[1];
3037 rgba[2] *= color_def->_color_gain[2];
3038 rgba[3] *= color_def->_color_gain[3];
3039 if (mayaegg_cat.is_spam()) {
3040 mayaegg_cat.spam() <<
"ssa:rgba = " << rgba << endl;
3044 primitive.set_color(rgba);
3046 if (mayaegg_cat.is_spam()) {
3047 mayaegg_cat.spam() <<
" set_shader_attributes : end\n";
3058 void MayaToEggConverter::
3061 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
3062 tex.set_magfilter(EggTexture::FT_linear);
3064 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
3065 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
3067 tex.set_wrap_u(wrap_u);
3068 tex.set_wrap_v(wrap_v);
3081 void MayaToEggConverter::
3083 switch (color_def._blend_type) {
3084 case MayaShaderColorDef::BT_unspecified:
3085 tex.set_env_type(EggTexture::ET_unspecified);
3087 case MayaShaderColorDef::BT_modulate:
3088 tex.set_env_type(EggTexture::ET_modulate);
3090 case MayaShaderColorDef::BT_decal:
3091 tex.set_env_type(EggTexture::ET_decal);
3093 case MayaShaderColorDef::BT_blend:
3094 tex.set_env_type(EggTexture::ET_blend);
3096 case MayaShaderColorDef::BT_replace:
3097 tex.set_env_type(EggTexture::ET_replace);
3099 case MayaShaderColorDef::BT_add:
3100 tex.set_env_type(EggTexture::ET_add);
3102 case MayaShaderColorDef::BT_blend_color_scale:
3103 tex.set_env_type(EggTexture::ET_blend_color_scale);
3105 case MayaShaderColorDef::BT_modulate_glow:
3106 tex.set_env_type(EggTexture::ET_modulate_glow);
3108 case MayaShaderColorDef::BT_modulate_gloss:
3109 tex.set_env_type(EggTexture::ET_modulate_gloss);
3111 case MayaShaderColorDef::BT_normal:
3112 tex.set_env_type(EggTexture::ET_normal);
3114 case MayaShaderColorDef::BT_normal_height:
3115 tex.set_env_type(EggTexture::ET_normal_height);
3117 case MayaShaderColorDef::BT_glow:
3118 tex.set_env_type(EggTexture::ET_glow);
3120 case MayaShaderColorDef::BT_gloss:
3121 tex.set_env_type(EggTexture::ET_gloss);
3123 case MayaShaderColorDef::BT_height:
3124 tex.set_env_type(EggTexture::ET_height);
3126 case MayaShaderColorDef::BT_selector:
3127 tex.set_env_type(EggTexture::ET_selector);
3137 void MayaToEggConverter::
3141 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
3142 tex.set_filename(outpath);
3151 void MayaToEggConverter::
3153 if (def._opposite) {
3154 tex.set_format(EggTexture::F_rgba);
3155 if (def._opposite->_texture_filename != def._texture_filename) {
3158 _path_replace->full_convert_path(filename, get_model_path(), fullpath, outpath);
3174 bool MayaToEggConverter::
3179 EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
3180 EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
3184 if (wrap_u == EggTexture::WM_repeat) {
3185 tex.set_wrap_u(wrap_u);
3190 if (wrap_v == EggTexture::WM_repeat) {
3191 tex.set_wrap_v(wrap_v);
3197 LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
3198 m(1, 0), m(1, 1), 0.0, m(1, 2),
3200 m(2, 0), m(2, 1), 0.0, m(2, 2));
3218 bool MayaToEggConverter::
3224 EggGroup *decal_base = (EggGroup *)NULL;
3227 EggGroupNode::iterator ci;
3228 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
3230 if (child->
is_of_type(EggGroup::get_class_type())) {
3231 EggGroup *child_group = DCAST(EggGroup, child);
3233 if (decal_base != (
EggNode *)NULL) {
3235 <<
"Two children of " << egg_parent->get_name()
3236 <<
" both have decalbase set: " << decal_base->get_name()
3237 <<
" and " << child_group->get_name() <<
"\n";
3241 decal_base = child_group;
3245 decal_children.push_back(child_group);
3250 if (decal_base == (EggGroup *)NULL) {
3251 if (!decal_children.empty()) {
3252 mayaegg_cat.warning()
3253 << decal_children.front()->get_name()
3254 <<
" has decal, but no sibling node has decalbase.\n";
3258 if (decal_children.empty()) {
3259 mayaegg_cat.warning()
3260 << decal_base->get_name()
3261 <<
" has decalbase, but no sibling nodes have decal.\n";
3269 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
3270 EggGroup *child_group = (*di);
3275 decal_base->set_decal_flag(
true);
3280 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
3282 if (child->
is_of_type(EggGroupNode::get_class_type())) {
3284 if (!reparent_decals(child_group)) {
3301 if (cmp_nocase(arg,
"all") == 0) {
3303 }
else if (cmp_nocase(arg,
"model") == 0) {
3305 }
else if (cmp_nocase(arg,
"dcs") == 0) {
3307 }
else if (cmp_nocase(arg,
"none") == 0) {
3321 void MayaToEggConverter::
3323 if (shader == (
MayaShader *)NULL || shader->_legacy_mode) {
3324 set_vertex_color_legacy(vert, pi, vert_index, shader, color);
3326 set_vertex_color_modern(vert, pi, vert_index, shader, color);
3338 void MayaToEggConverter::
3339 set_vertex_color_legacy(
EggVertex &vert, MItMeshPolygon &pi,
int vert_index,
const MayaShader *shader,
const LColor &color){
3340 if (pi.hasColor()) {
3342 MStatus status = pi.getColor(c, vert_index);
3344 status.perror(
"MItMeshPolygon::getColor");
3351 vert.set_color(
LColor(c.r * color[0], c.g * color[1], c.b * color[2], c.a * color[3]));
3353 if (mayaegg_cat.is_spam()) {
3354 mayaegg_cat.spam() <<
"maya_color = " << c.r <<
" " << c.g <<
" " << c.b <<
" " << c.a << endl;
3355 mayaegg_cat.spam() <<
"vert_color = " << vert.
get_color() << endl;
3359 vert.set_color(color);
3372 void MayaToEggConverter::
3373 set_vertex_color_modern(
EggVertex &vert, MItMeshPolygon &pi,
int vert_index,
const MayaShader *shader,
const LColor &color) {
3375 if (pi.hasColor(vert_index)) {
3377 MStatus status = pi.getColor(c, vert_index);
3379 vert.set_color(
LColor(c.r, c.g, c.b, c.a));
3385 if (shader->_color_maps.empty()) {
3386 const LColord &c = shader->_flat_color;
3387 vert.set_color(
LColor((PN_stdfloat)c[0], (PN_stdfloat)c[1], (PN_stdfloat)c[2], (PN_stdfloat)c[3]));
3390 vert.set_color(
LColor(1.0f, 1.0f, 1.0f, 1.0f));
void set_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_fullpath().
EggXfmSAnim * get_egg_anim(MayaNodeDesc *node_desc)
Returns the anim table corresponding to the joint for the indicated node.
A base class for any of a number of kinds of geometry primitives: polygons, point lights...
void optimize()
Optimizes the data by collapsing a long table of duplicate values into a single value.
void setup(int order, int num_knots)
Prepares a new curve definition with the indicated order and number of knots.
void add_subset(const GlobPattern &glob)
Adds a name pattern to the list of subset nodes.
A handle to a Maya blend shape description.
bool has_input_frame_rate() const
Returns true if the frame rate has been explicitly specified via set_input_frame_rate(), or false otherwise.
bool has_dag_path() const
Returns true if a Maya dag path has been associated with this node, false otherwise.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
EggUserData * get_user_data() const
Returns the user data pointer most recently stored on this object, or NULL if nothing was previously ...
bool has_user_data() const
Returns true if a generic user data pointer has recently been set and not yet cleared, false otherwise.
bool open_api(bool revert_directory=true)
Attempts to open the Maya API if it was not already open, and returns true if successful, or false if there is an error.
MayaBlendDesc * get_blend_desc(int n) const
Returns the nth MayaBlendDesc object that affects the geometry in this node.
EggVertex * get_vertex(int index) const
Returns the vertex in the pool with the indicated index number, or NULL if no vertices have that inde...
void tag_all()
Tags the entire hierarchy for conversion.
EggTexture * create_unique_texture(const EggTexture ©, int eq)
Creates a new texture if there is not already one equivalent (according to eq, see EggTexture::is_equ...
This is a 4-by-4 transform matrix.
LColor get_rgba(size_t idx=0) const
Returns the overall color of the shader as a single-precision rgba value, where the alpha component r...
void add_texture(EggTexture *texture)
Applies the indicated texture to the primitive.
void clear_subsets()
Empties the list of subset nodes added via add_subset().
void add_data(double value)
Adds a single element to the table.
LColor get_color() const
Returns the color set on this particular attribute.
static TransformType string_transform_type(const string &arg)
Returns the TransformType value corresponding to the indicated string, or TT_invalid.
WrapMode determine_wrap_v() const
Determines the appropriate wrap in the V direction.
void bind_uvsets(MObject mesh)
Causes all shaders in the set to use the given mesh as a file-to-uvset map.
void close_api()
Closes the Maya API, if it was previously opened.
bool has_object_type(string object_type) const
Returns true if this node or any of its parent has_object_type of object_type.
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
void set_pos(double pos)
Sets the vertex position.
int get_num_cvs() const
Returns the total number of control vertices that should* be defined for the curve.
A base class for nodes in the hierarchy that are not leaf nodes.
This is a four-component point in space.
void clear()
Resets the entire tree in preparation for repopulating with a new scene.
int get_num_nodes() const
Returns the total number of nodes in the hierarchy, not counting the root node.
Defines a texture map that may be applied to geometry.
bool ignore_slider(const string &name) const
Returns true if the indicated name is on the list of sliders to ignore, false otherwise.
virtual DistanceUnit get_input_units()
This may be called after convert_file() has been called and returned true, indicating a successful co...
bool has_neutral_frame() const
Returns true if the neutral frame has been explicitly specified via set_neutral_frame(), or false otherwise.
void set_u_knot(int k, double value)
Resets the value of the indicated knot as indicated.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
MayaNodeDesc * get_node(int n) const
Returns the nth node in the hierarchy, in an arbitrary ordering.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
const LMatrix4d & get_vertex_frame_inv() const
Returns the inverse of the matrix returned by get_vertex_frame().
bool has_dcs_type() const
Returns true if the specified DCS type is not DC_none and not DC_unspecified.
void clear()
Removes all textures from the collection.
pair< iterator, bool > insert(const MorphType &value)
This is similar to the insert() interface for sets, except it does not guarantee that the resulting l...
bool convert_maya()
Fills up the egg_data structure according to the global maya model data.
EggData * get_egg_data()
Returns the EggData structure.
string get_panda_uvset_name()
Maya's default uvset name is "map1".
This is the base class for all three-component vectors and points.
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
void setup(int u_order, int v_order, int num_u_knots, int num_v_knots)
Prepares a new surface definition with the indicated order and number of knots in each dimension...
void set_alpha_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_alpha_fullpath().
This is a two-component point in space.
bool almost_equal(const LVecBase3d &other, double threshold) const
Returns true if two vectors are memberwise equal within a specified tolerance.
void clear()
Frees all of the Maya pointers kept within this object, in preparation for loading a new scene or rel...
This is our own Panda specialization on the default STL list.
bool has_output_frame_rate() const
Returns true if the frame rate has been explicitly specified via set_output_frame_rate(), or false otherwise.
virtual string get_additional_extensions() const
Returns a space-separated list of extension, in addition to the one returned by get_extension(), that are recognized by this converter.
void set_external_index(int external_index)
Sets a special index number that is associated with the EggVertex (but is not written to the egg file...
EggGroup * get_egg_group(MayaNodeDesc *node_desc)
Returns the EggGroupNode corresponding to the group or joint for the indicated node.
A single <Dxyz> or <Duv> or some such entry.
bool is_tagged() const
Returns true if the node has been tagged to be converted, false otherwise.
void set_knot(int k, double value)
Resets the value of the indicated knot as indicated.
void clear_egg(EggData *egg_data, EggGroupNode *egg_root, EggGroupNode *skeleton_node, EggGroupNode *morph_node)
Removes all of the references to generated egg structures from the tree, and prepares the tree for ge...
bool tag_named(const GlobPattern &glob)
Tags nodes matching the indicated glob (and all of their children) for conversion.
static const LVector3d & zero()
Returns a zero-length vector.
int get_external_index() const
Returns the number set by set_external_index().
bool force_joint(const string &name) const
Returns true if the indicated name is on the list of DAG nodes to treat as a joint, false otherwise.
MayaShader * find_shader_for_node(MObject node, bool legacy_shader)
Extracts the shader assigned to the indicated node.
void clear_force_joints()
Empties the list of force_joints added via add_force_joint().
LMatrix3d compute_texture_matrix() const
Returns a texture matrix corresponding to the texture transforms indicated by the shader...
MayaNodeDesc * build_node(const MDagPath &dag_path)
Returns a pointer to the node corresponding to the indicated dag_path object, creating it first if ne...
bool remove_object_type(const string &object_type)
Removes the first instance of the indicated object type from the group if it is present.
This is our own Panda specialization on the default STL vector.
void set_bface_flag(bool flag)
Sets the backfacing flag of the polygon.
LTexCoordd project_uv(const LPoint3d &pos, const LPoint3d &ref_point) const
If the shader has a projection (has_projection() returns true), this computes the appropriate UV corr...
void set_alpha_filename(const Filename &filename)
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
void set_v_knot(int k, double value)
Resets the value of the indicated knot as indicated.
void clear_excludes()
Empties the list of excluded nodes added via add_exclude().
void reset_sliders()
Resets all of the sliders associated with all blend shapes down to 0.
This is a 3-by-3 transform matrix.
void clear_error()
Resets the error flag to the no-error state.
virtual string get_extension() const
Returns the common extension of the file type this converter supports.
virtual void reverse_vertex_ordering()
Reverses the ordering of the vertices in this primitive, if appropriate, in order to change the direc...
Describes a single instance of a node in the Maya scene graph, relating it to the corresponding egg s...
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
The name of a file, such as a texture file or an Egg file.
This defines the various attributes that Maya may associate with the "color" channel for a particular...
void clear_ignore_sliders()
Empties the list of ignore_sliders added via add_ignore_slider().
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
WrapMode determine_wrap_u() const
Determines the appropriate wrap in the U direction.
PN_stdfloat get_slider() const
Returns the current position of the Maya slider associated with this blend shape. ...
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
MayaShaderColorDef * get_color_def(size_t idx=0) const
This is part of the deprecated codepath.
string find_uv_link(const string &match)
Returns the current mapping from file to uvset for the given file texture name.
void set_uv_name(const string &uv_name)
Specifies the named set of texture coordinates that this texture will use when it is applied to geome...
int get_num_textures() const
Returns the number of textures applied to the primitive.
virtual string get_name() const
Returns the English name of the file type this converter supports.
bool tag_joint_named(const GlobPattern &glob)
Tags nodes matching the indicated glob (and all of their children) for conversion.
Corresponds to a single "shader" in Maya.
MayaShader * find_shader_for_shading_engine(MObject engine, bool legacy_shader)
Returns the MayaShader object associated with the indicated "shading engine".
bool has_projection() const
Returns true if the shader has a projection in effect.
A parametric NURBS curve.
int get_num_cvs() const
Returns the total number of control vertices that should* be defined for the surface.
void optimize()
Optimizes the table by collapsing redundant sub-tables.
bool had_error() const
Returns true if an error was detected during the conversion process (unless _allow_errors is true)...
void clear_subroots()
Empties the list of subroot nodes added via add_subroot().
AnimationConvert get_animation_convert() const
Returns how source animation will be converted into egg structures.
bool has_end_frame() const
Returns true if the ending frame has been explicitly specified via set_end_frame(), or false if the ending frame should be implicit based on the source.
double get_input_frame_rate() const
Returns the value set by a previous call to set_input_frame_rate().
bool has_object_type(const string &object_type) const
Returns true if the indicated object type has been added to the group, or false otherwise.
bool build_hierarchy()
Walks through the complete Maya hierarchy but does not tag any nodes for conversion.
This class supervises the construction of an EggData structure from a single Maya file...
This is the base class for all three-component vectors and points.
bool untag_named(const GlobPattern &glob)
Un-tags nodes matching the indicated glob (and all of their children) for conversion.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
double get_frame_inc() const
Returns the value set by a previous call to set_frame_inc().
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
const MDagPath & get_dag_path() const
Returns the dag path associated with this node.
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
double get_start_frame() const
Returns the value set by a previous call to set_start_frame().
bool has_start_frame() const
Returns true if the starting frame has been explicitly specified via set_start_frame(), or false if the starting frame should be implicit based on the source.
MayaBlendDesc * get_blend_desc(int n) const
Returns the nth MayaBlendDesc object discovered in the tree.
bool almost_equal(const LMatrix3d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
A base class for things that may be directly added into the egg hierarchy.
void add_force_joint(const GlobPattern &glob)
Adds a name pattern to the list of force_joints.
A parametric NURBS surface.
int get_external_index2() const
Returns the number set by set_external_index2().
bool calculate_normal(LNormald &result, CoordinateSystem cs=CS_default) const
Calculates the true polygon normal–the vector pointing out of the front of the polygon–based on the v...
double get_neutral_frame() const
Returns the value set by a previous call to set_neutral_frame().
bool has_frame_inc() const
Returns true if the frame increment has been explicitly specified via set_frame_inc(), or false if the ending frame should be implicit based on the source.
void ref_vertex(EggVertex *vert, double membership=1.0)
Adds the vertex to the set of those referenced by the group, at the indicated membership level...
void set_slider(PN_stdfloat value)
Moves the Maya slider associated with this blend shape to the indicated value.
EggSAnimData * get_egg_slider(MayaBlendDesc *blend_desc)
Returns the anim table corresponding to the slider for the indicated blend.
void set_from_selection(bool from_selection)
Sets the flag that indicates whether the currently selected Maya geometry will be converted...
void tag_joint_all()
Tags the entire hierarchy for conversion.
void set_external_index2(int external_index2)
Similar to set_external_index(), but this is a different number which may be used for a different pur...
void clear()
Frees all of the previously-defined MayaShader objects associated with this set.
static const LMatrix3d & ident_mat()
Returns an identity matrix.
int get_v_index(int vertex_index) const
Returns the V index number of the given vertex within the EggPrimitive's linear list of vertices...
int get_u_index(int vertex_index) const
Returns the U index number of the given vertex within the EggPrimitive's linear list of vertices...
double get_output_frame_rate() const
Returns the value set by a previous call to set_output_frame_rate().
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
This is a base class for a family of converter classes that manage a conversion from some file type t...
void add_subroot(const GlobPattern &glob)
Adds a name pattern to the list of subroot nodes.
virtual SomethingToEggConverter * make_copy()
Allocates and returns a new copy of the converter.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it...
int get_num_blend_descs() const
Returns the number of unique MayaBlendDesc objects (and hence the number of morph sliders) that affec...
const LMatrix4d & get_node_frame_inv() const
Returns the inverse of the matrix returned by get_node_frame().
This class contains extra user data which is piggybacked onto EggGroup objects for the purpose of the...
This class presents a wrapper around the global Maya interface.
double get_end_frame() const
Returns the value set by a previous call to set_end_frame().
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
virtual bool convert_file(const Filename &filename)
Handles the reading of the input file and converting it to egg.
void add_ignore_slider(const GlobPattern &glob)
Adds a name pattern to the list of ignore_sliders.
bool tag_selected()
Tags the just the selected hierarchy for conversion, or the entire hierarchy if nothing is selected...
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
void add_exclude(const GlobPattern &glob)
Adds a name pattern to the list of excluded nodes.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).