diff --git a/panda/src/egg/eggGroupNode.I b/panda/src/egg/eggGroupNode.I index 0176d3c8bb..da0286bd51 100644 --- a/panda/src/egg/eggGroupNode.I +++ b/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; diff --git a/panda/src/egg/eggGroupNode.cxx b/panda/src/egg/eggGroupNode.cxx index 048ab11781..163f6fdacc 100644 --- a/panda/src/egg/eggGroupNode.cxx +++ b/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); diff --git a/panda/src/egg/eggGroupNode.h b/panda/src/egg/eggGroupNode.h index 374b373358..8d0186896f 100644 --- a/panda/src/egg/eggGroupNode.h +++ b/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 TBNVertexGroup; typedef pmap TBNVertexCollection; diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index 20fa57391f..56ab475e2a 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/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); diff --git a/panda/src/egg/eggVertex.cxx b/panda/src/egg/eggVertex.cxx index c6c87d89a8..83ed50f962 100644 --- a/panda/src/egg/eggVertex.cxx +++ b/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 diff --git a/panda/src/egg/eggVertex.h b/panda/src/egg/eggVertex.h index 4d7ef22d93..fa861b50d7 100644 --- a/panda/src/egg/eggVertex.h +++ b/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);