17 #include "mayaShaderColorDef.h" 18 #include "mayaShader.h" 19 #include "maya_funcs.h" 20 #include "config_maya.h" 21 #include "string_utils.h" 24 #include "pre_maya_include.h" 25 #include <maya/MFnDependencyNode.h> 26 #include <maya/MPlug.h> 27 #include <maya/MPlugArray.h> 28 #include <maya/MObject.h> 29 #include <maya/MStatus.h> 30 #include <maya/MFnEnumAttribute.h> 31 #include "post_maya_include.h" 39 MayaShaderColorDef() {
41 _blend_type = BT_unspecified;
43 _projection_type = PT_off;
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 = (MObject *)NULL;
72 _has_flat_color =
false;
73 _flat_color.set(0.0, 0.0, 0.0, 0.0);
74 _has_alpha_channel =
false;
90 _has_texture = copy._has_texture;
91 _texture_filename = copy._texture_filename;
92 _texture_name = copy._texture_name;
93 _uvset_name = copy._uvset_name;
94 _color_gain = copy._color_gain;
96 _has_flat_color = copy._has_flat_color;
97 _flat_color = copy._flat_color;
99 _projection_type = copy._projection_type;
100 _projection_matrix = copy._projection_matrix;
101 _u_angle = copy._u_angle;
102 _v_angle = copy._v_angle;
104 _coverage = copy._coverage;
105 _translate_frame = copy._translate_frame;
106 _rotate_frame = copy._rotate_frame;
108 _mirror = copy._mirror;
109 _stagger = copy._stagger;
110 _wrap_u = copy._wrap_u;
111 _wrap_v = copy._wrap_v;
113 _blend_type = copy._blend_type;
114 _has_alpha_channel = copy._has_alpha_channel;
115 _keep_color = copy._keep_color;
116 _keep_alpha = copy._keep_alpha;
117 _interpolate = copy._interpolate;
119 _repeat_uv = copy._repeat_uv;
120 _offset = copy._offset;
121 _rotate_uv = copy._rotate_uv;
123 _is_alpha = copy._is_alpha;
125 _map_uvs = copy._map_uvs;
126 _color_object = copy._color_object;
137 ~MayaShaderColorDef() {
138 if (_color_object != (MObject *)NULL) {
139 delete _color_object;
151 LVector2d scale(_repeat_uv[0] / _coverage[0],
152 _repeat_uv[1] / _coverage[1]);
153 LVector2d trans(_offset[0] - _translate_frame[0] / _coverage[0],
154 _offset[1] - _translate_frame[1] / _coverage[1]);
171 return (_projection_type != PT_off);
187 return (this->*_map_uvs)(pos * _projection_matrix, centroid * _projection_matrix);
195 void MayaShaderColorDef::
196 write(ostream &out)
const {
198 out <<
" texture filename is " << _texture_filename <<
"\n" 199 <<
" texture name is " << _texture_name <<
"\n" 200 <<
" uv_set name is " << _uvset_name <<
"\n" 201 <<
" coverage is " << _coverage <<
"\n" 202 <<
" translate_frame is " << _translate_frame <<
"\n" 203 <<
" rotate_frame is " << _rotate_frame <<
"\n" 204 <<
" mirror is " << _mirror <<
"\n" 205 <<
" stagger is " << _stagger <<
"\n" 206 <<
" wrap_u is " << _wrap_u <<
"\n" 207 <<
" wrap_v is " << _wrap_v <<
"\n" 208 <<
" repeat_uv is " << _repeat_uv <<
"\n" 209 <<
" offset is " << _offset <<
"\n" 210 <<
" rotate_uv is " << _rotate_uv <<
"\n" 211 <<
" color_gain is " << _color_gain <<
"\n";
213 }
else if (_has_flat_color) {
214 out <<
" flat color is " << _flat_color <<
"\n";
226 if (_color_object != (MObject *)NULL) {
227 _has_texture = set_string_attribute(*_color_object,
"fileTextureName",
229 _texture_filename = texture;
233 <<
"Unable to reset texture filename.\n";
240 <<
"Attempt to reset texture on Maya object that has no color set.\n";
254 if (_uvset_name ==
"map1") {
268 void MayaShaderColorDef::
269 find_textures_legacy(
MayaShader *shader, MObject color,
bool trans) {
271 if (get_vec3_attribute(color,
"colorGain", color_gain)) {
272 color_gain[0] = color_gain[0] > 1.0 ? 1.0 : color_gain[0];
273 color_gain[0] = color_gain[0] < 0.0 ? 0.0 : color_gain[0];
274 _color_gain[0] *= color_gain[0];
275 color_gain[1] = color_gain[1] > 1.0 ? 1.0 : color_gain[1];
276 color_gain[1] = color_gain[1] < 0.0 ? 0.0 : color_gain[1];
277 _color_gain[1] *= color_gain[1];
278 color_gain[2] = color_gain[2] > 1.0 ? 1.0 : color_gain[2];
279 color_gain[2] = color_gain[2] < 0.0 ? 0.0 : color_gain[2];
280 _color_gain[2] *= color_gain[2];
282 PN_stdfloat alpha_gain;
283 if (get_maya_attribute(color,
"alphaGain", alpha_gain)) {
284 alpha_gain = alpha_gain > 1.0 ? 1.0 : alpha_gain;
285 alpha_gain = alpha_gain < 0.0 ? 0.0 : alpha_gain;
286 _color_gain[3] *= alpha_gain;
288 if (color.hasFn(MFn::kFileTexture)) {
289 MFnDependencyNode dfn(color);
290 _color_object =
new MObject(color);
291 _texture_name = dfn.name().asChar();
293 _has_texture = get_string_attribute(color,
"fileTextureName", filename);
294 _has_texture = _has_texture && !filename.empty();
299 <<
"Shader " << shader->get_name()
300 <<
" references texture filename " << filename
301 <<
" which is a directory; clearing.\n";
302 _has_texture =
false;
303 set_string_attribute(color,
"fileTextureName",
"");
307 get_vec2_attribute(color,
"coverage", _coverage);
308 get_vec2_attribute(color,
"translateFrame", _translate_frame);
309 get_angle_attribute(color,
"rotateFrame", _rotate_frame);
313 get_bool_attribute(color,
"mirror", _mirror);
314 get_bool_attribute(color,
"stagger", _stagger);
315 get_bool_attribute(color,
"wrapU", _wrap_u);
316 get_bool_attribute(color,
"wrapV", _wrap_v);
318 get_vec2_attribute(color,
"repeatUV", _repeat_uv);
319 get_vec2_attribute(color,
"offset", _offset);
320 get_angle_attribute(color,
"rotateUV", _rotate_uv);
323 if (maya_cat.is_debug()) {
324 maya_cat.debug() <<
"pushed a file texture" << endl;
326 shader->_color.push_back(
this);
329 }
else if (color.hasFn(MFn::kProjection)) {
330 if (maya_cat.is_debug()) {
331 maya_cat.debug() <<
"reading a projection texture" << endl;
335 MFnDependencyNode projection_fn(color);
336 MPlug image_plug = projection_fn.findPlug(
"image");
337 if (!image_plug.isNull()) {
339 image_plug.connectedTo(image_pa,
true,
false);
341 for (
size_t i = 0; i < image_pa.length(); i++) {
342 find_textures_legacy(shader, image_pa[0].node());
346 if (!get_mat4d_attribute(color,
"placementMatrix", _projection_matrix)) {
352 if (!get_angle_attribute(color,
"uAngle", _u_angle)) {
355 if (!get_angle_attribute(color,
"vAngle", _v_angle)) {
360 if (get_enum_attribute(color,
"projType", type)) {
361 set_projection_type(type);
364 }
else if (color.hasFn(MFn::kLayeredTexture)) {
365 if (maya_cat.is_debug()) {
366 maya_cat.debug() <<
"Found layered texture" << endl;
372 MFnDependencyNode layered_fn(color);
373 layered_fn.getConnections(color_pa);
374 MPlug inputsPlug = layered_fn.findPlug(
"inputs", &status);
375 MPlug blendModePlug = layered_fn.findPlug(
"blendMode", &status);
377 if (maya_cat.is_debug()) {
378 maya_cat.debug() <<
"number of connections: " << color_pa.length() << endl;
381 BlendType bt = BT_modulate;
382 for (
size_t i=0; i<color_pa.length(); ++i) {
383 MPlug pl = color_pa[i];
385 pl.connectedTo(pla,
true,
false);
388 int li = pl.logicalIndex();
391 if (maya_cat.is_spam()) {
392 maya_cat.spam() <<
"*** Start doIt... ***" << endl;
393 maya_cat.spam() <<
"inputsPlug Name: " << inputsPlug.name() << endl;
395 status = blendModePlug.selectAncestorLogicalIndex(li,inputsPlug);
396 blendModePlug.getValue(blendValue);
398 if (maya_cat.is_spam()) {
400 << blendModePlug.name() <<
": has value " << blendValue << endl;
403 MFnEnumAttribute blendModeEnum(blendModePlug);
404 MString blendName = blendModeEnum.fieldName(blendValue, &status);
406 switch (blendValue) {
409 get_bool_attribute(color,
"interpolate", _interpolate);
410 maya_cat.info() <<
"interpolate: " << _interpolate << endl;
415 get_bool_attribute(color,
"keepAlpha", _keep_alpha);
416 maya_cat.info() <<
"keepAlpha: " << _keep_alpha << endl;
422 maya_cat.info() << layered_fn.name() <<
": blendMode used " << blendName << endl;
423 if (maya_cat.is_spam()) {
424 maya_cat.spam() <<
"*** END doIt... ***" << endl;
429 pl.connectedTo(pla,
true,
false);
431 for (
size_t j=0; j<pla.length(); ++j) {
434 string pla_name = pla[j].name().asChar();
436 if (pla_name.find(
"outAlpha") != string::npos) {
438 if (maya_cat.is_debug()) {
439 maya_cat.debug() << pl.name().asChar() <<
":has alpha channel" << pla_name << endl;
441 _has_alpha_channel =
true;
445 if (maya_cat.is_debug()) {
446 maya_cat.debug() << pl.name().asChar() <<
" next:connectedTo: " << pla_name << endl;
449 color_p->find_textures_legacy(shader, pla[j].node());
450 color_p->_blend_type = bt;
451 size_t loc = color_p->_texture_name.find(
'.',0);
452 if (loc != string::npos) {
453 color_p->_texture_name.resize(loc);
455 if (maya_cat.is_debug()) {
456 maya_cat.debug() <<
"uv_name : " << color_p->_texture_name << endl;
460 if (maya_cat.is_debug()) {
461 maya_cat.debug() << pl.name().asChar() <<
" first:connectedTo: " << pla_name << endl;
463 find_textures_legacy(shader, pla[j].node());
464 _texture_name.assign(pla[j].name().asChar());
466 size_t loc = _texture_name.find(
'.',0);
467 if (loc != string::npos) {
468 _texture_name.resize(loc);
470 if (maya_cat.is_debug()) {
471 maya_cat.debug() <<
"uv_name : " << _texture_name << endl;
479 if (maya_cat.is_debug()) {
481 <<
"**Don't know how to interpret color attribute type " 482 << color.apiTypeStr() <<
"\n";
488 if (bad_types.insert(color.apiType()).second) {
490 <<
"**Don't know how to interpret color attribute type " 491 << color.apiTypeStr() <<
"\n";
504 void MayaShaderColorDef::
505 find_textures_modern(
const string &shadername,
MayaShaderColorList &list, MPlug inplug,
bool is_alpha) {
508 inplug.connectedTo(outplugs,
true,
false);
509 if (outplugs.length() == 0) {
512 if (outplugs.length() > 1) {
515 <<
"Shader " << shadername <<
" has weird plug connections.\n";
518 MPlug outplug = outplugs[0];
519 MObject source = outplug.node();
520 MFnDependencyNode sourceFn(source);
522 if (source.hasFn(MFn::kFileTexture)) {
525 bool hasfn = get_string_attribute(source,
"fileTextureName", filename);
526 if ((!hasfn) || (filename.empty())) {
528 <<
"Shader " << shadername <<
" references file texture " 529 <<
"with no file name, ignoring invalid file texture.\n";
535 <<
"Shader " << shadername <<
" references file name " 536 << filename <<
" which is a directory, ignoring it.\n";
542 def->_color_object =
new MObject(source);
544 def->_texture_name = sourceFn.name().asChar();
546 get_vec2_attribute(source,
"coverage", def->_coverage);
547 get_vec2_attribute(source,
"translateFrame", def->_translate_frame);
548 get_angle_attribute(source,
"rotateFrame", def->_rotate_frame);
550 get_bool_attribute(source,
"mirror", def->_mirror);
551 get_bool_attribute(source,
"stagger", def->_stagger);
552 get_bool_attribute(source,
"wrapU", def->_wrap_u);
553 get_bool_attribute(source,
"wrapV", def->_wrap_v);
555 get_vec2_attribute(source,
"repeatUV", def->_repeat_uv);
556 get_vec2_attribute(source,
"offset", def->_offset);
557 get_angle_attribute(source,
"rotateUV", def->_rotate_uv);
560 PN_stdfloat alpha_gain;
561 get_vec3_attribute(source,
"colorGain", color_gain);
562 get_maya_attribute(source,
"alphaGain", alpha_gain);
563 def->_color_gain[0] = color_gain[0];
564 def->_color_gain[1] = color_gain[1];
565 def->_color_gain[2] = color_gain[2];
566 def->_color_gain[3] = alpha_gain;
568 def->_is_alpha = is_alpha;
570 if (maya_cat.is_debug()) {
571 maya_cat.debug() <<
"pushed a file texture" << endl;
578 if (source.hasFn(MFn::kProjection)) {
581 size_t before = list.size();
582 MPlug image_plug = sourceFn.findPlug(
"image");
583 if (!image_plug.isNull()) {
585 image_plug.connectedTo(image_pa,
true,
false);
587 for (
size_t i = 0; i < image_pa.length(); i++) {
588 find_textures_modern(shadername, list, image_pa[0], is_alpha);
594 for (
size_t i=before; i<list.size(); i++) {
597 if (!get_mat4d_attribute(source,
"placementMatrix", def->_projection_matrix)) {
603 if (!get_angle_attribute(source,
"uAngle", def->_u_angle)) {
604 def->_u_angle = 360.0;
606 if (!get_angle_attribute(source,
"vAngle", def->_v_angle)) {
607 def->_v_angle = 180.0;
611 if (get_enum_attribute(source,
"projType", type)) {
612 def->set_projection_type(type);
618 if (source.hasFn(MFn::kLayeredTexture)) {
619 if (maya_cat.is_debug()) {
620 maya_cat.debug() <<
"Found layered texture" << endl;
623 MPlug inputsPlug = sourceFn.findPlug(
"inputs");
624 size_t nlayers = inputsPlug.numElements();
625 for (
size_t layer=0; layer<nlayers; layer++) {
626 MPlug elt = inputsPlug.elementByPhysicalIndex(layer);
629 for (
size_t j=0; j<elt.numChildren(); j++) {
630 MPlug child = elt.child(j);
631 MFnAttribute att(child.attribute());
632 if (att.name() ==
"color") color = child;
633 if (att.name() ==
"blendMode") blend = child;
635 if (color.isNull() || blend.isNull()) {
636 maya_cat.warning() <<
"Invalid layered texture - bad inputs.\n";
639 size_t before = list.size();
640 find_textures_modern(shadername, list, color, is_alpha);
642 blend.getValue(blendValue);
643 for (
size_t sub=before; sub<list.size(); sub++) {
645 switch (blendValue) {
646 case 1: def->_blend_type = BT_decal;
break;
647 case 6: def->_blend_type = BT_modulate;
break;
648 case 4: def->_blend_type = BT_add;
break;
655 if (source.apiType() == MFn::kReverse) {
656 MPlug input_plug = sourceFn.findPlug(
"input");
657 find_textures_modern(shadername, list, input_plug, is_alpha);
662 if (maya_cat.is_debug()) {
664 <<
"**Don't know how to interpret color attribute type " 665 << source.apiTypeStr() <<
"\n";
670 if (bad_types.insert(source.apiType()).second) {
672 <<
"Don't know how to export a shader of type " 673 << source.apiTypeStr() <<
" " << sourceFn.type() <<
"\n";
684 void MayaShaderColorDef::
685 set_projection_type(
const string &type) {
686 if (cmp_nocase(type,
"planar") == 0) {
687 _projection_type = PT_planar;
688 _map_uvs = &MayaShaderColorDef::map_planar;
692 _projection_matrix = _projection_matrix *
LMatrix4d(0.5, 0.0, 0.0, 0.0,
697 }
else if (cmp_nocase(type,
"cylindrical") == 0) {
698 _projection_type = PT_cylindrical;
699 _map_uvs = &MayaShaderColorDef::map_cylindrical;
703 _projection_matrix = _projection_matrix *
LMatrix4d(1.0, 0.0, 0.0, 0.0,
708 }
else if (cmp_nocase(type,
"spherical") == 0) {
709 _projection_type = PT_spherical;
710 _map_uvs = &MayaShaderColorDef::map_spherical;
716 <<
"Don't know how to handle type " << type <<
" projections.\n";
717 _projection_type = PT_off;
748 double xz_length = xz.
length();
750 if (xz_length < 0.01) {
758 xz.set(centroid[0], centroid[2]);
764 double u = rad_2_deg(atan2(xz[0], xz[1])) / (2.0 * _u_angle);
765 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / (2.0 * _u_angle);
768 u -= floor(u - c + 0.5);
769 }
else if (u - c < -0.5) {
770 u += floor(c - u + 0.5);
776 double v = rad_2_deg(atan2(yz[0], yz[1])) / (2.0 * _v_angle);
780 nassertr(fabs(u - c) <= 0.5, uv);
796 double xz_length = xz.
length();
798 if (xz_length < 0.01) {
809 xz.set(centroid[0], centroid[2]);
813 double u = rad_2_deg(atan2(xz[0], xz[1])) / _u_angle;
814 double c = rad_2_deg(atan2(centroid[0], centroid[2])) / _u_angle;
817 u -= floor(u - c + 0.5);
818 }
else if (u - c < -0.5) {
819 u += floor(c - u + 0.5);
826 nassertr(fabs(u - c) <= 0.5, uv);
static const LPoint2d & zero()
Returns a zero-length point.
This is the base class for all three-component vectors and points.
This is a 4-by-4 transform matrix.
static LMatrix3d rotate_mat(double angle)
Returns a matrix that rotates by the given angle in degrees counterclockwise.
This is a two-component vector offset.
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...
string get_panda_uvset_name()
Maya's default uvset name is "map1".
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...
This is a two-component point in space.
static LMatrix3d translate_mat(const LVecBase2d &trans)
Returns a matrix that applies the indicated translation.
string to_os_generic() const
This is similar to to_os_specific(), but it is designed to generate a filename that can be understood...
This is our own Panda specialization on the default STL vector.
This is a 3-by-3 transform matrix.
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...
static const LMatrix4d & ident_mat()
Returns an identity matrix.
double length() const
Returns the length of the vector, by the Pythagorean theorem.
Corresponds to a single "shader" in Maya.
bool is_directory() const
Returns true if the filename exists and is a directory name, false otherwise.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
static LMatrix3d scale_mat(const LVecBase2d &scale)
Returns a matrix that applies the indicated scale in each of the two axes.
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.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).