24 #include <maya/MFnDependencyNode.h> 25 #include <maya/MPlug.h> 26 #include <maya/MPlugArray.h> 27 #include <maya/MObject.h> 28 #include <maya/MStatus.h> 29 #include <maya/MFnEnumAttribute.h> 39 MayaShaderColorDef() {
41 _blend_type = BT_unspecified;
43 _projection_type = PT_off;
44 _projection_matrix = LMatrix4d::ident_mat();
48 _texture_filename =
"";
50 _color_gain.set(1.0f, 1.0f, 1.0f, 1.0f);
52 _coverage.set(1.0, 1.0);
53 _translate_frame.set(0.0, 0.0);
61 _repeat_uv.set(1.0, 1.0);
62 _offset.set(0.0, 0.0);
69 _color_object =
nullptr;
72 _has_flat_color =
false;
73 _flat_color.set(0.0, 0.0, 0.0, 0.0);
74 _has_alpha_channel =
false;
88 _has_texture = copy._has_texture;
89 _texture_filename = copy._texture_filename;
90 _texture_name = copy._texture_name;
91 _uvset_name = copy._uvset_name;
92 _color_gain = copy._color_gain;
94 _has_flat_color = copy._has_flat_color;
95 _flat_color = copy._flat_color;
97 _projection_type = copy._projection_type;
98 _projection_matrix = copy._projection_matrix;
99 _u_angle = copy._u_angle;
100 _v_angle = copy._v_angle;
102 _coverage = copy._coverage;
103 _translate_frame = copy._translate_frame;
104 _rotate_frame = copy._rotate_frame;
106 _mirror = copy._mirror;
107 _stagger = copy._stagger;
108 _wrap_u = copy._wrap_u;
109 _wrap_v = copy._wrap_v;
111 _blend_type = copy._blend_type;
112 _has_alpha_channel = copy._has_alpha_channel;
113 _keep_color = copy._keep_color;
114 _keep_alpha = copy._keep_alpha;
115 _interpolate = copy._interpolate;
117 _repeat_uv = copy._repeat_uv;
118 _offset = copy._offset;
119 _rotate_uv = copy._rotate_uv;
121 _is_alpha = copy._is_alpha;
123 _map_uvs = copy._map_uvs;
124 _color_object = copy._color_object;
133 ~MayaShaderColorDef() {
134 if (_color_object !=
nullptr) {
135 delete _color_object;
145 LVector2d scale(_repeat_uv[0] / _coverage[0],
146 _repeat_uv[1] / _coverage[1]);
147 LVector2d trans(_offset[0] - _translate_frame[0] / _coverage[0],
148 _offset[1] - _translate_frame[1] / _coverage[1]);
151 (LMatrix3d::translate_mat(LVector2d(-0.5, -0.5)) *
152 LMatrix3d::rotate_mat(_rotate_frame) *
153 LMatrix3d::translate_mat(LVector2d(0.5, 0.5))) *
154 LMatrix3d::scale_mat(scale) *
155 LMatrix3d::translate_mat(trans);
163 return (_projection_type != PT_off);
174 project_uv(
const LPoint3d &pos,
const LPoint3d ¢roid)
const {
175 nassertr(_map_uvs !=
nullptr, LTexCoordd::zero());
176 return (this->*_map_uvs)(pos * _projection_matrix, centroid * _projection_matrix);
182 void MayaShaderColorDef::
183 write(std::ostream &out)
const {
185 out <<
" texture filename is " << _texture_filename <<
"\n" 186 <<
" texture name is " << _texture_name <<
"\n" 187 <<
" uv_set name is " << _uvset_name <<
"\n" 188 <<
" coverage is " << _coverage <<
"\n" 189 <<
" translate_frame is " << _translate_frame <<
"\n" 190 <<
" rotate_frame is " << _rotate_frame <<
"\n" 191 <<
" mirror is " << _mirror <<
"\n" 192 <<
" stagger is " << _stagger <<
"\n" 193 <<
" wrap_u is " << _wrap_u <<
"\n" 194 <<
" wrap_v is " << _wrap_v <<
"\n" 195 <<
" repeat_uv is " << _repeat_uv <<
"\n" 196 <<
" offset is " << _offset <<
"\n" 197 <<
" rotate_uv is " << _rotate_uv <<
"\n" 198 <<
" color_gain is " << _color_gain <<
"\n";
200 }
else if (_has_flat_color) {
201 out <<
" flat color is " << _flat_color <<
"\n";
211 if (_color_object !=
nullptr) {
214 _texture_filename = texture;
218 <<
"Unable to reset texture filename.\n";
225 <<
"Attempt to reset texture on Maya object that has no color set.\n";
236 if (_uvset_name ==
"map1") {
247 void MayaShaderColorDef::
248 find_textures_legacy(
MayaShader *shader, MObject color,
bool trans) {
249 LRGBColor color_gain;
251 color_gain[0] = color_gain[0] > 1.0 ? 1.0 : color_gain[0];
252 color_gain[0] = color_gain[0] < 0.0 ? 0.0 : color_gain[0];
253 _color_gain[0] *= color_gain[0];
254 color_gain[1] = color_gain[1] > 1.0 ? 1.0 : color_gain[1];
255 color_gain[1] = color_gain[1] < 0.0 ? 0.0 : color_gain[1];
256 _color_gain[1] *= color_gain[1];
257 color_gain[2] = color_gain[2] > 1.0 ? 1.0 : color_gain[2];
258 color_gain[2] = color_gain[2] < 0.0 ? 0.0 : color_gain[2];
259 _color_gain[2] *= color_gain[2];
261 PN_stdfloat alpha_gain;
262 if (get_maya_attribute(color,
"alphaGain", alpha_gain)) {
263 alpha_gain = alpha_gain > 1.0 ? 1.0 : alpha_gain;
264 alpha_gain = alpha_gain < 0.0 ? 0.0 : alpha_gain;
265 _color_gain[3] *= alpha_gain;
267 if (color.hasFn(MFn::kFileTexture)) {
268 MFnDependencyNode dfn(color);
269 _color_object =
new MObject(color);
270 _texture_name = dfn.name().asChar();
273 _has_texture = _has_texture && !filename.empty();
278 <<
"Shader " << shader->get_name()
279 <<
" references texture filename " << filename
280 <<
" which is a directory; clearing.\n";
281 _has_texture =
false;
302 if (maya_cat.is_debug()) {
303 maya_cat.debug() <<
"pushed a file texture" << endl;
305 shader->_color.push_back(
this);
308 }
else if (color.hasFn(MFn::kProjection)) {
309 if (maya_cat.is_debug()) {
310 maya_cat.debug() <<
"reading a projection texture" << endl;
314 MFnDependencyNode projection_fn(color);
315 MPlug image_plug = projection_fn.findPlug(
"image");
316 if (!image_plug.isNull()) {
318 image_plug.connectedTo(image_pa,
true,
false);
320 for (
size_t i = 0; i < image_pa.length(); i++) {
321 find_textures_legacy(shader, image_pa[0].node());
326 _projection_matrix = LMatrix4d::ident_mat();
339 set_projection_type(type);
342 }
else if (color.hasFn(MFn::kLayeredTexture)) {
343 if (maya_cat.is_debug()) {
344 maya_cat.debug() <<
"Found layered texture" << endl;
350 MFnDependencyNode layered_fn(color);
351 layered_fn.getConnections(color_pa);
352 MPlug inputsPlug = layered_fn.findPlug(
"inputs", &status);
353 MPlug blendModePlug = layered_fn.findPlug(
"blendMode", &status);
355 if (maya_cat.is_debug()) {
356 maya_cat.debug() <<
"number of connections: " << color_pa.length() << endl;
359 BlendType bt = BT_modulate;
360 for (
size_t i=0; i<color_pa.length(); ++i) {
361 MPlug pl = color_pa[i];
363 pl.connectedTo(pla,
true,
false);
366 int li = pl.logicalIndex();
369 if (maya_cat.is_spam()) {
370 MString name = inputsPlug.name();
371 maya_cat.spam() <<
"*** Start doIt... ***" << endl;
372 maya_cat.spam() <<
"inputsPlug Name: " << name.asChar() << endl;
374 status = blendModePlug.selectAncestorLogicalIndex(li,inputsPlug);
375 blendModePlug.getValue(blendValue);
377 if (maya_cat.is_spam()) {
378 MString name = blendModePlug.name();
380 << name.asChar() <<
": has value " << blendValue << endl;
383 MFnEnumAttribute blendModeEnum(blendModePlug);
384 MString blendName = blendModeEnum.fieldName(blendValue, &status);
386 switch (blendValue) {
390 maya_cat.info() <<
"interpolate: " << _interpolate << endl;
396 maya_cat.info() <<
"keepAlpha: " << _keep_alpha << endl;
403 if (maya_cat.is_info()) {
404 MString name = layered_fn.name();
405 maya_cat.info() << name.asChar() <<
": blendMode used " << blendName.asChar() << endl;
406 if (maya_cat.is_spam()) {
407 maya_cat.spam() <<
"*** END doIt... ***" << endl;
413 pl.connectedTo(pla,
true,
false);
415 for (
size_t j=0; j<pla.length(); ++j) {
419 string pla_name = pla[j].name().asChar();
422 if (pla_name.find(
"outAlpha") != string::npos) {
425 if (maya_cat.is_debug()) {
426 maya_cat.debug() << pl.name().asChar() <<
":has alpha channel" << pla_name << endl;
428 _has_alpha_channel =
true;
432 if (maya_cat.is_debug()) {
433 maya_cat.debug() << pl.name().asChar() <<
" next:connectedTo: " << pla_name << endl;
436 color_p->find_textures_legacy(shader, pla[j].node());
437 color_p->_blend_type = bt;
438 size_t loc = color_p->_texture_name.find(
'.',0);
439 if (loc != string::npos) {
440 color_p->_texture_name.resize(loc);
442 if (maya_cat.is_debug()) {
443 maya_cat.debug() <<
"uv_name : " << color_p->_texture_name << endl;
447 if (maya_cat.is_debug()) {
448 maya_cat.debug() << pl.name().asChar() <<
" first:connectedTo: " << pla_name << endl;
450 find_textures_legacy(shader, pla[j].node());
451 _texture_name.assign(pla[j].name().asChar());
453 size_t loc = _texture_name.find(
'.',0);
454 if (loc != string::npos) {
455 _texture_name.resize(loc);
457 if (maya_cat.is_debug()) {
458 maya_cat.debug() <<
"uv_name : " << _texture_name << endl;
466 if (maya_cat.is_debug()) {
468 <<
"**Don't know how to interpret color attribute type " 469 << color.apiTypeStr() <<
"\n";
475 if (bad_types.insert(color.apiType()).second) {
477 <<
"**Don't know how to interpret color attribute type " 478 << color.apiTypeStr() <<
"\n";
488 void MayaShaderColorDef::
489 find_textures_modern(
const string &shadername,
MayaShaderColorList &list, MPlug inplug,
bool is_alpha) {
492 inplug.connectedTo(outplugs,
true,
false);
493 if (outplugs.length() == 0) {
496 if (outplugs.length() > 1) {
499 <<
"Shader " << shadername <<
" has weird plug connections.\n";
502 MPlug outplug = outplugs[0];
503 MObject source = outplug.node();
504 MFnDependencyNode sourceFn(source);
506 if (source.hasFn(MFn::kFileTexture)) {
510 if ((!hasfn) || (filename.empty())) {
512 <<
"Shader " << shadername <<
" references file texture " 513 <<
"with no file name, ignoring invalid file texture.\n";
519 <<
"Shader " << shadername <<
" references file name " 520 << filename <<
" which is a directory, ignoring it.\n";
526 def->_color_object =
new MObject(source);
528 def->_texture_name = sourceFn.name().asChar();
543 LRGBColor color_gain;
544 PN_stdfloat alpha_gain;
546 get_maya_attribute(source,
"alphaGain", alpha_gain);
547 def->_color_gain[0] = color_gain[0];
548 def->_color_gain[1] = color_gain[1];
549 def->_color_gain[2] = color_gain[2];
550 def->_color_gain[3] = alpha_gain;
552 def->_is_alpha = is_alpha;
554 if (maya_cat.is_debug()) {
555 maya_cat.debug() <<
"pushed a file texture" << endl;
562 if (source.hasFn(MFn::kProjection)) {
565 size_t before = list.size();
566 MPlug image_plug = sourceFn.findPlug(
"image");
567 if (!image_plug.isNull()) {
569 image_plug.connectedTo(image_pa,
true,
false);
571 for (
size_t i = 0; i < image_pa.length(); i++) {
572 find_textures_modern(shadername, list, image_pa[0], is_alpha);
578 for (
size_t i=before; i<list.size(); i++) {
582 def->_projection_matrix = LMatrix4d::ident_mat();
587 def->_u_angle = 360.0;
590 def->_v_angle = 180.0;
595 def->set_projection_type(type);
601 if (source.hasFn(MFn::kLayeredTexture)) {
602 if (maya_cat.is_debug()) {
603 maya_cat.debug() <<
"Found layered texture" << endl;
606 MPlug inputsPlug = sourceFn.findPlug(
"inputs");
607 size_t nlayers = inputsPlug.numElements();
608 for (
size_t layer=0; layer<nlayers; layer++) {
609 MPlug elt = inputsPlug.elementByPhysicalIndex(layer);
612 for (
size_t j=0; j<elt.numChildren(); j++) {
613 MPlug child = elt.child(j);
614 MFnAttribute att(child.attribute());
615 if (att.name() ==
"color") color = child;
616 if (att.name() ==
"blendMode") blend = child;
618 if (color.isNull() || blend.isNull()) {
619 maya_cat.warning() <<
"Invalid layered texture - bad inputs.\n";
622 size_t before = list.size();
623 find_textures_modern(shadername, list, color, is_alpha);
625 blend.getValue(blendValue);
626 for (
size_t sub=before; sub<list.size(); sub++) {
628 switch (blendValue) {
629 case 1: def->_blend_type = BT_decal;
break;
630 case 6: def->_blend_type = BT_modulate;
break;
631 case 4: def->_blend_type = BT_add;
break;
638 if (source.apiType() == MFn::kReverse) {
639 MPlug input_plug = sourceFn.findPlug(
"input");
640 find_textures_modern(shadername, list, input_plug, is_alpha);
645 if (maya_cat.is_debug()) {
647 <<
"**Don't know how to interpret color attribute type " 648 << source.apiTypeStr() <<
"\n";
653 if (bad_types.insert(source.apiType()).second) {
655 <<
"Don't know how to export a shader of type " 656 << source.apiTypeStr() <<
" " << sourceFn.type() <<
"\n";
665 void MayaShaderColorDef::
666 set_projection_type(
const string &type) {
667 if (cmp_nocase(type,
"planar") == 0) {
668 _projection_type = PT_planar;
669 _map_uvs = &MayaShaderColorDef::map_planar;
673 _projection_matrix = _projection_matrix * LMatrix4d(0.5, 0.0, 0.0, 0.0,
678 }
else if (cmp_nocase(type,
"cylindrical") == 0) {
679 _projection_type = PT_cylindrical;
680 _map_uvs = &MayaShaderColorDef::map_cylindrical;
684 _projection_matrix = _projection_matrix * LMatrix4d(1.0, 0.0, 0.0, 0.0,
689 }
else if (cmp_nocase(type,
"spherical") == 0) {
690 _projection_type = PT_spherical;
691 _map_uvs = &MayaShaderColorDef::map_spherical;
696 <<
"Don't know how to handle type " << type <<
" projections.\n";
697 _projection_type = PT_off;
705 LPoint2d MayaShaderColorDef::
706 map_planar(
const LPoint3d &pos,
const LPoint3d &)
const {
709 return LPoint2d(pos[0], pos[1]);
716 LPoint2d MayaShaderColorDef::
717 map_spherical(
const LPoint3d &pos,
const LPoint3d ¢roid)
const {
722 LVector2d xz(pos[0], pos[2]);
723 double xz_length = xz.length();
725 if (xz_length < 0.01) {
733 xz.set(centroid[0], centroid[2]);
739 double u = rad_2_deg(atan2(xz[0], xz[1])) / (2.0 * _u_angle);
740 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / (2.0 * _u_angle);
743 u -= floor(u - c + 0.5);
744 }
else if (u - c < -0.5) {
745 u += floor(c - u + 0.5);
750 LVector2d yz(pos[1], xz_length);
751 double v = rad_2_deg(atan2(yz[0], yz[1])) / (2.0 * _v_angle);
753 LPoint2d uv(u - 0.5, v - 0.5);
755 nassertr(fabs(u - c) <= 0.5, uv);
763 LPoint2d MayaShaderColorDef::
764 map_cylindrical(
const LPoint3d &pos,
const LPoint3d ¢roid)
const {
768 LVector2d xz(pos[0], pos[2]);
769 double xz_length = xz.length();
771 if (xz_length < 0.01) {
783 xz.set(centroid[0], centroid[2]);
787 double u = rad_2_deg(atan2(xz[0], xz[1])) / _u_angle;
788 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / _u_angle;
791 u -= floor(u - c + 0.5);
792 }
else if (u - c < -0.5) {
793 u += floor(c - u + 0.5);
797 LPoint2d uv(u - 0.5, pos[1]);
799 nassertr(fabs(u - c) <= 0.5, uv);
bool get_angle_attribute(MObject &node, const string &attribute_name, double &value)
Extracts the named angle in degrees from the MObject.
bool get_mat4d_attribute(MObject &node, const string &attribute_name, LMatrix4d &value)
Extracts the named 4x4 matrix from the MObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LTexCoordd project_uv(const LPoint3d &pos, const LPoint3d &ref_point) const
If the shader has a projection (has_projection() returns true), this computes the appropriate UV corr...
std::string get_panda_uvset_name()
Maya's default uvset name is "map1".
bool get_string_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the named string attribute from the MObject.
bool has_projection() const
Returns true if the shader has a projection in effect.
LMatrix3d compute_texture_matrix() const
Returns a texture matrix corresponding to the texture transforms indicated by the shader.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string to_os_generic() const
This is similar to to_os_specific(), but it is designed to generate a filename that can be understood...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool set_string_attribute(MObject &node, const string &attribute_name, const string &value)
Sets the named string attribute on the MObject.
bool get_bool_attribute(MObject &node, const string &attribute_name, bool &value)
Extracts the named boolean attribute from the MObject.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of a file, such as a texture file or an Egg file.
This defines the various attributes that Maya may associate with the "color" channel for a particular...
Corresponds to a single "shader" in Maya.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_directory() const
Returns true if the filename exists and is a directory name, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_vec3_attribute(MObject &node, const string &attribute_name, LVecBase3 &value)
Extracts the named three-component vector from the MObject.
This is our own Panda specialization on the default STL set.
bool reset_maya_texture(const Filename &texture)
Changes the texture filename stored in the Maya file for this particular shader.
bool get_vec2_attribute(MObject &node, const string &attribute_name, LVecBase2 &value)
Extracts the named two-component vector from the MObject.
bool get_enum_attribute(MObject &node, const string &attribute_name, string &value)
Extracts the enum attribute from the MObject as a string value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.