Răsfoiți Sursa

support projected textures

David Rose 23 ani în urmă
părinte
comite
81006f1eb4

+ 8 - 0
pandatool/src/maya/mayaApi.cxx

@@ -43,6 +43,9 @@ MayaApi::
 MayaApi(const string &program_name) {
 MayaApi(const string &program_name) {
   // Beginning with Maya4.5, the call to initialize seems to change
   // Beginning with Maya4.5, the call to initialize seems to change
   // the current directory!  Yikes!
   // the current directory!  Yikes!
+
+  // Furthermore, the current directory may change during the call to
+  // any Maya function!  Egad!
   Filename cwd = ExecutionEnvironment::get_cwd();
   Filename cwd = ExecutionEnvironment::get_cwd();
   MStatus stat = MLibrary::initialize((char *)program_name.c_str());
   MStatus stat = MLibrary::initialize((char *)program_name.c_str());
   
   
@@ -52,6 +55,11 @@ MayaApi(const string &program_name) {
     maya_cat.warning()
     maya_cat.warning()
       << "Unable to restore current directory to " << cwd
       << "Unable to restore current directory to " << cwd
       << " after initializing Maya.\n";
       << " after initializing Maya.\n";
+  } else {
+    if (maya_cat.is_debug()) {
+      maya_cat.debug()
+        << "Restored current directory to " << cwd << "\n";
+    }
   }
   }
 
 
   if (!stat) {
   if (!stat) {

+ 99 - 4
pandatool/src/maya/mayaShader.cxx

@@ -19,6 +19,7 @@
 #include "mayaShader.h"
 #include "mayaShader.h"
 #include "maya_funcs.h"
 #include "maya_funcs.h"
 #include "config_maya.h"
 #include "config_maya.h"
+#include "string_utils.h"
 #include "pset.h"
 #include "pset.h"
 
 
 #include "pre_maya_include.h"
 #include "pre_maya_include.h"
@@ -43,6 +44,7 @@ MayaShader(MObject engine) {
   _transparency = 0.0;
   _transparency = 0.0;
 
 
   _has_texture = false;
   _has_texture = false;
+  _projection_type = PT_off;
 
 
   _coverage.set(1.0, 1.0);
   _coverage.set(1.0, 1.0);
   _translate_frame.set(0.0, 0.0);
   _translate_frame.set(0.0, 0.0);
@@ -114,6 +116,38 @@ compute_texture_matrix() const {
     LMatrix3d::translate_mat(trans);
     LMatrix3d::translate_mat(trans);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MayaShader::has_projection
+//       Access: Public
+//  Description: Returns true if the shader has a projection in effect.
+////////////////////////////////////////////////////////////////////
+bool MayaShader::
+has_projection() const {
+  return (_projection_type != PT_off);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaShader::project_uv
+//       Access: Public
+//  Description: If the shader has a projection (has_projection()
+//               returns true), this computes the appropriate UV
+//               corresponding to the indicated 3-d point.
+////////////////////////////////////////////////////////////////////
+TexCoordd MayaShader::
+project_uv(const LPoint3d &point) const {
+  switch (_projection_type) {
+  case PT_planar:
+    {
+      LPoint3d p2d = point * _projection_matrix;
+      return TexCoordd(p2d[0], p2d[1]);
+      //return TexCoordd((p2d[0] + 1.0) / 2.0, (p2d[1] + 1.0) / 2.0);
+    }
+
+  default:
+    return TexCoordd(0.0, 0.0);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MayaShader::output
 //     Function: MayaShader::output
 //       Access: Public
 //       Access: Public
@@ -168,7 +202,7 @@ reset_maya_texture(const Filename &texture) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MayaShader::read_surface_shader
 //     Function: MayaShader::read_surface_shader
-//       Access: Public
+//       Access: Private
 //  Description: Extracts out the shading information from the Maya
 //  Description: Extracts out the shading information from the Maya
 //               surface shader.
 //               surface shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -196,6 +230,19 @@ read_surface_shader(MObject shader) {
     }
     }
   }
   }
 
 
+  // Or maybe a connection to outColor.  Not sure how this differs
+  // from just color, but empirically it seems that either might be
+  // used.
+  MPlug out_color_plug = shader_fn.findPlug("outColor");
+  if (!out_color_plug.isNull()) {
+    MPlugArray color_pa;
+    out_color_plug.connectedTo(color_pa, true, false);
+
+    for (size_t i = 0; i < color_pa.length(); i++) {
+      read_surface_color(color_pa[0].node());
+    }
+  }
+
   // Also try to get the ordinary color directly from the surface
   // Also try to get the ordinary color directly from the surface
   // shader.
   // shader.
   if (shader.hasFn(MFn::kLambert)) {
   if (shader.hasFn(MFn::kLambert)) {
@@ -218,16 +265,15 @@ read_surface_shader(MObject shader) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MayaShader::read_surface_color
 //     Function: MayaShader::read_surface_color
-//       Access: Public
+//       Access: Private
 //  Description: Determines the surface color specified by the shader.
 //  Description: Determines the surface color specified by the shader.
 //               This includes texturing and other advanced shader
 //               This includes texturing and other advanced shader
 //               properties.
 //               properties.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void MayaShader::
 void MayaShader::
 read_surface_color(MObject color) {
 read_surface_color(MObject color) {
-  _color_object = new MObject(color);
-
   if (color.hasFn(MFn::kFileTexture)) {
   if (color.hasFn(MFn::kFileTexture)) {
+    _color_object = new MObject(color);
     string filename;
     string filename;
     _has_texture = get_string_attribute(color, "fileTextureName", filename);
     _has_texture = get_string_attribute(color, "fileTextureName", filename);
     if (_has_texture) {
     if (_has_texture) {
@@ -247,6 +293,29 @@ read_surface_color(MObject color) {
     get_vec2f_attribute(color, "offset", _offset);
     get_vec2f_attribute(color, "offset", _offset);
     get_angle_attribute(color, "rotateUV", _rotate_uv);
     get_angle_attribute(color, "rotateUV", _rotate_uv);
 
 
+  } else if (color.hasFn(MFn::kProjection)) {
+    // This is a projected texture.  We will have to step one level
+    // deeper to find the actual texture.
+    MFnDependencyNode projection_fn(color);
+    MPlug image_plug = projection_fn.findPlug("image");
+    if (!image_plug.isNull()) {
+      MPlugArray image_pa;
+      image_plug.connectedTo(image_pa, true, false);
+      
+      for (size_t i = 0; i < image_pa.length(); i++) {
+        read_surface_color(image_pa[0].node());
+      }
+    }
+
+    if (!get_mat4d_attribute(color, "placementMatrix", _projection_matrix)) {
+      _projection_matrix = LMatrix4d::ident_mat();
+    }
+
+    string type;
+    if (get_enum_attribute(color, "projType", type)) {
+      set_projection_type(type);
+    }
+
   } else {
   } else {
     // This shader wasn't understood.
     // This shader wasn't understood.
     if (maya_cat.is_debug()) {
     if (maya_cat.is_debug()) {
@@ -266,3 +335,29 @@ read_surface_color(MObject color) {
     }
     }
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaShader::set_projection_type
+//       Access: Private
+//  Description: Sets up the shader to apply UV's according to the
+//               indicated projection type.
+////////////////////////////////////////////////////////////////////
+void MayaShader::
+set_projection_type(const string &type) {
+  if (cmp_nocase(type, "planar") == 0) {
+    _projection_type = PT_planar;
+
+    // The Planar projection normally projects to a range (-1, 1) in
+    // both axes.  Scale this into our UV range of (0, 1).
+    _projection_matrix = _projection_matrix * LMatrix4d(0.5, 0.0, 0.0, 0.0,
+                                                        0.0, 0.5, 0.0, 0.0,
+                                                        0.0, 0.0, 0.5, 0.0,
+                                                        0.5, 0.5, 0.0, 1.0);
+
+  } else {
+    // Other projection types are currently unimplemented by the
+    // converter.
+    maya_cat.error()
+      << "Don't know how to handle type " << type << " projections.\n";
+  }
+}

+ 17 - 0
pandatool/src/maya/mayaShader.h

@@ -40,6 +40,8 @@ public:
   ~MayaShader();
   ~MayaShader();
 
 
   LMatrix3d compute_texture_matrix() const;
   LMatrix3d compute_texture_matrix() const;
+  bool has_projection() const;
+  TexCoordd project_uv(const LPoint3d &point) const;
 
 
   void output(ostream &out) const;
   void output(ostream &out) const;
   bool reset_maya_texture(const Filename &texture);
   bool reset_maya_texture(const Filename &texture);
@@ -53,6 +55,20 @@ public:
   bool _has_texture;
   bool _has_texture;
   Filename _texture;
   Filename _texture;
 
 
+  enum ProjectionType {
+    PT_off,
+    PT_planar,
+    PT_spherical,
+    PT_cylindrical,
+    PT_ball,
+    PT_cubic,
+    PT_triplanar,
+    PT_concentric,
+    PT_perspective,
+  };
+  ProjectionType _projection_type;
+  LMatrix4d _projection_matrix;
+
   LVector2f _coverage;
   LVector2f _coverage;
   LVector2f _translate_frame;
   LVector2f _translate_frame;
   double _rotate_frame;
   double _rotate_frame;
@@ -71,6 +87,7 @@ private:
 
 
   bool read_surface_shader(MObject shader);
   bool read_surface_shader(MObject shader);
   void read_surface_color(MObject color);
   void read_surface_color(MObject color);
+  void set_projection_type(const string &type);
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const MayaShader &shader) {
 INLINE ostream &operator << (ostream &out, const MayaShader &shader) {

+ 61 - 0
pandatool/src/maya/maya_funcs.cxx

@@ -30,6 +30,8 @@
 #include <maya/MFnAttribute.h>
 #include <maya/MFnAttribute.h>
 #include <maya/MFnTypedAttribute.h>
 #include <maya/MFnTypedAttribute.h>
 #include <maya/MFnEnumAttribute.h>
 #include <maya/MFnEnumAttribute.h>
+#include <maya/MFnMatrixData.h>
+#include <maya/MMatrix.h>
 #include "post_maya_include.h"
 #include "post_maya_include.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -66,6 +68,29 @@ get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug) {
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: has_attribute
+//  Description: Returns true if the node has the indicated attribute,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool
+has_attribute(MObject &node, const string &attribute_name) { 
+  MStatus status;
+  MFnDependencyNode node_fn(node, &status);
+  if (!status) {
+    maya_cat.error()
+      << "Object is a " << node.apiTypeStr() << ", not a DependencyNode.\n";
+    return false;
+  }
+
+  node_fn.attribute(attribute_name.c_str(), &status);
+  if (!status) {
+    // No such attribute.
+    return false;
+  }
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: get_bool_attribute
 //     Function: get_bool_attribute
 //  Description: Extracts the named boolean attribute from the
 //  Description: Extracts the named boolean attribute from the
@@ -74,6 +99,12 @@ get_maya_plug(MObject &node, const string &attribute_name, MPlug &plug) {
 bool
 bool
 get_bool_attribute(MObject &node, const string &attribute_name,
 get_bool_attribute(MObject &node, const string &attribute_name,
                    bool &value) {
                    bool &value) {
+  if (!has_attribute(node, attribute_name)) {
+    // For bool attributes only, we assume if the attribute is absent
+    // it's the same thing as being false.
+    return false;
+  }
+
   if (!get_maya_attribute(node, attribute_name, value)) {
   if (!get_maya_attribute(node, attribute_name, value)) {
     maya_cat.error()
     maya_cat.error()
       << "Attribute " << attribute_name
       << "Attribute " << attribute_name
@@ -178,6 +209,36 @@ get_vec2d_attribute(MObject &node, const string &attribute_name,
   return true;
   return true;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: get_mat4d_attribute
+//  Description: Extracts the named 4x4 matrix from the MObject.
+////////////////////////////////////////////////////////////////////
+bool
+get_mat4d_attribute(MObject &node, const string &attribute_name,
+                    LMatrix4d &value) {
+  MStatus status;
+  MObject matrix;
+  if (!get_maya_attribute(node, attribute_name, matrix)) {
+    return false;
+  }
+
+  MFnMatrixData matrix_data(matrix, &status);
+  if (!status) {
+    maya_cat.error()
+      << "Attribute " << attribute_name << " is of type "
+      << node.apiTypeStr() << ", not a Matrix.\n";
+    return false;
+  }
+    
+  const MMatrix &mat = matrix_data.matrix();
+  for (int i = 0; i < 4; i++) {
+    for (int j = 0; j < 4; j++) {
+      value(i, j) = mat(i, j);
+    }
+  }
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: get_enum_attribute
 //     Function: get_enum_attribute
 //  Description: Extracts the enum attribute from the MObject as a
 //  Description: Extracts the enum attribute from the MObject as a

+ 7 - 0
pandatool/src/maya/maya_funcs.h

@@ -48,6 +48,9 @@ bool
 set_maya_attribute(MObject &node, const string &attribute_name,
 set_maya_attribute(MObject &node, const string &attribute_name,
                    ValueType &value);
                    ValueType &value);
 
 
+bool
+has_attribute(MObject &node, const string &attribute_name);
+
 bool
 bool
 get_bool_attribute(MObject &node, const string &attribute_name,
 get_bool_attribute(MObject &node, const string &attribute_name,
                    bool &value);
                    bool &value);
@@ -64,6 +67,10 @@ bool
 get_vec2d_attribute(MObject &node, const string &attribute_name,
 get_vec2d_attribute(MObject &node, const string &attribute_name,
                     LVecBase2d &value);
                     LVecBase2d &value);
 
 
+bool
+get_mat4d_attribute(MObject &node, const string &attribute_name,
+                    LMatrix4d &value);
+
 bool
 bool
 get_enum_attribute(MObject &node, const string &attribute_name,
 get_enum_attribute(MObject &node, const string &attribute_name,
                    string &value);
                    string &value);

+ 28 - 17
pandatool/src/mayaegg/mayaToEggConverter.cxx

@@ -1209,12 +1209,29 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
 
 
     egg_poly->set_bface_flag(double_sided);
     egg_poly->set_bface_flag(double_sided);
 
 
+    // Determine the shader for this particular polygon.
+    MayaShader *shader = NULL;
+    int index = pi.index();
+    nassertv(index >= 0 && index < (int)poly_shader_indices.length());
+    int shader_index = poly_shader_indices[index];
+    if (shader_index != -1) {
+      nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
+      MObject engine = shaders[shader_index];
+      shader =
+        _shaders.find_shader_for_shading_engine(engine);
+
+    } else if (default_shader != (MayaShader *)NULL) {
+      shader = default_shader;
+    }
+
+    // Get the vertices for the polygon.
     long num_verts = pi.polygonVertexCount();
     long num_verts = pi.polygonVertexCount();
     for (long i = 0; i < num_verts; i++) {
     for (long i = 0; i < num_verts; i++) {
       EggVertex vert;
       EggVertex vert;
 
 
       MPoint p = pi.point(i, MSpace::kWorld);
       MPoint p = pi.point(i, MSpace::kWorld);
-      vert.set_pos(LPoint3d(p[0], p[1], p[2]));
+      LPoint3d p3d(p[0], p[1], p[2]);
+      vert.set_pos(p3d);
 
 
       MVector n;
       MVector n;
       status = pi.getNormal(i, n, MSpace::kWorld);
       status = pi.getNormal(i, n, MSpace::kWorld);
@@ -1224,7 +1241,13 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
         vert.set_normal(LVector3d(n[0], n[1], n[2]));
         vert.set_normal(LVector3d(n[0], n[1], n[2]));
       }
       }
 
 
-      if (pi.hasUVs()) {
+      if (shader->has_projection()) {
+        // If the shader has a projection, use it instead of the
+        // polygon's built-in UV's.
+        vert.set_uv(shader->project_uv(p3d));
+
+      } else if (pi.hasUVs()) {
+        // Get the UV's from the polygon.
         float2 uvs;
         float2 uvs;
         status = pi.getUV(i, uvs);
         status = pi.getUV(i, uvs);
         if (!status) {
         if (!status) {
@@ -1249,21 +1272,9 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
       egg_poly->add_vertex(vpool->create_unique_vertex(vert));
       egg_poly->add_vertex(vpool->create_unique_vertex(vert));
     }
     }
 
 
-    // Determine the shader for this particular polygon.
-    int index = pi.index();
-    nassertv(index >= 0 && index < (int)poly_shader_indices.length());
-    int shader_index = poly_shader_indices[index];
-    if (shader_index != -1) {
-      nassertv(shader_index >= 0 && shader_index < (int)shaders.length());
-      MObject engine = shaders[shader_index];
-      MayaShader *shader =
-        _shaders.find_shader_for_shading_engine(engine);
-      if (shader != (MayaShader *)NULL) {
-        set_shader_attributes(*egg_poly, *shader);
-      }
-
-    } else if (default_shader != (MayaShader *)NULL) {
-      set_shader_attributes(*egg_poly, *default_shader);
+    // Now apply the shader.
+    if (shader != (MayaShader *)NULL) {
+      set_shader_attributes(*egg_poly, *shader);
     }
     }
 
 
     pi.next();
     pi.next();

+ 8 - 0
pandatool/src/mayaprogs/mayaToEgg.cxx

@@ -19,6 +19,7 @@
 #include "mayaToEgg.h"
 #include "mayaToEgg.h"
 #include "mayaToEggConverter.h"
 #include "mayaToEggConverter.h"
 #include "config_mayaegg.h"
 #include "config_mayaegg.h"
+#include "config_maya.h"  // for maya_cat
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MayaToEgg::Constructor
 //     Function: MayaToEgg::Constructor
@@ -78,13 +79,20 @@ void MayaToEgg::
 run() {
 run() {
   // Set the verbose level by using Notify.
   // Set the verbose level by using Notify.
   if (_verbose >= 3) {
   if (_verbose >= 3) {
+    maya_cat->set_severity(NS_spam);
     mayaegg_cat->set_severity(NS_spam);
     mayaegg_cat->set_severity(NS_spam);
   } else if (_verbose >= 2) {
   } else if (_verbose >= 2) {
+    maya_cat->set_severity(NS_debug);
     mayaegg_cat->set_severity(NS_debug);
     mayaegg_cat->set_severity(NS_debug);
   } else if (_verbose >= 1) {
   } else if (_verbose >= 1) {
+    maya_cat->set_severity(NS_info);
     mayaegg_cat->set_severity(NS_info);
     mayaegg_cat->set_severity(NS_info);
   }
   }
 
 
+  // Let's open the output file before we initialize Maya, since Maya
+  // now has a nasty habit of changing the current directory.
+  get_output();
+
   nout << "Initializing Maya.\n";
   nout << "Initializing Maya.\n";
   MayaToEggConverter converter(_program_name);
   MayaToEggConverter converter(_program_name);
   if (!converter.open_api()) {
   if (!converter.open_api()) {

+ 2 - 1
pandatool/src/progbase/withOutputFile.cxx

@@ -17,8 +17,9 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "withOutputFile.h"
 #include "withOutputFile.h"
+#include "executionEnvironment.h"
 
 
-#include <notify.h>
+#include "notify.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: WithOutputFile::Constructor
 //     Function: WithOutputFile::Constructor