Kaynağa Gözat

fix tbn to properly split vertices at a texture mirror edge

David Rose 20 yıl önce
ebeveyn
işleme
dc8916d350

+ 13 - 0
panda/src/egg/eggGroupNode.I

@@ -17,6 +17,16 @@
 ////////////////////////////////////////////////////////////////////
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroupNode::is_right
+//       Access: Private, Static
+//  Description: Returns true if the 2-d v1 is to the right of v2.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggGroupNode::
+is_right(const LVector2d &v1, const LVector2d &v2) {
+  return (-v1[0] * v2[1] + v1[1] * v2[0]) > 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggGroupNode::TBNVertexValue::operator <
 //       Access: Public
@@ -24,6 +34,9 @@
 ////////////////////////////////////////////////////////////////////
 bool EggGroupNode::TBNVertexValue::
 operator < (const TBNVertexValue &other) const {
+  if (_facing != other._facing) {
+    return (int)_facing < (int)other._facing;
+  }
   int compare = _pos.compare_to(other._pos);
   if (compare != 0) {
     return compare < 0;

+ 12 - 4
panda/src/egg/eggGroupNode.cxx

@@ -712,8 +712,8 @@ strip_normals() {
 //
 //               Like recompute_vertex_normals(), this function does
 //               not remove or adjust vertices in the vertex pool; it
-//               only adds new vertices with the normals removed.
-//               Thus, it is a good idea to call
+//               only adds new vertices with the new tangents and
+//               binormals computed.  Thus, it is a good idea to call
 //               remove_unused_vertices() after calling this.
 ////////////////////////////////////////////////////////////////////
 void EggGroupNode::
@@ -1781,7 +1781,15 @@ r_collect_tangent_binormal(const GlobPattern &uv_name,
               TexCoordd w1 = v1->get_uv(name);
               TexCoordd w2 = v2->get_uv(name);
               TexCoordd w3 = v3->get_uv(name);
-              
+
+              // Check the facing of the texture; we will have to
+              // split vertices whose UV's are mirrored along a seam.
+              // The facing is determined by the winding order of the
+              // texcoords on the polygon.  A front-facing polygon
+              // should not contribute to the tangent and binormal of
+              // a back-facing polygon, and vice-versa.
+	      value._facing = is_right(w1 - w2, w3 - w1);
+
               double x1 = p2[0] - p1[0];
               double x2 = p3[0] - p1[0];
               double y1 = p2[1] - p1[1];
@@ -1867,7 +1875,7 @@ do_compute_tangent_binormal(const TBNVertexValue &value,
     EggVertexPool *pool = vertex->get_pool();
 
     EggVertex new_vertex(*vertex);
-    EggVertexUV *uv_obj = new_vertex.get_uv_obj(value._uv_name);
+    EggVertexUV *uv_obj = new_vertex.modify_uv_obj(value._uv_name);
     nassertv(uv_obj != (EggVertexUV *)NULL);
     uv_obj->set_tangent(tangent);
     uv_obj->set_binormal(binormal);

+ 4 - 0
panda/src/egg/eggGroupNode.h

@@ -175,6 +175,9 @@ protected:
   bool r_load_externals(const DSearchPath &searchpath, 
                         CoordinateSystem coordsys);
 
+private:
+  INLINE static bool is_right(const LVector2d &v1, const LVector2d &v2);
+
 private:
   Children _children;
   const_iterator _gnc_iterator;
@@ -214,6 +217,7 @@ private:
     Normald _normal;
     string _uv_name;
     TexCoordd _uv;
+    bool _facing;
   };
   typedef pvector<TBNVertexReference> TBNVertexGroup;
   typedef pmap<TBNVertexValue, TBNVertexGroup> TBNVertexCollection;

+ 1 - 1
panda/src/egg/eggPrimitive.cxx

@@ -1065,7 +1065,7 @@ r_apply_texmats(EggTextureCollection &textures) {
       for (size_t i = 0; i < num_vertices; i++) {
         EggVertex *vertex = get_vertex(i);
 
-        EggVertexUV *uv_obj = vertex->get_uv_obj(uv_name);
+        const EggVertexUV *uv_obj = vertex->get_uv_obj(uv_name);
         if (uv_obj != (EggVertexUV *)NULL) {
           EggVertex new_vertex(*vertex);
           PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj);

+ 27 - 2
panda/src/egg/eggVertex.cxx

@@ -223,9 +223,12 @@ set_uvw(const string &name, const TexCoord3d &uvw) {
 //       Access: Published
 //  Description: Returns the named EggVertexUV object, which defines
 //               both the UV coordinate pair for this name and the UV
-//               morphs.
+//               morphs.  This object might be shared between multiple
+//               vertices.  You should not attempt to modify this
+//               object; instead, call modify_uv_object to return a
+//               modifiable pointer.
 ////////////////////////////////////////////////////////////////////
-EggVertexUV *EggVertex::
+const EggVertexUV *EggVertex::
 get_uv_obj(const string &name) const {
   UVMap::const_iterator ui = _uv_map.find(name);
   if (ui != _uv_map.end()) {
@@ -234,6 +237,28 @@ get_uv_obj(const string &name) const {
   return NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::modify_uv_obj
+//       Access: Published
+//  Description: Returns a modifiable pointer to the named EggVertexUV
+//               object, which defines both the UV coordinate pair for
+//               this name and the UV morphs.  Returns NULL if there
+//               is no such named UV object.
+////////////////////////////////////////////////////////////////////
+EggVertexUV *EggVertex::
+modify_uv_obj(const string &name) {
+  UVMap::iterator ui = _uv_map.find(name);
+  if (ui != _uv_map.end()) {
+    if ((*ui).second->get_ref_count() != 1) {
+      // Copy on write.
+      (*ui).second = new EggVertexUV(*(*ui).second);
+    }
+    return (*ui).second;
+  }
+
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::set_uv_obj
 //       Access: Published

+ 2 - 1
panda/src/egg/eggVertex.h

@@ -91,7 +91,8 @@ PUBLISHED:
   const TexCoord3d &get_uvw(const string &name) const;
   void set_uv(const string &name, const TexCoordd &texCoord);
   void set_uvw(const string &name, const TexCoord3d &texCoord);
-  EggVertexUV *get_uv_obj(const string &name) const;
+  const EggVertexUV *get_uv_obj(const string &name) const;
+  EggVertexUV *modify_uv_obj(const string &name);
   void set_uv_obj(EggVertexUV *vertex_uv);
   void clear_uv(const string &name);