Panda3D
|
00001 // Filename: mayaShaderColorDef.cxx 00002 // Created by: drose (12Apr03) 00003 // Modified 19Mar10 by ETC PandaSE team (see 00004 // header comment for mayaToEgg.cxx for details) 00005 // 00006 //////////////////////////////////////////////////////////////////// 00007 // 00008 // PANDA 3D SOFTWARE 00009 // Copyright (c) Carnegie Mellon University. All rights reserved. 00010 // 00011 // All use of this software is subject to the terms of the revised BSD 00012 // license. You should have received a copy of this license along 00013 // with this source code in a file named "LICENSE." 00014 // 00015 //////////////////////////////////////////////////////////////////// 00016 00017 #include "mayaShaderColorDef.h" 00018 #include "mayaShader.h" 00019 #include "maya_funcs.h" 00020 #include "config_maya.h" 00021 #include "string_utils.h" 00022 #include "pset.h" 00023 00024 #include "pre_maya_include.h" 00025 #include <maya/MFnDependencyNode.h> 00026 #include <maya/MPlug.h> 00027 #include <maya/MPlugArray.h> 00028 #include <maya/MObject.h> 00029 #include <maya/MStatus.h> 00030 #include <maya/MFnEnumAttribute.h> 00031 #include "post_maya_include.h" 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function: MayaShaderColorDef::Constructor 00035 // Access: Public 00036 // Description: 00037 //////////////////////////////////////////////////////////////////// 00038 MayaShaderColorDef:: 00039 MayaShaderColorDef() { 00040 00041 _blend_type = BT_unspecified; 00042 00043 _projection_type = PT_off; 00044 _projection_matrix = LMatrix4d::ident_mat(); 00045 _u_angle = 0.0; 00046 _v_angle = 0.0; 00047 00048 _texture_filename = ""; 00049 _texture_name = ""; 00050 _color_gain.set(1.0f, 1.0f, 1.0f, 1.0f); 00051 00052 _coverage.set(1.0, 1.0); 00053 _translate_frame.set(0.0, 0.0); 00054 _rotate_frame = 0.0; 00055 00056 _mirror = false; 00057 _stagger = false; 00058 _wrap_u = true; 00059 _wrap_v = true; 00060 00061 _repeat_uv.set(1.0, 1.0); 00062 _offset.set(0.0, 0.0); 00063 _rotate_uv = 0.0; 00064 00065 _is_alpha = false; 00066 00067 _opposite = 0; 00068 00069 _color_object = (MObject *)NULL; 00070 00071 _has_texture = false; 00072 _has_flat_color = false; 00073 _flat_color.set(0.0, 0.0, 0.0, 0.0); 00074 _has_alpha_channel = false; 00075 _keep_color = false; // classic mode overwrites color: new mode retains color with a 3rd layer 00076 _keep_alpha = false; 00077 _interpolate = false; 00078 _uvset_name = "map1"; 00079 00080 _map_uvs = NULL; 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: MayaShaderColorDef::Constructor 00085 // Access: Public 00086 // Description: 00087 //////////////////////////////////////////////////////////////////// 00088 MayaShaderColorDef:: 00089 MayaShaderColorDef(MayaShaderColorDef ©) { 00090 _has_texture = copy._has_texture; 00091 _texture_filename = copy._texture_filename; 00092 _texture_name = copy._texture_name; 00093 _uvset_name = copy._uvset_name; 00094 _color_gain = copy._color_gain; 00095 00096 _has_flat_color = copy._has_flat_color; 00097 _flat_color = copy._flat_color; 00098 00099 _projection_type = copy._projection_type; 00100 _projection_matrix = copy._projection_matrix; 00101 _u_angle = copy._u_angle; 00102 _v_angle = copy._v_angle; 00103 00104 _coverage = copy._coverage; 00105 _translate_frame = copy._translate_frame; 00106 _rotate_frame = copy._rotate_frame; 00107 00108 _mirror = copy._mirror; 00109 _stagger = copy._stagger; 00110 _wrap_u = copy._wrap_u; 00111 _wrap_v = copy._wrap_v; 00112 00113 _blend_type = copy._blend_type; 00114 _has_alpha_channel = copy._has_alpha_channel; 00115 _keep_color = copy._keep_color; 00116 _keep_alpha = copy._keep_alpha; 00117 _interpolate = copy._interpolate; 00118 00119 _repeat_uv = copy._repeat_uv; 00120 _offset = copy._offset; 00121 _rotate_uv = copy._rotate_uv; 00122 00123 _is_alpha = copy._is_alpha; 00124 00125 _map_uvs = copy._map_uvs; 00126 _color_object = copy._color_object; 00127 00128 _opposite = 0; 00129 } 00130 00131 //////////////////////////////////////////////////////////////////// 00132 // Function: MayaShaderColorDef::Destructor 00133 // Access: Public 00134 // Description: 00135 //////////////////////////////////////////////////////////////////// 00136 MayaShaderColorDef:: 00137 ~MayaShaderColorDef() { 00138 if (_color_object != (MObject *)NULL) { 00139 delete _color_object; 00140 } 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: MayaShaderColorDef::compute_texture_matrix 00145 // Access: Public 00146 // Description: Returns a texture matrix corresponding to the texture 00147 // transforms indicated by the shader. 00148 //////////////////////////////////////////////////////////////////// 00149 LMatrix3d MayaShaderColorDef:: 00150 compute_texture_matrix() const { 00151 LVector2d scale(_repeat_uv[0] / _coverage[0], 00152 _repeat_uv[1] / _coverage[1]); 00153 LVector2d trans(_offset[0] - _translate_frame[0] / _coverage[0], 00154 _offset[1] - _translate_frame[1] / _coverage[1]); 00155 00156 return 00157 (LMatrix3d::translate_mat(LVector2d(-0.5, -0.5)) * 00158 LMatrix3d::rotate_mat(_rotate_frame) * 00159 LMatrix3d::translate_mat(LVector2d(0.5, 0.5))) * 00160 LMatrix3d::scale_mat(scale) * 00161 LMatrix3d::translate_mat(trans); 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: MayaShaderColorDef::has_projection 00166 // Access: Public 00167 // Description: Returns true if the shader has a projection in effect. 00168 //////////////////////////////////////////////////////////////////// 00169 bool MayaShaderColorDef:: 00170 has_projection() const { 00171 return (_projection_type != PT_off); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: MayaShaderColorDef::project_uv 00176 // Access: Public 00177 // Description: If the shader has a projection (has_projection() 00178 // returns true), this computes the appropriate UV 00179 // corresponding to the indicated 3-d point. Seams that 00180 // might be introduced on polygons that cross quadrants 00181 // are closed up by ensuring the point is in the same 00182 // quadrant as the indicated reference point. 00183 //////////////////////////////////////////////////////////////////// 00184 TexCoordd MayaShaderColorDef:: 00185 project_uv(const LPoint3d &pos, const LPoint3d ¢roid) const { 00186 nassertr(_map_uvs != NULL, TexCoordd::zero()); 00187 return (this->*_map_uvs)(pos * _projection_matrix, centroid * _projection_matrix); 00188 } 00189 00190 //////////////////////////////////////////////////////////////////// 00191 // Function: MayaShaderColorDef::write 00192 // Access: Public 00193 // Description: 00194 //////////////////////////////////////////////////////////////////// 00195 void MayaShaderColorDef:: 00196 write(ostream &out) const { 00197 if (_has_texture) { 00198 out << " texture filename is " << _texture_filename << "\n" 00199 << " texture name is " << _texture_name << "\n" 00200 << " uv_set name is " << _uvset_name << "\n" 00201 << " coverage is " << _coverage << "\n" 00202 << " translate_frame is " << _translate_frame << "\n" 00203 << " rotate_frame is " << _rotate_frame << "\n" 00204 << " mirror is " << _mirror << "\n" 00205 << " stagger is " << _stagger << "\n" 00206 << " wrap_u is " << _wrap_u << "\n" 00207 << " wrap_v is " << _wrap_v << "\n" 00208 << " repeat_uv is " << _repeat_uv << "\n" 00209 << " offset is " << _offset << "\n" 00210 << " rotate_uv is " << _rotate_uv << "\n" 00211 << " color_gain is " << _color_gain << "\n"; 00212 00213 } else if (_has_flat_color) { 00214 out << " flat color is " << _flat_color << "\n"; 00215 } 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: MayaShaderColorDef::reset_maya_texture 00220 // Access: Public 00221 // Description: Changes the texture filename stored in the Maya file 00222 // for this particular shader. 00223 //////////////////////////////////////////////////////////////////// 00224 bool MayaShaderColorDef:: 00225 reset_maya_texture(const Filename &texture) { 00226 if (_color_object != (MObject *)NULL) { 00227 _has_texture = set_string_attribute(*_color_object, "fileTextureName", 00228 texture.to_os_generic()); 00229 _texture_filename = texture; 00230 00231 if (!_has_texture) { 00232 maya_cat.error() 00233 << "Unable to reset texture filename.\n"; 00234 } 00235 00236 return _has_texture; 00237 } 00238 00239 maya_cat.error() 00240 << "Attempt to reset texture on Maya object that has no color set.\n"; 00241 return false; 00242 } 00243 00244 00245 //////////////////////////////////////////////////////////////////// 00246 // Function: MayaShaderColorDef::get_panda_uvset_name 00247 // Access: Private 00248 // Description: Maya's default uvset name is "map1". Panda's default 00249 // uvset name is "default". Otherwise, leaves uvset 00250 // name untranslated. 00251 //////////////////////////////////////////////////////////////////// 00252 string MayaShaderColorDef:: 00253 get_panda_uvset_name() { 00254 if (_uvset_name == "map1") { 00255 return "default"; 00256 } 00257 return _uvset_name; 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: MayaShaderColorDef::find_textures_legacy 00262 // Access: Private 00263 // Description: This is part of the deprecated codepath. 00264 // Determines the surface color specified by the shader. 00265 // This includes texturing and other advanced shader 00266 // properties. 00267 //////////////////////////////////////////////////////////////////// 00268 void MayaShaderColorDef:: 00269 find_textures_legacy(MayaShader *shader, MObject color, bool _texture_copy, Filename _texture_out_dir, bool trans) { 00270 RGBColorf color_gain; 00271 if (get_vec3f_attribute(color, "colorGain", color_gain)) { 00272 color_gain[0] = color_gain[0] > 1.0 ? 1.0 : color_gain[0]; 00273 color_gain[0] = color_gain[0] < 0.0 ? 0.0 : color_gain[0]; 00274 _color_gain[0] *= color_gain[0]; 00275 color_gain[1] = color_gain[1] > 1.0 ? 1.0 : color_gain[1]; 00276 color_gain[1] = color_gain[1] < 0.0 ? 0.0 : color_gain[1]; 00277 _color_gain[1] *= color_gain[1]; 00278 color_gain[2] = color_gain[2] > 1.0 ? 1.0 : color_gain[2]; 00279 color_gain[2] = color_gain[2] < 0.0 ? 0.0 : color_gain[2]; 00280 _color_gain[2] *= color_gain[2]; 00281 } 00282 float alpha_gain; 00283 if (get_maya_attribute(color, "alphaGain", alpha_gain)) { 00284 alpha_gain = alpha_gain > 1.0 ? 1.0 : alpha_gain; 00285 alpha_gain = alpha_gain < 0.0 ? 0.0 : alpha_gain; 00286 _color_gain[3] *= alpha_gain; 00287 } 00288 if (color.hasFn(MFn::kFileTexture)) { 00289 MFnDependencyNode dfn(color); 00290 _color_object = new MObject(color); 00291 _texture_name = dfn.name().asChar(); 00292 string filename; 00293 _has_texture = get_string_attribute(color, "fileTextureName", filename); 00294 _has_texture = _has_texture && !filename.empty(); 00295 if (_has_texture) { 00296 _texture_filename = Filename::from_os_specific(filename); 00297 if (_texture_filename.is_directory()) { 00298 maya_cat.warning() 00299 << "Shader " << shader->get_name() 00300 << " references texture filename " << filename 00301 << " which is a directory; clearing.\n"; 00302 _has_texture = false; 00303 set_string_attribute(color, "fileTextureName", ""); 00304 } 00305 // create directory, copy texture, modify texture filename 00306 if (_texture_copy) { 00307 if (_texture_out_dir[_texture_out_dir.length()-1] != '/') 00308 _texture_out_dir+="/"; 00309 _texture_out_dir.make_dir(); 00310 Filename texture_copy_filename=Filename(_texture_out_dir, _texture_filename.get_basename()); 00311 if (_texture_filename.copy_to(texture_copy_filename)) { 00312 _texture_filename=texture_copy_filename; 00313 } 00314 else { 00315 maya_cat.warning() 00316 <<"unable to copy texture files from "<<_texture_filename.get_dirname() 00317 <<" to "<<_texture_out_dir<<"\n" 00318 <<"make sure you have the access right to the assigned directory\n" 00319 <<"the output egg file will adapt to the original texture files' path\n"; 00320 } 00321 } 00322 } 00323 00324 get_vec2f_attribute(color, "coverage", _coverage); 00325 get_vec2f_attribute(color, "translateFrame", _translate_frame); 00326 get_angle_attribute(color, "rotateFrame", _rotate_frame); 00327 00328 //get_bool_attribute(color, "alphaIsLuminance", _alpha_is_luminance); 00329 00330 get_bool_attribute(color, "mirror", _mirror); 00331 get_bool_attribute(color, "stagger", _stagger); 00332 get_bool_attribute(color, "wrapU", _wrap_u); 00333 get_bool_attribute(color, "wrapV", _wrap_v); 00334 00335 get_vec2f_attribute(color, "repeatUV", _repeat_uv); 00336 get_vec2f_attribute(color, "offset", _offset); 00337 get_angle_attribute(color, "rotateUV", _rotate_uv); 00338 00339 if (!trans) { 00340 if (maya_cat.is_debug()) { 00341 maya_cat.debug() << "pushed a file texture" << endl; 00342 } 00343 shader->_color.push_back(this); 00344 } 00345 00346 } else if (color.hasFn(MFn::kProjection)) { 00347 if (maya_cat.is_debug()) { 00348 maya_cat.debug() << "reading a projection texture" << endl; 00349 } 00350 // This is a projected texture. We will have to step one level 00351 // deeper to find the actual texture. 00352 MFnDependencyNode projection_fn(color); 00353 MPlug image_plug = projection_fn.findPlug("image"); 00354 if (!image_plug.isNull()) { 00355 MPlugArray image_pa; 00356 image_plug.connectedTo(image_pa, true, false); 00357 00358 for (size_t i = 0; i < image_pa.length(); i++) { 00359 find_textures_legacy(shader, image_pa[0].node(), _texture_copy, _texture_out_dir); 00360 } 00361 } 00362 00363 if (!get_mat4d_attribute(color, "placementMatrix", _projection_matrix)) { 00364 _projection_matrix = LMatrix4d::ident_mat(); 00365 } 00366 00367 // The uAngle and vAngle might be used for certain kinds of 00368 // projections. 00369 if (!get_angle_attribute(color, "uAngle", _u_angle)) { 00370 _u_angle = 360.0; 00371 } 00372 if (!get_angle_attribute(color, "vAngle", _v_angle)) { 00373 _v_angle = 180.0; 00374 } 00375 00376 string type; 00377 if (get_enum_attribute(color, "projType", type)) { 00378 set_projection_type(type); 00379 } 00380 00381 } else if (color.hasFn(MFn::kLayeredTexture)) { 00382 if (maya_cat.is_debug()) { 00383 maya_cat.debug() << "Found layered texture" << endl; 00384 } 00385 00386 int blendValue; 00387 MStatus status; 00388 MPlugArray color_pa; 00389 MFnDependencyNode layered_fn(color); 00390 layered_fn.getConnections(color_pa); 00391 MPlug inputsPlug = layered_fn.findPlug("inputs", &status); 00392 MPlug blendModePlug = layered_fn.findPlug("blendMode", &status); 00393 00394 if (maya_cat.is_debug()) { 00395 maya_cat.debug() << "number of connections: " << color_pa.length() << endl; 00396 } 00397 bool first = true; 00398 BlendType bt = BT_modulate; 00399 for (size_t i=0; i<color_pa.length(); ++i) { 00400 MPlug pl = color_pa[i]; 00401 MPlugArray pla; 00402 pl.connectedTo(pla, true, false); 00403 00404 // First figure out the blend mode intended for this shadercolordef 00405 int li = pl.logicalIndex(); 00406 if (li > -1) { 00407 // found a blend mode 00408 if (maya_cat.is_spam()) { 00409 maya_cat.spam() << "*** Start doIt... ***" << endl; 00410 maya_cat.spam() << "inputsPlug Name: " << inputsPlug.name() << endl; 00411 } 00412 status = blendModePlug.selectAncestorLogicalIndex(li,inputsPlug); 00413 blendModePlug.getValue(blendValue); 00414 00415 if (maya_cat.is_spam()) { 00416 maya_cat.spam() 00417 << blendModePlug.name() << ": has value " << blendValue << endl; 00418 } 00419 00420 MFnEnumAttribute blendModeEnum(blendModePlug); 00421 MString blendName = blendModeEnum.fieldName(blendValue, &status); 00422 00423 switch (blendValue) { 00424 case 1: 00425 bt = BT_decal; 00426 get_bool_attribute(color, "interpolate", _interpolate); 00427 maya_cat.info() << "interpolate: " << _interpolate << endl; 00428 _keep_color = true; 00429 break; 00430 case 6: 00431 bt = BT_modulate; 00432 get_bool_attribute(color, "keepAlpha", _keep_alpha); 00433 maya_cat.info() << "keepAlpha: " << _keep_alpha << endl; 00434 break; 00435 case 4: 00436 bt = BT_add; 00437 break; 00438 } 00439 maya_cat.info() << layered_fn.name() << ": blendMode used " << blendName << endl; 00440 if (maya_cat.is_spam()) { 00441 maya_cat.spam() << "*** END doIt... ***" << endl; 00442 } 00443 00444 // advance to the next plug, because that is where the shader info are 00445 pl = color_pa[++i]; 00446 pl.connectedTo(pla, true, false); 00447 } 00448 for (size_t j=0; j<pla.length(); ++j) { 00449 //maya_cat.debug() << pl.name() << " is(pl) " << pl.node().apiTypeStr() << endl; 00450 //maya_cat.debug() << pla[j].name() << " is(pla) " << pla[j].node().apiTypeStr() << endl; 00451 string pla_name = pla[j].name().asChar(); 00452 // sometimes, by default, maya gives a outAlpha on subsequent plugs, ignore that 00453 if (pla_name.find("outAlpha") != string::npos) { 00454 // top texture has an alpha channel, so make sure that this alpha is retained by egg file 00455 if (maya_cat.is_debug()) { 00456 maya_cat.debug() << pl.name().asChar() << ":has alpha channel" << pla_name << endl; 00457 } 00458 _has_alpha_channel = true; 00459 continue; 00460 } 00461 if (!first) { 00462 if (maya_cat.is_debug()) { 00463 maya_cat.debug() << pl.name().asChar() << " next:connectedTo: " << pla_name << endl; 00464 } 00465 MayaShaderColorDef *color_p = new MayaShaderColorDef; 00466 color_p->find_textures_legacy(shader, pla[j].node(), _texture_copy, _texture_out_dir); 00467 color_p->_blend_type = bt; 00468 size_t loc = color_p->_texture_name.find('.',0); 00469 if (loc != string::npos) { 00470 color_p->_texture_name.resize(loc); 00471 } 00472 if (maya_cat.is_debug()) { 00473 maya_cat.debug() << "uv_name : " << color_p->_texture_name << endl; 00474 } 00475 } 00476 else { 00477 if (maya_cat.is_debug()) { 00478 maya_cat.debug() << pl.name().asChar() << " first:connectedTo: " << pla_name << endl; 00479 } 00480 find_textures_legacy(shader, pla[j].node(), _texture_copy, _texture_out_dir); 00481 _texture_name.assign(pla[j].name().asChar()); 00482 _blend_type = bt; 00483 size_t loc = _texture_name.find('.',0); 00484 if (loc != string::npos) { 00485 _texture_name.resize(loc); 00486 } 00487 if (maya_cat.is_debug()) { 00488 maya_cat.debug() << "uv_name : " << _texture_name << endl; 00489 } 00490 first = false; 00491 } 00492 } 00493 } 00494 } else { 00495 // This shader wasn't understood. 00496 if (maya_cat.is_debug()) { 00497 maya_cat.info() 00498 << "**Don't know how to interpret color attribute type " 00499 << color.apiTypeStr() << "\n"; 00500 00501 } else { 00502 // If we don't have a heavy verbose count, only report each type 00503 // of unsupported shader once. 00504 static pset<MFn::Type> bad_types; 00505 if (bad_types.insert(color.apiType()).second) { 00506 maya_cat.info() 00507 << "**Don't know how to interpret color attribute type " 00508 << color.apiTypeStr() << "\n"; 00509 } 00510 } 00511 } 00512 } 00513 00514 //////////////////////////////////////////////////////////////////// 00515 // Function: MayaShaderColorDef::find_textures 00516 // Access: Private 00517 // Description: Search to find any file textures that lead into the 00518 // given input plug. Any textures found will be added 00519 // to the provided MayaShaderColorList. 00520 //////////////////////////////////////////////////////////////////// 00521 void MayaShaderColorDef:: 00522 find_textures_modern(const string &shadername, MayaShaderColorList &list, MPlug inplug,bool _texture_copy, Filename _texture_out_dir, bool is_alpha) { 00523 00524 MPlugArray outplugs; 00525 inplug.connectedTo(outplugs, true, false); 00526 if (outplugs.length() == 0) { 00527 return; 00528 } 00529 if (outplugs.length() > 1) { 00530 // Only one output plug should be connected to a given input plug. 00531 maya_cat.warning() 00532 << "Shader " << shadername << " has weird plug connections.\n"; 00533 return; 00534 } 00535 MPlug outplug = outplugs[0]; 00536 MObject source = outplug.node(); 00537 MFnDependencyNode sourceFn(source); 00538 00539 if (source.hasFn(MFn::kFileTexture)) { 00540 00541 string filename; 00542 bool hasfn = get_string_attribute(source, "fileTextureName", filename); 00543 if ((!hasfn) || (filename.empty())) { 00544 maya_cat.warning() 00545 << "Shader " << shadername << " references file texture " 00546 << "with no file name, ignoring invalid file texture.\n"; 00547 return; 00548 } 00549 Filename fn = filename; 00550 if (fn.is_directory()) { 00551 maya_cat.warning() 00552 << "Shader " << shadername << " references file name " 00553 << filename << " which is a directory, ignoring it.\n"; 00554 return; 00555 } 00556 00557 MayaShaderColorDef *def = new MayaShaderColorDef; 00558 00559 def->_color_object = new MObject(source); 00560 def->_texture_filename = Filename::from_os_specific(filename); 00561 // create directory, copy texture, modify texture filename 00562 if (_texture_copy) { 00563 if (_texture_out_dir[_texture_out_dir.length()-1] != '/') { 00564 _texture_out_dir+="/"; 00565 } 00566 _texture_out_dir.make_dir(); 00567 Filename texture_copy_filename=Filename(_texture_out_dir, def->_texture_filename.get_basename()); 00568 if (def->_texture_filename.copy_to(texture_copy_filename)) { 00569 def->_texture_filename=texture_copy_filename; 00570 } 00571 else { 00572 maya_cat.warning() 00573 <<"unable to copy texture files from "<<def->_texture_filename.get_dirname() 00574 <<" to "<<_texture_out_dir<<"\n" 00575 <<"make sure you have the access right to the assigned directory\n" 00576 <<"the output egg file will adapt to the original texture files' path\n"; 00577 } 00578 } 00579 def->_texture_name = sourceFn.name().asChar(); 00580 00581 get_vec2f_attribute(source, "coverage", def->_coverage); 00582 get_vec2f_attribute(source, "translateFrame", def->_translate_frame); 00583 get_angle_attribute(source, "rotateFrame", def->_rotate_frame); 00584 00585 get_bool_attribute(source, "mirror", def->_mirror); 00586 get_bool_attribute(source, "stagger", def->_stagger); 00587 get_bool_attribute(source, "wrapU", def->_wrap_u); 00588 get_bool_attribute(source, "wrapV", def->_wrap_v); 00589 00590 get_vec2f_attribute(source, "repeatUV", def->_repeat_uv); 00591 get_vec2f_attribute(source, "offset", def->_offset); 00592 get_angle_attribute(source, "rotateUV", def->_rotate_uv); 00593 00594 RGBColorf color_gain; 00595 float alpha_gain; 00596 get_vec3f_attribute(source, "colorGain", color_gain); 00597 get_maya_attribute(source, "alphaGain", alpha_gain); 00598 def->_color_gain[0] = color_gain[0]; 00599 def->_color_gain[1] = color_gain[1]; 00600 def->_color_gain[2] = color_gain[2]; 00601 def->_color_gain[3] = alpha_gain; 00602 00603 def->_is_alpha = is_alpha; 00604 00605 if (maya_cat.is_debug()) { 00606 maya_cat.debug() << "pushed a file texture" << endl; 00607 } 00608 list.push_back(def); 00609 00610 return; 00611 } 00612 00613 if (source.hasFn(MFn::kProjection)) { 00614 // This is a projected texture. We will have to step one level 00615 // deeper to find the actual texture. 00616 size_t before = list.size(); 00617 MPlug image_plug = sourceFn.findPlug("image"); 00618 if (!image_plug.isNull()) { 00619 MPlugArray image_pa; 00620 image_plug.connectedTo(image_pa, true, false); 00621 00622 for (size_t i = 0; i < image_pa.length(); i++) { 00623 find_textures_modern(shadername, list, image_pa[0], _texture_copy, _texture_out_dir, is_alpha); 00624 } 00625 } 00626 00627 // Now apply any inherited attributes to all textures found. 00628 00629 for (size_t i=before; i<list.size(); i++) { 00630 MayaShaderColorDef *def = list[i]; 00631 00632 if (!get_mat4d_attribute(source, "placementMatrix", def->_projection_matrix)) { 00633 def->_projection_matrix = LMatrix4d::ident_mat(); 00634 } 00635 00636 // The uAngle and vAngle might be used for certain kinds of 00637 // projections. 00638 if (!get_angle_attribute(source, "uAngle", def->_u_angle)) { 00639 def->_u_angle = 360.0; 00640 } 00641 if (!get_angle_attribute(source, "vAngle", def->_v_angle)) { 00642 def->_v_angle = 180.0; 00643 } 00644 00645 string type; 00646 if (get_enum_attribute(source, "projType", type)) { 00647 def->set_projection_type(type); 00648 } 00649 } 00650 return; 00651 } 00652 00653 if (source.hasFn(MFn::kLayeredTexture)) { 00654 if (maya_cat.is_debug()) { 00655 maya_cat.debug() << "Found layered texture" << endl; 00656 } 00657 00658 MPlug inputsPlug = sourceFn.findPlug("inputs"); 00659 size_t nlayers = inputsPlug.numElements(); 00660 for (size_t layer=0; layer<nlayers; layer++) { 00661 MPlug elt = inputsPlug.elementByPhysicalIndex(layer); 00662 MPlug color; 00663 MPlug blend; 00664 for (size_t j=0; j<elt.numChildren(); j++) { 00665 MPlug child = elt.child(j); 00666 MFnAttribute att(child.attribute()); 00667 if (att.name() == "color") color = child; 00668 if (att.name() == "blendMode") blend = child; 00669 } 00670 if (color.isNull() || blend.isNull()) { 00671 maya_cat.warning() << "Invalid layered texture - bad inputs.\n"; 00672 return; 00673 } 00674 size_t before = list.size(); 00675 find_textures_modern(shadername, list, color, _texture_copy, _texture_out_dir, is_alpha); 00676 int blendValue; 00677 blend.getValue(blendValue); 00678 for (size_t sub=before; sub<list.size(); sub++) { 00679 MayaShaderColorDef *def = list[sub]; 00680 switch (blendValue) { 00681 case 1: def->_blend_type = BT_decal; break; 00682 case 6: def->_blend_type = BT_modulate; break; 00683 case 4: def->_blend_type = BT_add; break; 00684 } 00685 } 00686 } 00687 return; 00688 } 00689 00690 if (source.apiType() == MFn::kReverse) { 00691 MPlug input_plug = sourceFn.findPlug("input"); 00692 find_textures_modern(shadername, list, input_plug, _texture_copy, _texture_out_dir, is_alpha); 00693 return; 00694 } 00695 00696 // This shader wasn't understood. 00697 if (maya_cat.is_debug()) { 00698 maya_cat.info() 00699 << "**Don't know how to interpret color attribute type " 00700 << source.apiTypeStr() << "\n"; 00701 } else { 00702 // If we don't have a heavy verbose count, only report each type 00703 // of unsupported shader once. 00704 static pset<MFn::Type> bad_types; 00705 if (bad_types.insert(source.apiType()).second) { 00706 maya_cat.warning() 00707 << "Don't know how to export a shader of type " 00708 << source.apiTypeStr() << " " << sourceFn.type() << "\n"; 00709 } 00710 } 00711 } 00712 00713 //////////////////////////////////////////////////////////////////// 00714 // Function: MayaShaderColorDef::set_projection_type 00715 // Access: Private 00716 // Description: Sets up the shader to apply UV's according to the 00717 // indicated projection type. 00718 //////////////////////////////////////////////////////////////////// 00719 void MayaShaderColorDef:: 00720 set_projection_type(const string &type) { 00721 if (cmp_nocase(type, "planar") == 0) { 00722 _projection_type = PT_planar; 00723 _map_uvs = &MayaShaderColorDef::map_planar; 00724 00725 // The Planar projection normally projects to a range (-1, 1) in 00726 // both axes. Scale this into our UV range of (0, 1). 00727 _projection_matrix = _projection_matrix * LMatrix4d(0.5, 0.0, 0.0, 0.0, 00728 0.0, 0.5, 0.0, 0.0, 00729 0.0, 0.0, 1.0, 0.0, 00730 0.5, 0.5, 0.0, 1.0); 00731 00732 } else if (cmp_nocase(type, "cylindrical") == 0) { 00733 _projection_type = PT_cylindrical; 00734 _map_uvs = &MayaShaderColorDef::map_cylindrical; 00735 00736 // The cylindrical projection is orthographic in the Y axis; scale 00737 // the range (-1, 1) in this axis into our UV range (0, 1). 00738 _projection_matrix = _projection_matrix * LMatrix4d(1.0, 0.0, 0.0, 0.0, 00739 0.0, 0.5, 0.0, 0.0, 00740 0.0, 0.0, 1.0, 0.0, 00741 0.0, 0.5, 0.0, 1.0); 00742 00743 } else if (cmp_nocase(type, "spherical") == 0) { 00744 _projection_type = PT_spherical; 00745 _map_uvs = &MayaShaderColorDef::map_spherical; 00746 00747 } else { 00748 // Other projection types are currently unimplemented by the 00749 // converter. 00750 maya_cat.error() 00751 << "Don't know how to handle type " << type << " projections.\n"; 00752 _projection_type = PT_off; 00753 _map_uvs = NULL; 00754 } 00755 } 00756 00757 //////////////////////////////////////////////////////////////////// 00758 // Function: MayaShaderColorDef::map_planar 00759 // Access: Private 00760 // Description: Computes a UV based on the given point in space, 00761 // using a planar projection. 00762 //////////////////////////////////////////////////////////////////// 00763 LPoint2d MayaShaderColorDef:: 00764 map_planar(const LPoint3d &pos, const LPoint3d &) const { 00765 // A planar projection is about as easy as can be. We ignore the Z 00766 // axis, and project the point into the XY plane. Done. 00767 return LPoint2d(pos[0], pos[1]); 00768 } 00769 00770 //////////////////////////////////////////////////////////////////// 00771 // Function: MayaShaderColorDef::map_spherical 00772 // Access: Private 00773 // Description: Computes a UV based on the given point in space, 00774 // using a spherical projection. 00775 //////////////////////////////////////////////////////////////////// 00776 LPoint2d MayaShaderColorDef:: 00777 map_spherical(const LPoint3d &pos, const LPoint3d ¢roid) const { 00778 // To compute the x position on the frame, we only need to consider 00779 // the angle of the vector about the Y axis. Project the vector 00780 // into the XZ plane to do this. 00781 00782 LVector2d xz(pos[0], pos[2]); 00783 double xz_length = xz.length(); 00784 00785 if (xz_length < 0.01) { 00786 // If we have a point on or near either pole, we've got problems. 00787 // This point maps to the entire bottom edge of the image, so 00788 // which U value should we choose? It does make a difference, 00789 // especially if we have a number of polygons around the south 00790 // pole that all share the common vertex. 00791 00792 // We choose the U value based on the polygon's centroid. 00793 xz.set(centroid[0], centroid[2]); 00794 } 00795 00796 // Now, if the polygon crosses the seam, we also have problems. 00797 // Make sure that the u value is in the same half of the texture as 00798 // the centroid's u value. 00799 double u = rad_2_deg(atan2(xz[0], xz[1])) / (2.0 * _u_angle); 00800 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / (2.0 * _u_angle); 00801 00802 if (u - c > 0.5) { 00803 u -= floor(u - c + 0.5); 00804 } else if (u - c < -0.5) { 00805 u += floor(c - u + 0.5); 00806 } 00807 00808 // Now rotate the vector into the YZ plane, and the V value is based 00809 // on the latitude: the angle about the X axis. 00810 LVector2d yz(pos[1], xz_length); 00811 double v = rad_2_deg(atan2(yz[0], yz[1])) / (2.0 * _v_angle); 00812 00813 LPoint2d uv(u - 0.5, v - 0.5); 00814 00815 nassertr(fabs(u - c) <= 0.5, uv); 00816 return uv; 00817 } 00818 00819 //////////////////////////////////////////////////////////////////// 00820 // Function: MayaShaderColorDef::map_cylindrical 00821 // Access: Private 00822 // Description: Computes a UV based on the given point in space, 00823 // using a cylindrical projection. 00824 //////////////////////////////////////////////////////////////////// 00825 LPoint2d MayaShaderColorDef:: 00826 map_cylindrical(const LPoint3d &pos, const LPoint3d ¢roid) const { 00827 // This is almost identical to the spherical projection, except for 00828 // the computation of V. 00829 00830 LVector2d xz(pos[0], pos[2]); 00831 double xz_length = xz.length(); 00832 00833 if (xz_length < 0.01) { 00834 // A cylindrical mapping has the same singularity problem at the 00835 // pole as a spherical mapping does: points at the pole do not map 00836 // to a single point on the texture. (It's technically a slightly 00837 // different problem: in a cylindrical mapping, points at the pole 00838 // do not map to any point on the texture, while in a spherical 00839 // mapping, points at the pole map to the top or bottom edge of 00840 // the texture. But this is a technicality that doesn't really 00841 // apply to us.) We still solve it the same way: if our point is 00842 // at or near the pole, compute the angle based on the centroid of 00843 // the polygon (which we assume is further from the pole). 00844 xz.set(centroid[0], centroid[2]); 00845 } 00846 00847 // And cylinders do still have a seam at the back. 00848 double u = rad_2_deg(atan2(xz[0], xz[1])) / _u_angle; 00849 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / _u_angle; 00850 00851 if (u - c > 0.5) { 00852 u -= floor(u - c + 0.5); 00853 } else if (u - c < -0.5) { 00854 u += floor(c - u + 0.5); 00855 } 00856 00857 // For a cylindrical mapping, the V value comes directly from Y. 00858 // Easy. 00859 LPoint2d uv(u - 0.5, pos[1]); 00860 00861 nassertr(fabs(u - c) <= 0.5, uv); 00862 return uv; 00863 }