From 1c6c6f4cdab19f12a344cbb59ca7878398119fcc Mon Sep 17 00:00:00 2001 From: "Asad M. Zaman" Date: Fri, 18 Feb 2005 20:15:55 +0000 Subject: [PATCH] first pass multi-texture support on maya2egg. Bugs are expected, please report to asad, if you see some model problems --- pandatool/src/maya/mayaShader.cxx | 74 +++-- pandatool/src/maya/mayaShader.h | 8 +- pandatool/src/maya/mayaShaderColorDef.cxx | 113 +++++++- pandatool/src/maya/mayaShaderColorDef.h | 7 +- pandatool/src/maya/maya_funcs.cxx | 118 ++++++-- pandatool/src/maya/maya_funcs.h | 3 + pandatool/src/mayaegg/mayaToEggConverter.cxx | 270 ++++++++++++------- pandatool/src/mayaegg/mayaToEggConverter.h | 5 +- pandatool/src/mayaprogs/mayaCopy.cxx | 8 +- 9 files changed, 440 insertions(+), 166 deletions(-) diff --git a/pandatool/src/maya/mayaShader.cxx b/pandatool/src/maya/mayaShader.cxx index 153404dd6a..c2ccfa572a 100644 --- a/pandatool/src/maya/mayaShader.cxx +++ b/pandatool/src/maya/mayaShader.cxx @@ -55,7 +55,6 @@ MayaShader(MObject engine) { if (!shader_plug.isNull()) { MPlugArray shader_pa; shader_plug.connectedTo(shader_pa, true, false); - for (size_t i = 0; i < shader_pa.length() && !found_shader; i++) { MObject shader = shader_pa[0].node(); found_shader = read_surface_shader(shader); @@ -70,6 +69,9 @@ MayaShader(MObject engine) { //////////////////////////////////////////////////////////////////// MayaShader:: ~MayaShader() { + for (size_t i=0; i<_color.size(); ++i) { + _color.pop_back(); + } } //////////////////////////////////////////////////////////////////// @@ -91,11 +93,23 @@ void MayaShader:: write(ostream &out) const { out << "Shader " << get_name() << "\n" << " color:\n"; - _color.write(out); + for (size_t i=0; i<_color.size(); ++i) { + _color[i]->write(out); + } out << " transparency:\n"; _transparency.write(out); } +//////////////////////////////////////////////////////////////////// +// Function: MayaShader::get_color_def +// Access: Public +// Description: Now that the shaders can have multiple textures +// return the color def i.e. texture at idx +//////////////////////////////////////////////////////////////////// +MayaShaderColorDef *MayaShader:: +get_color_def(size_t idx) const { + return _color[idx]; +} //////////////////////////////////////////////////////////////////// // Function: MayaShader::get_rgba // Access: Public @@ -110,13 +124,13 @@ write(ostream &out) const { // is true), this value is not used by Maya. //////////////////////////////////////////////////////////////////// Colorf MayaShader:: -get_rgba() const { +get_rgba(size_t idx) const { Colorf rgba(1.0f, 1.0f, 1.0f, 1.0f); - if (_color._has_flat_color) { - rgba[0] = (float)_color._flat_color[0]; - rgba[1] = (float)_color._flat_color[1]; - rgba[2] = (float)_color._flat_color[2]; + if (_color[idx]->_has_flat_color) { + rgba[0] = (float)_color[idx]->_flat_color[0]; + rgba[1] = (float)_color[idx]->_flat_color[1]; + rgba[2] = (float)_color[idx]->_flat_color[2]; } if (_transparency._has_flat_color) { @@ -143,7 +157,7 @@ bool MayaShader:: read_surface_shader(MObject shader) { MStatus status; MFnDependencyNode shader_fn(shader); - + if (maya_cat.is_spam()) { maya_cat.spam() << " Reading surface shader " << shader_fn.name().asChar() << "\n"; @@ -160,13 +174,21 @@ read_surface_shader(MObject shader) { // used. color_plug = shader_fn.findPlug("outColor"); } - + if (!color_plug.isNull()) { MPlugArray color_pa; color_plug.connectedTo(color_pa, true, false); + MayaShaderColorDef *color_p = new MayaShaderColorDef; for (size_t i = 0; i < color_pa.length(); i++) { - _color.read_surface_color(this, color_pa[0].node()); + maya_cat.spam() << "color_pa[" << i << "]:" << color_pa[i].name() << endl; + color_p->read_surface_color(this, color_pa[0].node()); + } + + if (color_pa.length() < 1) { + // assign a blank default color to this shader + maya_cat.spam() << shader_fn.name().asChar() << " was not connected to texture" << endl; + this->_color.push_back(color_p); } } @@ -181,32 +203,42 @@ read_surface_shader(MObject shader) { trans_plug.connectedTo(trans_pa, true, false); for (size_t i = 0; i < trans_pa.length(); i++) { - _transparency.read_surface_color(this, trans_pa[0].node()); + maya_cat.spam() << "read a transparency texture" << endl; + _transparency.read_surface_color(this, trans_pa[0].node(), true); } } // Also try to get the ordinary color directly from the surface // shader. + bool b_color_def = true; if (shader.hasFn(MFn::kLambert)) { MFnLambertShader lambert_fn(shader); MColor color = lambert_fn.color(&status); if (status) { // Warning! The alpha component of color doesn't mean // transparency in Maya. - _color._has_flat_color = true; - _color._flat_color.set(color.r, color.g, color.b, color.a); - _transparency._flat_color.set(0.0, 0.0, 0.0, 0.0); + for (size_t i=0; i<_color.size(); ++i) { + _color[i]->_has_flat_color = true; + _color[i]->_flat_color.set(color.r, color.g, color.b, color.a); + maya_cat.spam() << shader_fn.name().asChar() << " set shader color" << endl; + // needed to print the final check + if (!_color[i]->_has_flat_color && !_color[i]->_has_texture) + b_color_def = false; - // Get the transparency separately. - color = lambert_fn.transparency(&status); - if (status) { - _transparency._has_flat_color = true; - _transparency._flat_color.set(color.r, color.g, color.b, color.a); + _transparency._flat_color.set(0.0, 0.0, 0.0, 0.0); + + // Get the transparency separately. + color = lambert_fn.transparency(&status); + if (status) { + _transparency._has_flat_color = true; + _transparency._flat_color.set(color.r, color.g, color.b, color.a); + } } } } - - if (!_color._has_flat_color && !_color._has_texture) { + // if (!_color._has_flat_color && !_color._has_texture) { + if (!b_color_def) { + maya_cat.info() << shader_fn.name().asChar() << "Color def not found" << endl; if (maya_cat.is_spam()) { maya_cat.spam() << " Color definition not found.\n"; diff --git a/pandatool/src/maya/mayaShader.h b/pandatool/src/maya/mayaShader.h index acc64fea36..48b75e700e 100644 --- a/pandatool/src/maya/mayaShader.h +++ b/pandatool/src/maya/mayaShader.h @@ -44,10 +44,14 @@ public: void output(ostream &out) const; void write(ostream &out) const; - Colorf get_rgba() const; + Colorf get_rgba(size_t idx=0) const; + MayaShaderColorDef *get_color_def(size_t idx=0) const; - MayaShaderColorDef _color; MayaShaderColorDef _transparency; + //MayaShaderColorDef _color; + // There could be multiple textures, so create an array of these colordefs + typedef pvector ColorDef; + ColorDef _color; private: bool read_surface_shader(MObject shader); diff --git a/pandatool/src/maya/mayaShaderColorDef.cxx b/pandatool/src/maya/mayaShaderColorDef.cxx index 1583a7b642..b3e83c13f9 100644 --- a/pandatool/src/maya/mayaShaderColorDef.cxx +++ b/pandatool/src/maya/mayaShaderColorDef.cxx @@ -44,6 +44,8 @@ MayaShaderColorDef() { _flat_color.set(0.0, 0.0, 0.0, 0.0); _has_texture = false; + _texture_name = ""; + _uvset_name = "map1"; _projection_type = PT_off; _map_uvs = NULL; @@ -63,6 +65,44 @@ MayaShaderColorDef() { _color_object = (MObject *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: MayaShaderColorDef::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +MayaShaderColorDef:: +MayaShaderColorDef(MayaShaderColorDef ©) { + _has_texture = copy._has_texture; + _texture_filename = copy._texture_filename; + _texture_name = copy._texture_name; + _uvset_name = copy._uvset_name; + _color_gain = copy._color_gain; + + _has_flat_color = copy._has_flat_color; + _flat_color = copy._flat_color; + + _projection_type = copy._projection_type; + _projection_matrix = copy._projection_matrix; + _u_angle = copy._u_angle; + _v_angle = copy._v_angle; + + _coverage = copy._coverage; + _translate_frame = copy._translate_frame; + _rotate_frame = copy._rotate_frame; + + _mirror = copy._mirror; + _stagger = copy._stagger; + _wrap_u = copy._wrap_u; + _wrap_v = copy._wrap_v; + + _repeat_uv = copy._repeat_uv; + _offset = copy._offset; + _rotate_uv = copy._rotate_uv; + + _map_uvs = copy._map_uvs; + _color_object = copy._color_object; +} + //////////////////////////////////////////////////////////////////// // Function: MayaShaderColorDef::Destructor // Access: Public @@ -130,7 +170,9 @@ project_uv(const LPoint3d &pos, const LPoint3d ¢roid) const { void MayaShaderColorDef:: write(ostream &out) const { if (_has_texture) { - out << " texture is " << _texture << "\n" + out << " texture filename is " << _texture_filename << "\n" + << " texture name is " << _texture_name << "\n" + << " uv_set name is " << _uvset_name << "\n" << " coverage is " << _coverage << "\n" << " translate_frame is " << _translate_frame << "\n" << " rotate_frame is " << _rotate_frame << "\n" @@ -159,7 +201,7 @@ reset_maya_texture(const Filename &texture) { if (_color_object != (MObject *)NULL) { _has_texture = set_string_attribute(*_color_object, "fileTextureName", texture.to_os_generic()); - _texture = texture; + _texture_filename = texture; if (!_has_texture) { maya_cat.error() @@ -182,7 +224,7 @@ reset_maya_texture(const Filename &texture) { // properties. //////////////////////////////////////////////////////////////////// void MayaShaderColorDef:: -read_surface_color(const MayaShader *shader, MObject color) { +read_surface_color(MayaShader *shader, MObject color, bool trans) { RGBColorf color_gain; if (get_vec3f_attribute(color, "colorGain", color_gain)) { _color_gain[0] *= color_gain[0]; @@ -193,15 +235,14 @@ read_surface_color(const MayaShader *shader, MObject color) { if (get_maya_attribute(color, "alphaGain", alpha_gain)) { _color_gain[3] *= alpha_gain; } - if (color.hasFn(MFn::kFileTexture)) { _color_object = new MObject(color); string filename; _has_texture = get_string_attribute(color, "fileTextureName", filename); _has_texture = _has_texture && !filename.empty(); if (_has_texture) { - _texture = Filename::from_os_specific(filename); - if (_texture.is_directory()) { + _texture_filename = Filename::from_os_specific(filename); + if (_texture_filename.is_directory()) { maya_cat.warning() << "Shader " << shader->get_name() << " references texture filename " << filename @@ -224,7 +265,13 @@ read_surface_color(const MayaShader *shader, MObject color) { get_vec2f_attribute(color, "offset", _offset); get_angle_attribute(color, "rotateUV", _rotate_uv); + if (!trans) { + maya_cat.debug() << "pushed a file texture" << endl; + shader->_color.push_back(this); + } + } else if (color.hasFn(MFn::kProjection)) { + maya_cat.debug() << "reading a projection texture" << endl; // This is a projected texture. We will have to step one level // deeper to find the actual texture. MFnDependencyNode projection_fn(color); @@ -256,6 +303,60 @@ read_surface_color(const MayaShader *shader, MObject color) { set_projection_type(type); } + } else if (color.hasFn(MFn::kLayeredTexture)) { + maya_cat.debug() << "Found layered texture" << endl; + //list_maya_attributes(color); + //shader->_multi_texture = true; + //get_enum_attribute(color,"blendMode",shader->_blend_mode); + //maya_cat.debug() << "blend mode :" << shader->_blend_mode << endl; + MFnDependencyNode layered_fn(color); + MPlugArray color_pa; + MStatus status = layered_fn.getConnections(color_pa); + maya_cat.debug() << "number of connections: " << color_pa.length() << endl; + bool first = true; + for (size_t i=0; iread_surface_color(shader, pla[j].node()); + color_p->_texture_name.assign(pla[j].name().asChar()); + int loc = color_p->_texture_name.find('.',0); + if( loc != string::npos ) + color_p->_texture_name.resize(loc); + maya_cat.debug() << "uv_name : " << color_p->_texture_name << endl; + } + else { + maya_cat.debug() << pl.name() << " first:connectedTo: " << pla[j].name() << endl; + read_surface_color(shader, pla[j].node()); + _texture_name.assign(pla[j].name().asChar()); + int loc = _texture_name.find('.',0); + if( loc != string::npos ) + _texture_name.resize(loc); + maya_cat.debug() << "uv_name : " << _texture_name << endl; + first = false; + } + + // lets see what this is connected to!? + MPlug pl_temp = pla[j]; + MPlugArray pla_temp; + pl_temp.connectedTo(pla_temp, true, false); + maya_cat.debug() << pl_temp.name() << "connectedTo:" << pla_temp.length() << " plugs\n"; + } + /* + string blah; + get_enum_attribute(pl.node(),"blendMode",blah); + maya_cat.debug() << "blend mode :" << blah << endl; + float alpha; + get_maya_attribute(pl.node(),"alpha",alpha); + maya_cat.debug() << "alpha :" << alpha << endl; + */ + } } else { // This shader wasn't understood. if (maya_cat.is_debug()) { diff --git a/pandatool/src/maya/mayaShaderColorDef.h b/pandatool/src/maya/mayaShaderColorDef.h index 71f5ee21c5..9479b73c6e 100755 --- a/pandatool/src/maya/mayaShaderColorDef.h +++ b/pandatool/src/maya/mayaShaderColorDef.h @@ -36,6 +36,7 @@ class MayaShader; class MayaShaderColorDef { public: MayaShaderColorDef(); + MayaShaderColorDef(MayaShaderColorDef&); ~MayaShaderColorDef(); LMatrix3d compute_texture_matrix() const; @@ -58,7 +59,9 @@ public: }; bool _has_texture; - Filename _texture; + Filename _texture_filename; + string _texture_name; + string _uvset_name; Colorf _color_gain; bool _has_flat_color; @@ -83,7 +86,7 @@ public: double _rotate_uv; private: - void read_surface_color(const MayaShader *shader, MObject color); + void read_surface_color(MayaShader *shader, MObject color, bool trans=false); void set_projection_type(const string &type); LPoint2d map_planar(const LPoint3d &pos, const LPoint3d ¢roid) const; diff --git a/pandatool/src/maya/maya_funcs.cxx b/pandatool/src/maya/maya_funcs.cxx index bf6e78a572..6e5ade109e 100644 --- a/pandatool/src/maya/maya_funcs.cxx +++ b/pandatool/src/maya/maya_funcs.cxx @@ -29,7 +29,9 @@ #include #include #include +#include #include +#include #include #include #include "post_maya_include.h" @@ -170,7 +172,7 @@ get_bool_attribute(MObject &node, const string &attribute_name, } if (!get_maya_attribute(node, attribute_name, value)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a bool value.\n"; describe_maya_attribute(node, attribute_name); @@ -189,7 +191,7 @@ get_angle_attribute(MObject &node, const string &attribute_name, double &value) { MAngle maya_value; if (!get_maya_attribute(node, attribute_name, maya_value)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have an angle value.\n"; describe_maya_attribute(node, attribute_name); @@ -211,7 +213,7 @@ get_vec2f_attribute(MObject &node, const string &attribute_name, MObject vec2f_object; if (!get_maya_attribute(node, attribute_name, vec2f_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a vec2f object value.\n"; describe_maya_attribute(node, attribute_name); @@ -220,7 +222,7 @@ get_vec2f_attribute(MObject &node, const string &attribute_name, MFnNumericData data(vec2f_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << vec2f_object.apiTypeStr() << ", not a NumericData.\n"; return false; @@ -228,7 +230,7 @@ get_vec2f_attribute(MObject &node, const string &attribute_name, status = data.getData(value[0], value[1]); if (!status) { - maya_cat.error() + maya_cat.warning() << "Unable to extract 2 floats from " << attribute_name << ", of type " << vec2f_object.apiTypeStr() << "\n"; } @@ -248,7 +250,7 @@ get_vec3f_attribute(MObject &node, const string &attribute_name, MObject vec3f_object; if (!get_maya_attribute(node, attribute_name, vec3f_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a vec3f object value.\n"; describe_maya_attribute(node, attribute_name); @@ -257,7 +259,7 @@ get_vec3f_attribute(MObject &node, const string &attribute_name, MFnNumericData data(vec3f_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << vec3f_object.apiTypeStr() << ", not a NumericData.\n"; return false; @@ -265,7 +267,7 @@ get_vec3f_attribute(MObject &node, const string &attribute_name, status = data.getData(value[0], value[1], value[2]); if (!status) { - maya_cat.error() + maya_cat.warning() << "Unable to extract 3 floats from " << attribute_name << ", of type " << vec3f_object.apiTypeStr() << "\n"; } @@ -285,7 +287,7 @@ get_vec2d_attribute(MObject &node, const string &attribute_name, MObject vec2d_object; if (!get_maya_attribute(node, attribute_name, vec2d_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a vec2d object value.\n"; describe_maya_attribute(node, attribute_name); @@ -294,7 +296,7 @@ get_vec2d_attribute(MObject &node, const string &attribute_name, MFnNumericData data(vec2d_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << vec2d_object.apiTypeStr() << ", not a NumericData.\n"; return false; @@ -302,7 +304,7 @@ get_vec2d_attribute(MObject &node, const string &attribute_name, status = data.getData(value[0], value[1]); if (!status) { - maya_cat.error() + maya_cat.warning() << "Unable to extract 2 doubles from " << attribute_name << ", of type " << vec2d_object.apiTypeStr() << "\n"; } @@ -322,7 +324,7 @@ get_vec3d_attribute(MObject &node, const string &attribute_name, MObject vec3d_object; if (!get_maya_attribute(node, attribute_name, vec3d_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a vec3d object value.\n"; describe_maya_attribute(node, attribute_name); @@ -331,7 +333,7 @@ get_vec3d_attribute(MObject &node, const string &attribute_name, MFnNumericData data(vec3d_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << vec3d_object.apiTypeStr() << ", not a NumericData.\n"; return false; @@ -339,7 +341,7 @@ get_vec3d_attribute(MObject &node, const string &attribute_name, status = data.getData(value[0], value[1], value[2]); if (!status) { - maya_cat.error() + maya_cat.warning() << "Unable to extract 3 doubles from " << attribute_name << ", of type " << vec3d_object.apiTypeStr() << "\n"; } @@ -362,7 +364,7 @@ get_mat4d_attribute(MObject &node, const string &attribute_name, MFnMatrixData matrix_data(matrix, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << node.apiTypeStr() << ", not a Matrix.\n"; return false; @@ -395,7 +397,7 @@ get_enum_attribute(MObject &node, const string &attribute_name, MObject attrib = plug.attribute(); MFnEnumAttribute enum_attrib(attrib, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Not an enum attribute: " << attribute_name << "\n"; return false; } @@ -403,7 +405,7 @@ get_enum_attribute(MObject &node, const string &attribute_name, short index; status = plug.getValue(index); if (!status) { - maya_cat.error() + maya_cat.warning() << "Could not get numeric value of " << attribute_name << "\n"; status.perror("MPlug::getValue(short)"); return false; @@ -411,7 +413,7 @@ get_enum_attribute(MObject &node, const string &attribute_name, MString name = enum_attrib.fieldName(index, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Invalid value for " << attribute_name << ": " << index << "\n"; status.perror("MFnEnumAttribute::fieldName()"); return false; @@ -433,7 +435,7 @@ get_string_attribute(MObject &node, const string &attribute_name, MObject string_object; if (!get_maya_attribute(node, attribute_name, string_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have an string object value.\n"; describe_maya_attribute(node, attribute_name); @@ -442,7 +444,7 @@ get_string_attribute(MObject &node, const string &attribute_name, MFnStringData data(string_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << string_object.apiTypeStr() << ", not a StringData.\n"; return false; @@ -465,7 +467,7 @@ set_string_attribute(MObject &node, const string &attribute_name, // First, we get the string_object, then we set its string. MObject string_object; if (!get_maya_attribute(node, attribute_name, string_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " does not have a string object value.\n"; describe_maya_attribute(node, attribute_name); @@ -474,7 +476,7 @@ set_string_attribute(MObject &node, const string &attribute_name, MFnStringData data(string_object, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " is of type " << string_object.apiTypeStr() << ", not a StringData.\n"; return false; @@ -489,7 +491,7 @@ set_string_attribute(MObject &node, const string &attribute_name, // And it appears we now need to set the string object back. if (!set_maya_attribute(node, attribute_name, string_object)) { - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " suddenly does not have a string object value.\n"; return false; @@ -498,9 +500,63 @@ set_string_attribute(MObject &node, const string &attribute_name, return true; } +//////////////////////////////////////////////////////////////////// +// Function: describe_compound_attribute +// Description: Extracts the children of this attribute from the +// MObject. test for now +//////////////////////////////////////////////////////////////////// +bool +describe_compound_attribute(MObject &node) { + MStatus status; + + MFnCompoundAttribute comp_attr(node, &status); + + maya_cat.info() << "comp_attr has:" << comp_attr.numChildren() << " children" << endl; + for (size_t i = 0; i < comp_attr.numChildren(); i++) { + MObject child = comp_attr.child(i, &status); + if (child.apiType() == MFn::kAttribute3Float){ + RGBColorf color; + /* + if (get_vec3f_attribute(child, "color", color)) { + maya_cat.info() << "color: " << color << endl; + } + */ + } + else if (child.apiType() == MFn::kNumericAttribute) { + MFnNumericAttribute numeric(child, &status); + if (status) { + switch(numeric.unitType()) { + case MFnNumericData::kFloat : + float alpha; + status = numeric.getDefault(alpha); + maya_cat.info() << "found a float :" << alpha << endl; + break; + case MFnNumericData::kBoolean : + bool v; + status = numeric.getDefault(v); + maya_cat.info() << "found a bool :" << v << endl; + default: + maya_cat.info() << numeric.unitType() << endl; + } + } + } + else if (child.apiType() == MFn::kEnumAttribute) { + MFnEnumAttribute enu(child, &status); + if (status) { + MString blah; + status = enu.getDefault(blah); + maya_cat.info() << "found a string :" << blah << endl; + MPlug plug = MPlug(node, child); + maya_cat.info() << "plug name" << plug.name() << endl; + } + } + } + return true; +} + //////////////////////////////////////////////////////////////////// // Function: describe_maya_attribute -// Description: Writes some error output about the indicated Maya +// Description: Writes some warning output about the indicated Maya // attribute. //////////////////////////////////////////////////////////////////// void @@ -508,20 +564,20 @@ describe_maya_attribute(MObject &node, const string &attribute_name) { MStatus status; MFnDependencyNode node_fn(node, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n"; return; } MObject attr = node_fn.attribute(attribute_name.c_str(), &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Object " << node_fn.name().asChar() << " does not support attribute " << attribute_name << "\n"; return; } - maya_cat.error() + maya_cat.warning() << "Attribute " << attribute_name << " on object " << node_fn.name().asChar() << " has type " << attr.apiTypeStr() << "\n"; } @@ -608,7 +664,7 @@ list_maya_attributes(MObject &node) { MStatus status; MFnDependencyNode node_fn(node, &status); if (!status) { - maya_cat.error() + maya_cat.warning() << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n"; return; } @@ -631,6 +687,10 @@ list_maya_attributes(MObject &node) { << " " << i << ". " << plug.name().asChar() << ", " << plug.attribute().apiTypeStr() << ", " << plug.node().apiTypeStr(); + if (plug.attribute().apiType() == MFn::kCompoundAttribute) { + //maya_cat.info() << plug.info(); + //describe_compound_attribute(plug.attribute()); + } if (plug.isConnected()) { maya_cat.info(false) << " (*)"; @@ -639,7 +699,7 @@ list_maya_attributes(MObject &node) { << "\n"; } } - + maya_cat.info() << name << " has " << node_fn.attributeCount() << " attributes.\n"; for (i = 0; i < node_fn.attributeCount(); i++) { diff --git a/pandatool/src/maya/maya_funcs.h b/pandatool/src/maya/maya_funcs.h index 637c54425d..d83548d74e 100644 --- a/pandatool/src/maya/maya_funcs.h +++ b/pandatool/src/maya/maya_funcs.h @@ -100,6 +100,9 @@ set_string_attribute(MObject &node, const string &attribute_name, void describe_maya_attribute(MObject &node, const string &attribute_name); +bool +describe_compound_attribute(MObject &node); + string string_mfndata_type(MFnData::Type type); diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index 7ebdd3ced0..3da9506c6c 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -740,7 +739,6 @@ convert_hierarchy(EggGroupNode *egg_root) { return false; } } - return true; } @@ -1652,6 +1650,16 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, } } + MStringArray uvset_names; + status = mesh.getUVSetNames(uvset_names); + if (!status) { + status.perror("MFnMesh getUVSetNames not found"); + //return; + } + for (size_t ui=0; uiadd_child(egg_poly); @@ -1675,10 +1683,10 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, // And apply the shader properties to the polygon. if (shader != (MayaShader *)NULL) { - set_shader_attributes(*egg_poly, *shader); + set_shader_attributes(*egg_poly, *shader, &pi); } - const MayaShaderColorDef &color_def = shader->_color; + const MayaShaderColorDef *color_def = shader->get_color_def(); // Should we extract the color from the vertices? Normally, in // Maya a texture completely replaces the vertex color, so we @@ -1694,7 +1702,7 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, // that the "vertex-color" flag is always set. bool ignore_vertex_color = false; if (shader != (MayaShader *)NULL) { - ignore_vertex_color = color_def._has_texture && !(egg_vertex_color || _always_show_vertex_color); + ignore_vertex_color = color_def->_has_texture && !(egg_vertex_color || _always_show_vertex_color); } Colorf poly_color(1.0f, 1.0f, 1.0f, 1.0f); @@ -1711,7 +1719,7 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, long i; LPoint3d centroid(0.0, 0.0, 0.0); - if (shader != (MayaShader *)NULL && color_def.has_projection()) { + if (shader != (MayaShader *)NULL && color_def->has_projection()) { // If the shader has a projection, we may need to compute the // polygon's centroid to avoid seams at the edges. for (i = 0; i < num_verts; i++) { @@ -1722,7 +1730,6 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, } centroid /= (double)num_verts; } - for (i = 0; i < num_verts; i++) { EggVertex vert; @@ -1741,19 +1748,41 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, vert.set_normal(n3d); } - if (shader != (MayaShader *)NULL && color_def.has_projection()) { - // If the shader has a projection, use it instead of the - // polygon's built-in UV's. - vert.set_uv(color_def.project_uv(p3d, centroid)); + string uv_name(""); + if (shader != (MayaShader *)NULL && color_def->_has_texture) { + // Go thru all the texture references for this primitive and set uvs + mayaegg_cat.debug() << "shader->_color.size is " << shader->_color.size() << endl; + mayaegg_cat.debug() << "primitive->tref.size is " << egg_poly->get_num_textures() << endl; + for (int ti=0; ti< egg_poly->get_num_textures(); ++ti) { + // get the eggTexture pointer + EggTexture *tex_p = egg_poly->get_texture(ti); + mayaegg_cat.debug() << "tex->uvset_name :" << tex_p->get_uv_name() << endl; - } else if (pi.hasUVs()) { - // Get the UV's from the polygon. - float2 uvs; - status = pi.getUV(i, uvs); - if (!status) { - status.perror("MItMeshPolygon::getUV"); - } else { - vert.set_uv(TexCoordd(uvs[0], uvs[1])); + // get the shader color def that matches this EggTexture + for (size_t tj=0; tj< shader->_color.size(); ++tj) { + color_def = shader->get_color_def(tj); + if (color_def->_texture_name == tex_p->get_uv_name()) { + mayaegg_cat.debug() << "matched colordef idx: " << tj << endl; + break; + } + } + mayaegg_cat.debug() << "color_def->uvset_name :" << color_def->_uvset_name << endl; + uv_name = color_def->_uvset_name; // this is the name to look up by in maya + + if (color_def->has_projection()) { + // If the shader has a projection, use it instead of the + // polygon's built-in UV's. + vert.set_uv(tex_p->get_uv_name(),color_def->project_uv(p3d, centroid)); + } else { + // Get the UV's from the polygon. + float2 uvs; + status = pi.getUV(i, uvs, &MString(uv_name.c_str())); + if (!status) { + status.perror("MItMeshPolygon::getUV"); + } else { + vert.set_uv(tex_p->get_uv_name(),TexCoordd(uvs[0], uvs[1])); + } + } } } @@ -1808,7 +1837,9 @@ make_polyset(MayaNodeDesc *node_desc, const MDagPath &dag_path, } pi.next(); + } + mayaegg_cat.spam() << "done traversing polys" << endl; // Now that we've added all the polygons (and created all the // vertices), go back through the vertex pool and set up the @@ -2166,99 +2197,134 @@ get_vertex_weights(const MDagPath &dag_path, const MFnNurbsSurface &surface, // egg primitive. //////////////////////////////////////////////////////////////////// void MayaToEggConverter:: -set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader) { +set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader, const MItMeshPolygon *pi) { // In Maya, a polygon is either textured or colored. The texture, - // if present, replaces the color. - const MayaShaderColorDef &color_def = shader._color; + // if present, replaces the color. Also now there could be multiple textures + MayaShaderColorDef *color_def; const MayaShaderColorDef &trans_def = shader._transparency; - if (color_def._has_texture || trans_def._has_texture) { - EggTexture tex(shader.get_name(), ""); - - if (color_def._has_texture) { - // If we have a texture on color, apply it as the filename. - Filename filename = Filename::from_os_specific(color_def._texture); - Filename fullpath = - _path_replace->match_path(filename, get_texture_path()); - tex.set_filename(_path_replace->store_path(fullpath)); - tex.set_fullpath(fullpath); - apply_texture_properties(tex, color_def); - - // If we also have a texture on transparency, apply it as the - // alpha filename. - if (trans_def._has_texture) { - if (color_def._wrap_u != trans_def._wrap_u || - color_def._wrap_u != trans_def._wrap_u) { - mayaegg_cat.warning() - << "Shader " << shader.get_name() - << " has contradictory wrap modes on color and texture.\n"; - } + for (size_t i=0; i_has_texture || trans_def._has_texture) { + EggTexture tex(shader.get_name(), ""); + string uvset_name = color_def->_texture_name; + + //maya_cat.debug() << "got shader name:" << shader.get_name() << endl; + maya_cat.debug() << "ssa:texture name[" << i << "]: " << color_def->_texture_name << endl; + + if (color_def->_has_texture) { + // If we have a texture on color, apply it as the filename. + //mayaegg_cat.debug() << "ssa:got texture name" << color_def->_texture_filename << endl; + Filename filename = Filename::from_os_specific(color_def->_texture_filename); + Filename fullpath = + _path_replace->match_path(filename, get_texture_path()); + tex.set_filename(_path_replace->store_path(fullpath)); + tex.set_fullpath(fullpath); + apply_texture_properties(tex, *color_def); + + // If we also have a texture on transparency, apply it as the + // alpha filename. + if (trans_def._has_texture) { + if (color_def->_wrap_u != trans_def._wrap_u || + color_def->_wrap_u != trans_def._wrap_u) { + mayaegg_cat.warning() + << "Shader " << shader.get_name() + << " has contradictory wrap modes on color and texture.\n"; + } - if (!compare_texture_properties(tex, trans_def)) { - // Only report each broken shader once. - static pset bad_shaders; - if (bad_shaders.insert(shader.get_name()).second) { - mayaegg_cat.error() - << "Color and transparency texture properties differ on shader " - << shader.get_name() << "\n"; + if (!compare_texture_properties(tex, trans_def)) { + // Only report each broken shader once. + static pset bad_shaders; + if (bad_shaders.insert(shader.get_name()).second) { + mayaegg_cat.error() + << "Color and transparency texture properties differ on shader " + << shader.get_name() << "\n"; + } + } + //tex.set_format(EggTexture::F_rgba); + + // We should try to be smarter about whether the transparency + // value is connected to the texture's alpha channel or to its + // grayscale channel. However, I'm not sure how to detect + // this at the moment; rather than spending days trying to + // figure out, for now I'll just assume that if the same + // texture image is used for both color and transparency, then + // the artist meant to use the alpha channel for transparency. + if (trans_def._texture_filename == color_def->_texture_filename) { + // That means that we don't need to do anything special: use + // all the channels of the texture. + + } else { + // Otherwise, pull the alpha channel from the other image + // file. Ideally, we should figure out which channel from + // the other image supplies alpha (and specify this via + // set_alpha_file_channel()), but for now we assume it comes + // from the grayscale data. + filename = Filename::from_os_specific(trans_def._texture_filename); + fullpath = _path_replace->match_path(filename, get_texture_path()); + tex.set_alpha_filename(_path_replace->store_path(fullpath)); + tex.set_alpha_fullpath(fullpath); + } + } else { + // If there is no transparency texture specified, we don't + // have any transparency, so tell the egg format to ignore any + // alpha channel that might be on the color texture. + //tex.set_format(EggTexture::F_rgb); + } + + // if multi-textured, first texture in maya is on top, so + // default it to decal + if ((shader._color.size() > 1) && (i!=shader._color.size()-1)) + tex.set_env_type(EggTexture::ET_decal); + + } else { // trans_def._has_texture + // We have a texture on transparency only. Apply it as the + // primary filename, and set the format accordingly. + Filename filename = Filename::from_os_specific(trans_def._texture_filename); + Filename fullpath = + _path_replace->match_path(filename, get_texture_path()); + tex.set_filename(_path_replace->store_path(fullpath)); + tex.set_fullpath(fullpath); + //tex.set_format(EggTexture::F_alpha); + apply_texture_properties(tex, trans_def); + } + + //mayaegg_cat.debug() << "ssa:tref_name:" << tex.get_name() << endl; + EggTexture *new_tex = + _textures.create_unique_texture(tex, ~0); + //_textures.create_unique_texture(tex, ~EggTexture::E_tref_name); + + if (pi && shader._color.size() > 1) { + // see if the uvset_name exists for this polygon, if yes, add the texture to primitive + if (pi->hasUVs(MString(uvset_name.c_str()))) { + primitive.add_texture(new_tex); + color_def->_uvset_name.assign(uvset_name.c_str()); + new_tex->set_uv_name(color_def->_texture_name); + } else { + // if the uvset is under different name, try taking out the + // numeric from the uv name. This was a compromise to support + // one uvset but different layered texture for layer1 texture + uvset_name.resize(uvset_name.length()-1); + mayaegg_cat.debug() << "ssa:trying uvset_name: " << uvset_name << endl; + if (pi->hasUVs(MString(uvset_name.c_str()))) { + primitive.add_texture(new_tex); + color_def->_uvset_name.assign(uvset_name.c_str()); + new_tex->set_uv_name(color_def->_texture_name); + } else { + mayaegg_cat.debug() << "ssa: didn't find uvset_name: " << uvset_name << endl; } } - tex.set_format(EggTexture::F_rgba); - - // We should try to be smarter about whether the transparency - // value is connected to the texture's alpha channel or to its - // grayscale channel. However, I'm not sure how to detect - // this at the moment; rather than spending days trying to - // figure out, for now I'll just assume that if the same - // texture image is used for both color and transparency, then - // the artist meant to use the alpha channel for transparency. - if (trans_def._texture == color_def._texture) { - // That means that we don't need to do anything special: use - // all the channels of the texture. - - } else { - // Otherwise, pull the alpha channel from the other image - // file. Ideally, we should figure out which channel from - // the other image supplies alpha (and specify this via - // set_alpha_file_channel()), but for now we assume it comes - // from the grayscale data. - filename = Filename::from_os_specific(trans_def._texture); - fullpath = _path_replace->match_path(filename, get_texture_path()); - tex.set_alpha_filename(_path_replace->store_path(fullpath)); - tex.set_alpha_fullpath(fullpath); - } - } else { - // If there is no transparency texture specified, we don't - // have any transparency, so tell the egg format to ignore any - // alpha channel that might be on the color texture. - tex.set_format(EggTexture::F_rgb); + primitive.add_texture(new_tex); + new_tex->set_uv_name(color_def->_uvset_name); } - - } else { // trans_def._has_texture - // We have a texture on transparency only. Apply it as the - // primary filename, and set the format accordingly. - Filename filename = Filename::from_os_specific(trans_def._texture); - Filename fullpath = - _path_replace->match_path(filename, get_texture_path()); - tex.set_filename(_path_replace->store_path(fullpath)); - tex.set_fullpath(fullpath); - tex.set_format(EggTexture::F_alpha); - apply_texture_properties(tex, trans_def); } - - EggTexture *new_tex = - _textures.create_unique_texture(tex, ~EggTexture::E_tref_name); - - primitive.set_texture(new_tex); - } - // Also apply an overall color to the primitive. Colorf rgba = shader.get_rgba(); // The existence of a texture on either color channel completely // replaces the corresponding flat color. - if (color_def._has_texture) { + if (color_def->_has_texture) { rgba[0] = 1.0f; rgba[1] = 1.0f; rgba[2] = 1.0f; @@ -2268,10 +2334,10 @@ set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader) { } // But the color gain always gets applied. - rgba[0] *= color_def._color_gain[0]; - rgba[1] *= color_def._color_gain[1]; - rgba[2] *= color_def._color_gain[2]; - rgba[3] *= color_def._color_gain[3]; + rgba[0] *= color_def->_color_gain[0]; + rgba[1] *= color_def->_color_gain[1]; + rgba[2] *= color_def->_color_gain[2]; + rgba[3] *= color_def->_color_gain[3]; primitive.set_color(rgba); } diff --git a/pandatool/src/mayaegg/mayaToEggConverter.h b/pandatool/src/mayaegg/mayaToEggConverter.h index 7e84cabe7f..9dcdff9f68 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.h +++ b/pandatool/src/mayaegg/mayaToEggConverter.h @@ -33,6 +33,7 @@ #include "pre_maya_include.h" #include +#include #include "post_maya_include.h" class EggData; @@ -133,8 +134,10 @@ private: pvector &joints, MFloatArray &weights); bool get_vertex_weights(const MDagPath &dag_path, const MFnNurbsSurface &surface, pvector &joints, MFloatArray &weights); + // void set_shader_attributes(EggPrimitive &primitive, + // const MayaShader &shader); void set_shader_attributes(EggPrimitive &primitive, - const MayaShader &shader); + const MayaShader &shader, const MItMeshPolygon *pi=NULL); void apply_texture_properties(EggTexture &tex, const MayaShaderColorDef &color_def); bool compare_texture_properties(EggTexture &tex, diff --git a/pandatool/src/mayaprogs/mayaCopy.cxx b/pandatool/src/mayaprogs/mayaCopy.cxx index 7b54013240..3c1a65f069 100644 --- a/pandatool/src/mayaprogs/mayaCopy.cxx +++ b/pandatool/src/mayaprogs/mayaCopy.cxx @@ -167,8 +167,10 @@ copy_maya_file(const Filename &source, const Filename &dest, int num_shaders = _shaders.get_num_shaders(); for (int i = 0; i < num_shaders; i++) { MayaShader *shader = _shaders.get_shader(i); - if (!extract_texture(shader->_color, dir)) { - return false; + for (size_t j = 0; j < shader->_color.size(); j++) { + if (!extract_texture(*shader->get_color_def(j), dir)) { + return false; + } } if (!extract_texture(shader->_transparency, dir)) { return false; @@ -227,7 +229,7 @@ bool MayaCopy:: extract_texture(MayaShaderColorDef &color_def, CVSSourceDirectory *dir) { if (color_def._has_texture) { Filename texture_filename = - _path_replace->convert_path(color_def._texture); + _path_replace->convert_path(color_def._texture_filename); if (!texture_filename.exists()) { nout << "*** Warning: texture " << texture_filename << " does not exist.\n";