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 LTexCoordd MayaShaderColorDef:: 00185 project_uv(const LPoint3d &pos, const LPoint3d ¢roid) const { 00186 nassertr(_map_uvs != NULL, LTexCoordd::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 trans) { 00270 LRGBColor color_gain; 00271 if (get_vec3_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 PN_stdfloat 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 } 00306 00307 get_vec2_attribute(color, "coverage", _coverage); 00308 get_vec2_attribute(color, "translateFrame", _translate_frame); 00309 get_angle_attribute(color, "rotateFrame", _rotate_frame); 00310 00311 //get_bool_attribute(color, "alphaIsLuminance", _alpha_is_luminance); 00312 00313 get_bool_attribute(color, "mirror", _mirror); 00314 get_bool_attribute(color, "stagger", _stagger); 00315 get_bool_attribute(color, "wrapU", _wrap_u); 00316 get_bool_attribute(color, "wrapV", _wrap_v); 00317 00318 get_vec2_attribute(color, "repeatUV", _repeat_uv); 00319 get_vec2_attribute(color, "offset", _offset); 00320 get_angle_attribute(color, "rotateUV", _rotate_uv); 00321 00322 if (!trans) { 00323 if (maya_cat.is_debug()) { 00324 maya_cat.debug() << "pushed a file texture" << endl; 00325 } 00326 shader->_color.push_back(this); 00327 } 00328 00329 } else if (color.hasFn(MFn::kProjection)) { 00330 if (maya_cat.is_debug()) { 00331 maya_cat.debug() << "reading a projection texture" << endl; 00332 } 00333 // This is a projected texture. We will have to step one level 00334 // deeper to find the actual texture. 00335 MFnDependencyNode projection_fn(color); 00336 MPlug image_plug = projection_fn.findPlug("image"); 00337 if (!image_plug.isNull()) { 00338 MPlugArray image_pa; 00339 image_plug.connectedTo(image_pa, true, false); 00340 00341 for (size_t i = 0; i < image_pa.length(); i++) { 00342 find_textures_legacy(shader, image_pa[0].node()); 00343 } 00344 } 00345 00346 if (!get_mat4d_attribute(color, "placementMatrix", _projection_matrix)) { 00347 _projection_matrix = LMatrix4d::ident_mat(); 00348 } 00349 00350 // The uAngle and vAngle might be used for certain kinds of 00351 // projections. 00352 if (!get_angle_attribute(color, "uAngle", _u_angle)) { 00353 _u_angle = 360.0; 00354 } 00355 if (!get_angle_attribute(color, "vAngle", _v_angle)) { 00356 _v_angle = 180.0; 00357 } 00358 00359 string type; 00360 if (get_enum_attribute(color, "projType", type)) { 00361 set_projection_type(type); 00362 } 00363 00364 } else if (color.hasFn(MFn::kLayeredTexture)) { 00365 if (maya_cat.is_debug()) { 00366 maya_cat.debug() << "Found layered texture" << endl; 00367 } 00368 00369 int blendValue; 00370 MStatus status; 00371 MPlugArray color_pa; 00372 MFnDependencyNode layered_fn(color); 00373 layered_fn.getConnections(color_pa); 00374 MPlug inputsPlug = layered_fn.findPlug("inputs", &status); 00375 MPlug blendModePlug = layered_fn.findPlug("blendMode", &status); 00376 00377 if (maya_cat.is_debug()) { 00378 maya_cat.debug() << "number of connections: " << color_pa.length() << endl; 00379 } 00380 bool first = true; 00381 BlendType bt = BT_modulate; 00382 for (size_t i=0; i<color_pa.length(); ++i) { 00383 MPlug pl = color_pa[i]; 00384 MPlugArray pla; 00385 pl.connectedTo(pla, true, false); 00386 00387 // First figure out the blend mode intended for this shadercolordef 00388 int li = pl.logicalIndex(); 00389 if (li > -1) { 00390 // found a blend mode 00391 if (maya_cat.is_spam()) { 00392 maya_cat.spam() << "*** Start doIt... ***" << endl; 00393 maya_cat.spam() << "inputsPlug Name: " << inputsPlug.name() << endl; 00394 } 00395 status = blendModePlug.selectAncestorLogicalIndex(li,inputsPlug); 00396 blendModePlug.getValue(blendValue); 00397 00398 if (maya_cat.is_spam()) { 00399 maya_cat.spam() 00400 << blendModePlug.name() << ": has value " << blendValue << endl; 00401 } 00402 00403 MFnEnumAttribute blendModeEnum(blendModePlug); 00404 MString blendName = blendModeEnum.fieldName(blendValue, &status); 00405 00406 switch (blendValue) { 00407 case 1: 00408 bt = BT_decal; 00409 get_bool_attribute(color, "interpolate", _interpolate); 00410 maya_cat.info() << "interpolate: " << _interpolate << endl; 00411 _keep_color = true; 00412 break; 00413 case 6: 00414 bt = BT_modulate; 00415 get_bool_attribute(color, "keepAlpha", _keep_alpha); 00416 maya_cat.info() << "keepAlpha: " << _keep_alpha << endl; 00417 break; 00418 case 4: 00419 bt = BT_add; 00420 break; 00421 } 00422 maya_cat.info() << layered_fn.name() << ": blendMode used " << blendName << endl; 00423 if (maya_cat.is_spam()) { 00424 maya_cat.spam() << "*** END doIt... ***" << endl; 00425 } 00426 00427 // advance to the next plug, because that is where the shader info are 00428 pl = color_pa[++i]; 00429 pl.connectedTo(pla, true, false); 00430 } 00431 for (size_t j=0; j<pla.length(); ++j) { 00432 //maya_cat.debug() << pl.name() << " is(pl) " << pl.node().apiTypeStr() << endl; 00433 //maya_cat.debug() << pla[j].name() << " is(pla) " << pla[j].node().apiTypeStr() << endl; 00434 string pla_name = pla[j].name().asChar(); 00435 // sometimes, by default, maya gives a outAlpha on subsequent plugs, ignore that 00436 if (pla_name.find("outAlpha") != string::npos) { 00437 // top texture has an alpha channel, so make sure that this alpha is retained by egg file 00438 if (maya_cat.is_debug()) { 00439 maya_cat.debug() << pl.name().asChar() << ":has alpha channel" << pla_name << endl; 00440 } 00441 _has_alpha_channel = true; 00442 continue; 00443 } 00444 if (!first) { 00445 if (maya_cat.is_debug()) { 00446 maya_cat.debug() << pl.name().asChar() << " next:connectedTo: " << pla_name << endl; 00447 } 00448 MayaShaderColorDef *color_p = new MayaShaderColorDef; 00449 color_p->find_textures_legacy(shader, pla[j].node()); 00450 color_p->_blend_type = bt; 00451 size_t loc = color_p->_texture_name.find('.',0); 00452 if (loc != string::npos) { 00453 color_p->_texture_name.resize(loc); 00454 } 00455 if (maya_cat.is_debug()) { 00456 maya_cat.debug() << "uv_name : " << color_p->_texture_name << endl; 00457 } 00458 } 00459 else { 00460 if (maya_cat.is_debug()) { 00461 maya_cat.debug() << pl.name().asChar() << " first:connectedTo: " << pla_name << endl; 00462 } 00463 find_textures_legacy(shader, pla[j].node()); 00464 _texture_name.assign(pla[j].name().asChar()); 00465 _blend_type = bt; 00466 size_t loc = _texture_name.find('.',0); 00467 if (loc != string::npos) { 00468 _texture_name.resize(loc); 00469 } 00470 if (maya_cat.is_debug()) { 00471 maya_cat.debug() << "uv_name : " << _texture_name << endl; 00472 } 00473 first = false; 00474 } 00475 } 00476 } 00477 } else { 00478 // This shader wasn't understood. 00479 if (maya_cat.is_debug()) { 00480 maya_cat.info() 00481 << "**Don't know how to interpret color attribute type " 00482 << color.apiTypeStr() << "\n"; 00483 00484 } else { 00485 // If we don't have a heavy verbose count, only report each type 00486 // of unsupported shader once. 00487 static pset<MFn::Type> bad_types; 00488 if (bad_types.insert(color.apiType()).second) { 00489 maya_cat.info() 00490 << "**Don't know how to interpret color attribute type " 00491 << color.apiTypeStr() << "\n"; 00492 } 00493 } 00494 } 00495 } 00496 00497 //////////////////////////////////////////////////////////////////// 00498 // Function: MayaShaderColorDef::find_textures 00499 // Access: Private 00500 // Description: Search to find any file textures that lead into the 00501 // given input plug. Any textures found will be added 00502 // to the provided MayaShaderColorList. 00503 //////////////////////////////////////////////////////////////////// 00504 void MayaShaderColorDef:: 00505 find_textures_modern(const string &shadername, MayaShaderColorList &list, MPlug inplug, bool is_alpha) { 00506 00507 MPlugArray outplugs; 00508 inplug.connectedTo(outplugs, true, false); 00509 if (outplugs.length() == 0) { 00510 return; 00511 } 00512 if (outplugs.length() > 1) { 00513 // Only one output plug should be connected to a given input plug. 00514 maya_cat.warning() 00515 << "Shader " << shadername << " has weird plug connections.\n"; 00516 return; 00517 } 00518 MPlug outplug = outplugs[0]; 00519 MObject source = outplug.node(); 00520 MFnDependencyNode sourceFn(source); 00521 00522 if (source.hasFn(MFn::kFileTexture)) { 00523 00524 string filename; 00525 bool hasfn = get_string_attribute(source, "fileTextureName", filename); 00526 if ((!hasfn) || (filename.empty())) { 00527 maya_cat.warning() 00528 << "Shader " << shadername << " references file texture " 00529 << "with no file name, ignoring invalid file texture.\n"; 00530 return; 00531 } 00532 Filename fn = filename; 00533 if (fn.is_directory()) { 00534 maya_cat.warning() 00535 << "Shader " << shadername << " references file name " 00536 << filename << " which is a directory, ignoring it.\n"; 00537 return; 00538 } 00539 00540 MayaShaderColorDef *def = new MayaShaderColorDef; 00541 00542 def->_color_object = new MObject(source); 00543 def->_texture_filename = Filename::from_os_specific(filename); 00544 def->_texture_name = sourceFn.name().asChar(); 00545 00546 get_vec2_attribute(source, "coverage", def->_coverage); 00547 get_vec2_attribute(source, "translateFrame", def->_translate_frame); 00548 get_angle_attribute(source, "rotateFrame", def->_rotate_frame); 00549 00550 get_bool_attribute(source, "mirror", def->_mirror); 00551 get_bool_attribute(source, "stagger", def->_stagger); 00552 get_bool_attribute(source, "wrapU", def->_wrap_u); 00553 get_bool_attribute(source, "wrapV", def->_wrap_v); 00554 00555 get_vec2_attribute(source, "repeatUV", def->_repeat_uv); 00556 get_vec2_attribute(source, "offset", def->_offset); 00557 get_angle_attribute(source, "rotateUV", def->_rotate_uv); 00558 00559 LRGBColor color_gain; 00560 PN_stdfloat alpha_gain; 00561 get_vec3_attribute(source, "colorGain", color_gain); 00562 get_maya_attribute(source, "alphaGain", alpha_gain); 00563 def->_color_gain[0] = color_gain[0]; 00564 def->_color_gain[1] = color_gain[1]; 00565 def->_color_gain[2] = color_gain[2]; 00566 def->_color_gain[3] = alpha_gain; 00567 00568 def->_is_alpha = is_alpha; 00569 00570 if (maya_cat.is_debug()) { 00571 maya_cat.debug() << "pushed a file texture" << endl; 00572 } 00573 list.push_back(def); 00574 00575 return; 00576 } 00577 00578 if (source.hasFn(MFn::kProjection)) { 00579 // This is a projected texture. We will have to step one level 00580 // deeper to find the actual texture. 00581 size_t before = list.size(); 00582 MPlug image_plug = sourceFn.findPlug("image"); 00583 if (!image_plug.isNull()) { 00584 MPlugArray image_pa; 00585 image_plug.connectedTo(image_pa, true, false); 00586 00587 for (size_t i = 0; i < image_pa.length(); i++) { 00588 find_textures_modern(shadername, list, image_pa[0], is_alpha); 00589 } 00590 } 00591 00592 // Now apply any inherited attributes to all textures found. 00593 00594 for (size_t i=before; i<list.size(); i++) { 00595 MayaShaderColorDef *def = list[i]; 00596 00597 if (!get_mat4d_attribute(source, "placementMatrix", def->_projection_matrix)) { 00598 def->_projection_matrix = LMatrix4d::ident_mat(); 00599 } 00600 00601 // The uAngle and vAngle might be used for certain kinds of 00602 // projections. 00603 if (!get_angle_attribute(source, "uAngle", def->_u_angle)) { 00604 def->_u_angle = 360.0; 00605 } 00606 if (!get_angle_attribute(source, "vAngle", def->_v_angle)) { 00607 def->_v_angle = 180.0; 00608 } 00609 00610 string type; 00611 if (get_enum_attribute(source, "projType", type)) { 00612 def->set_projection_type(type); 00613 } 00614 } 00615 return; 00616 } 00617 00618 if (source.hasFn(MFn::kLayeredTexture)) { 00619 if (maya_cat.is_debug()) { 00620 maya_cat.debug() << "Found layered texture" << endl; 00621 } 00622 00623 MPlug inputsPlug = sourceFn.findPlug("inputs"); 00624 size_t nlayers = inputsPlug.numElements(); 00625 for (size_t layer=0; layer<nlayers; layer++) { 00626 MPlug elt = inputsPlug.elementByPhysicalIndex(layer); 00627 MPlug color; 00628 MPlug blend; 00629 for (size_t j=0; j<elt.numChildren(); j++) { 00630 MPlug child = elt.child(j); 00631 MFnAttribute att(child.attribute()); 00632 if (att.name() == "color") color = child; 00633 if (att.name() == "blendMode") blend = child; 00634 } 00635 if (color.isNull() || blend.isNull()) { 00636 maya_cat.warning() << "Invalid layered texture - bad inputs.\n"; 00637 return; 00638 } 00639 size_t before = list.size(); 00640 find_textures_modern(shadername, list, color, is_alpha); 00641 int blendValue; 00642 blend.getValue(blendValue); 00643 for (size_t sub=before; sub<list.size(); sub++) { 00644 MayaShaderColorDef *def = list[sub]; 00645 switch (blendValue) { 00646 case 1: def->_blend_type = BT_decal; break; 00647 case 6: def->_blend_type = BT_modulate; break; 00648 case 4: def->_blend_type = BT_add; break; 00649 } 00650 } 00651 } 00652 return; 00653 } 00654 00655 if (source.apiType() == MFn::kReverse) { 00656 MPlug input_plug = sourceFn.findPlug("input"); 00657 find_textures_modern(shadername, list, input_plug, is_alpha); 00658 return; 00659 } 00660 00661 // This shader wasn't understood. 00662 if (maya_cat.is_debug()) { 00663 maya_cat.info() 00664 << "**Don't know how to interpret color attribute type " 00665 << source.apiTypeStr() << "\n"; 00666 } else { 00667 // If we don't have a heavy verbose count, only report each type 00668 // of unsupported shader once. 00669 static pset<MFn::Type> bad_types; 00670 if (bad_types.insert(source.apiType()).second) { 00671 maya_cat.warning() 00672 << "Don't know how to export a shader of type " 00673 << source.apiTypeStr() << " " << sourceFn.type() << "\n"; 00674 } 00675 } 00676 } 00677 00678 //////////////////////////////////////////////////////////////////// 00679 // Function: MayaShaderColorDef::set_projection_type 00680 // Access: Private 00681 // Description: Sets up the shader to apply UV's according to the 00682 // indicated projection type. 00683 //////////////////////////////////////////////////////////////////// 00684 void MayaShaderColorDef:: 00685 set_projection_type(const string &type) { 00686 if (cmp_nocase(type, "planar") == 0) { 00687 _projection_type = PT_planar; 00688 _map_uvs = &MayaShaderColorDef::map_planar; 00689 00690 // The Planar projection normally projects to a range (-1, 1) in 00691 // both axes. Scale this into our UV range of (0, 1). 00692 _projection_matrix = _projection_matrix * LMatrix4d(0.5, 0.0, 0.0, 0.0, 00693 0.0, 0.5, 0.0, 0.0, 00694 0.0, 0.0, 1.0, 0.0, 00695 0.5, 0.5, 0.0, 1.0); 00696 00697 } else if (cmp_nocase(type, "cylindrical") == 0) { 00698 _projection_type = PT_cylindrical; 00699 _map_uvs = &MayaShaderColorDef::map_cylindrical; 00700 00701 // The cylindrical projection is orthographic in the Y axis; scale 00702 // the range (-1, 1) in this axis into our UV range (0, 1). 00703 _projection_matrix = _projection_matrix * LMatrix4d(1.0, 0.0, 0.0, 0.0, 00704 0.0, 0.5, 0.0, 0.0, 00705 0.0, 0.0, 1.0, 0.0, 00706 0.0, 0.5, 0.0, 1.0); 00707 00708 } else if (cmp_nocase(type, "spherical") == 0) { 00709 _projection_type = PT_spherical; 00710 _map_uvs = &MayaShaderColorDef::map_spherical; 00711 00712 } else { 00713 // Other projection types are currently unimplemented by the 00714 // converter. 00715 maya_cat.error() 00716 << "Don't know how to handle type " << type << " projections.\n"; 00717 _projection_type = PT_off; 00718 _map_uvs = NULL; 00719 } 00720 } 00721 00722 //////////////////////////////////////////////////////////////////// 00723 // Function: MayaShaderColorDef::map_planar 00724 // Access: Private 00725 // Description: Computes a UV based on the given point in space, 00726 // using a planar projection. 00727 //////////////////////////////////////////////////////////////////// 00728 LPoint2d MayaShaderColorDef:: 00729 map_planar(const LPoint3d &pos, const LPoint3d &) const { 00730 // A planar projection is about as easy as can be. We ignore the Z 00731 // axis, and project the point into the XY plane. Done. 00732 return LPoint2d(pos[0], pos[1]); 00733 } 00734 00735 //////////////////////////////////////////////////////////////////// 00736 // Function: MayaShaderColorDef::map_spherical 00737 // Access: Private 00738 // Description: Computes a UV based on the given point in space, 00739 // using a spherical projection. 00740 //////////////////////////////////////////////////////////////////// 00741 LPoint2d MayaShaderColorDef:: 00742 map_spherical(const LPoint3d &pos, const LPoint3d ¢roid) const { 00743 // To compute the x position on the frame, we only need to consider 00744 // the angle of the vector about the Y axis. Project the vector 00745 // into the XZ plane to do this. 00746 00747 LVector2d xz(pos[0], pos[2]); 00748 double xz_length = xz.length(); 00749 00750 if (xz_length < 0.01) { 00751 // If we have a point on or near either pole, we've got problems. 00752 // This point maps to the entire bottom edge of the image, so 00753 // which U value should we choose? It does make a difference, 00754 // especially if we have a number of polygons around the south 00755 // pole that all share the common vertex. 00756 00757 // We choose the U value based on the polygon's centroid. 00758 xz.set(centroid[0], centroid[2]); 00759 } 00760 00761 // Now, if the polygon crosses the seam, we also have problems. 00762 // Make sure that the u value is in the same half of the texture as 00763 // the centroid's u value. 00764 double u = rad_2_deg(atan2(xz[0], xz[1])) / (2.0 * _u_angle); 00765 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / (2.0 * _u_angle); 00766 00767 if (u - c > 0.5) { 00768 u -= floor(u - c + 0.5); 00769 } else if (u - c < -0.5) { 00770 u += floor(c - u + 0.5); 00771 } 00772 00773 // Now rotate the vector into the YZ plane, and the V value is based 00774 // on the latitude: the angle about the X axis. 00775 LVector2d yz(pos[1], xz_length); 00776 double v = rad_2_deg(atan2(yz[0], yz[1])) / (2.0 * _v_angle); 00777 00778 LPoint2d uv(u - 0.5, v - 0.5); 00779 00780 nassertr(fabs(u - c) <= 0.5, uv); 00781 return uv; 00782 } 00783 00784 //////////////////////////////////////////////////////////////////// 00785 // Function: MayaShaderColorDef::map_cylindrical 00786 // Access: Private 00787 // Description: Computes a UV based on the given point in space, 00788 // using a cylindrical projection. 00789 //////////////////////////////////////////////////////////////////// 00790 LPoint2d MayaShaderColorDef:: 00791 map_cylindrical(const LPoint3d &pos, const LPoint3d ¢roid) const { 00792 // This is almost identical to the spherical projection, except for 00793 // the computation of V. 00794 00795 LVector2d xz(pos[0], pos[2]); 00796 double xz_length = xz.length(); 00797 00798 if (xz_length < 0.01) { 00799 // A cylindrical mapping has the same singularity problem at the 00800 // pole as a spherical mapping does: points at the pole do not map 00801 // to a single point on the texture. (It's technically a slightly 00802 // different problem: in a cylindrical mapping, points at the pole 00803 // do not map to any point on the texture, while in a spherical 00804 // mapping, points at the pole map to the top or bottom edge of 00805 // the texture. But this is a technicality that doesn't really 00806 // apply to us.) We still solve it the same way: if our point is 00807 // at or near the pole, compute the angle based on the centroid of 00808 // the polygon (which we assume is further from the pole). 00809 xz.set(centroid[0], centroid[2]); 00810 } 00811 00812 // And cylinders do still have a seam at the back. 00813 double u = rad_2_deg(atan2(xz[0], xz[1])) / _u_angle; 00814 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / _u_angle; 00815 00816 if (u - c > 0.5) { 00817 u -= floor(u - c + 0.5); 00818 } else if (u - c < -0.5) { 00819 u += floor(c - u + 0.5); 00820 } 00821 00822 // For a cylindrical mapping, the V value comes directly from Y. 00823 // Easy. 00824 LPoint2d uv(u - 0.5, pos[1]); 00825 00826 nassertr(fabs(u - c) <= 0.5, uv); 00827 return uv; 00828 }