From 38057f46b25c508c7bb733917e1cee16908e79ef Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 13 Mar 2003 17:29:41 +0000 Subject: [PATCH] implement cylindrical projections --- pandatool/src/maya/mayaShader.cxx | 45 +++++++++++++++++--- pandatool/src/maya/mayaShader.h | 2 +- pandatool/src/mayaegg/mayaToEggConverter.cxx | 11 ++++- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/pandatool/src/maya/mayaShader.cxx b/pandatool/src/maya/mayaShader.cxx index fad88f2b37..9fc3f8d73b 100644 --- a/pandatool/src/maya/mayaShader.cxx +++ b/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. diff --git a/pandatool/src/maya/mayaShader.h b/pandatool/src/maya/mayaShader.h index 96a5cc190f..a663192225 100644 --- a/pandatool/src/maya/mayaShader.h +++ b/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); diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index 0a14e81337..26c13203a9 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/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.