Browse Source

implement cylindrical projections

David Rose 23 years ago
parent
commit
38057f46b2

+ 39 - 6
pandatool/src/maya/mayaShader.cxx

@@ -131,16 +131,39 @@ has_projection() const {
 //       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.
+//               corresponding to the indicated 3-d point.  Seams that
+//               might be introduced on polygons that cross quadrants
+//               are closed up by ensuring the point is in the same
+//               quadrant as the indicated reference point.
 ////////////////////////////////////////////////////////////////////
 TexCoordd MayaShader::
-project_uv(const LPoint3d &point) const {
+project_uv(const LPoint3d &point, const LPoint3d &ref_point) const {
+  LPoint3d p = point * _projection_matrix;
+
   switch (_projection_type) {
   case PT_planar:
+    return TexCoordd(p[0], p[1]);
+
+  case PT_cylindrical:
     {
-      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);
+      LPoint3d rp = ref_point * _projection_matrix;
+
+      TexCoordd uv
+        (// The u position is the angle about the Y axis, scaled to 0 .. 1.
+         catan2(p[0], p[2]) / (2.0 * MathNumbers::pi) + 0.5,
+         // The v position is the Y height.
+         p[1]);
+
+      // Also convert the reference point, so we can adjust the
+      // quadrant if necessary; each single polygon should only go the
+      // short way around the cylinder.
+      double ref_u = catan2(rp[0], rp[1]) / (2.0 * MathNumbers::pi) + 0.5;
+      if (uv[0] - ref_u > 0.5) {
+        uv[0] -= 1.0;
+      } else if (uv[0] - ref_u < -0.5) {
+        uv[0] += 1.0;
+      }
+      return uv;
     }
 
   default:
@@ -351,9 +374,19 @@ set_projection_type(const string &type) {
     // 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.0, 0.0, 1.0, 0.0,
                                                         0.5, 0.5, 0.0, 1.0);
 
+  } else if (cmp_nocase(type, "cylindrical") == 0) {
+    _projection_type = PT_cylindrical;
+
+    // The cylindrical projection is orthographic in the Y axis; scale
+    // the range (-1, 1) in this axis into our UV range (0, 1).
+    _projection_matrix = _projection_matrix * LMatrix4d(1.0, 0.0, 0.0, 0.0,
+                                                        0.0, 0.5, 0.0, 0.0,
+                                                        0.0, 0.0, 1.0, 0.0,
+                                                        0.0, 0.5, 0.0, 1.0);
+
   } else {
     // Other projection types are currently unimplemented by the
     // converter.

+ 1 - 1
pandatool/src/maya/mayaShader.h

@@ -41,7 +41,7 @@ public:
 
   LMatrix3d compute_texture_matrix() const;
   bool has_projection() const;
-  TexCoordd project_uv(const LPoint3d &point) const;
+  TexCoordd project_uv(const LPoint3d &point, const LPoint3d &ref_point) const;
 
   void output(ostream &out) const;
   bool reset_maya_texture(const Filename &texture);

+ 10 - 1
pandatool/src/mayaegg/mayaToEggConverter.cxx

@@ -1309,11 +1309,20 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
 
     // Get the vertices for the polygon.
     long num_verts = pi.polygonVertexCount();
+    LPoint3d ref_p3d;
     for (long i = 0; i < num_verts; i++) {
       EggVertex vert;
 
       MPoint p = pi.point(i, MSpace::kWorld);
       LPoint3d p3d(p[0], p[1], p[2]);
+      if (i == 0) {
+        // Save the first vertex of the polygon as a reference point
+        // for sealing up seams that might be introduced by a UV
+        // projection, so we can ensure that all the vertices are
+        // projected into the same quadrant.
+        ref_p3d = p3d;
+      }
+
       vert.set_pos(p3d);
 
       MVector n;
@@ -1327,7 +1336,7 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
       if (shader != (MayaShader *)NULL && 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));
+        vert.set_uv(shader->project_uv(p3d, ref_p3d));
 
       } else if (pi.hasUVs()) {
         // Get the UV's from the polygon.