fix tbn to properly split vertices at a texture mirror edge

This commit is contained in:
David Rose 2005-10-05 20:19:54 +00:00
parent e53f8c7ae4
commit dc8916d350
6 changed files with 59 additions and 8 deletions

View File

@ -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 < // Function: EggGroupNode::TBNVertexValue::operator <
// Access: Public // Access: Public
@ -24,6 +34,9 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool EggGroupNode::TBNVertexValue:: bool EggGroupNode::TBNVertexValue::
operator < (const TBNVertexValue &other) const { operator < (const TBNVertexValue &other) const {
if (_facing != other._facing) {
return (int)_facing < (int)other._facing;
}
int compare = _pos.compare_to(other._pos); int compare = _pos.compare_to(other._pos);
if (compare != 0) { if (compare != 0) {
return compare < 0; return compare < 0;

View File

@ -712,8 +712,8 @@ strip_normals() {
// //
// Like recompute_vertex_normals(), this function does // Like recompute_vertex_normals(), this function does
// not remove or adjust vertices in the vertex pool; it // not remove or adjust vertices in the vertex pool; it
// only adds new vertices with the normals removed. // only adds new vertices with the new tangents and
// Thus, it is a good idea to call // binormals computed. Thus, it is a good idea to call
// remove_unused_vertices() after calling this. // remove_unused_vertices() after calling this.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void EggGroupNode:: void EggGroupNode::
@ -1782,6 +1782,14 @@ r_collect_tangent_binormal(const GlobPattern &uv_name,
TexCoordd w2 = v2->get_uv(name); TexCoordd w2 = v2->get_uv(name);
TexCoordd w3 = v3->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 x1 = p2[0] - p1[0];
double x2 = p3[0] - p1[0]; double x2 = p3[0] - p1[0];
double y1 = p2[1] - p1[1]; double y1 = p2[1] - p1[1];
@ -1867,7 +1875,7 @@ do_compute_tangent_binormal(const TBNVertexValue &value,
EggVertexPool *pool = vertex->get_pool(); EggVertexPool *pool = vertex->get_pool();
EggVertex new_vertex(*vertex); 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); nassertv(uv_obj != (EggVertexUV *)NULL);
uv_obj->set_tangent(tangent); uv_obj->set_tangent(tangent);
uv_obj->set_binormal(binormal); uv_obj->set_binormal(binormal);

View File

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

View File

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

View File

@ -223,9 +223,12 @@ set_uvw(const string &name, const TexCoord3d &uvw) {
// Access: Published // Access: Published
// Description: Returns the named EggVertexUV object, which defines // Description: Returns the named EggVertexUV object, which defines
// both the UV coordinate pair for this name and the UV // 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 { get_uv_obj(const string &name) const {
UVMap::const_iterator ui = _uv_map.find(name); UVMap::const_iterator ui = _uv_map.find(name);
if (ui != _uv_map.end()) { if (ui != _uv_map.end()) {
@ -234,6 +237,28 @@ get_uv_obj(const string &name) const {
return NULL; 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 // Function: EggVertex::set_uv_obj
// Access: Published // Access: Published

View File

@ -91,7 +91,8 @@ PUBLISHED:
const TexCoord3d &get_uvw(const string &name) const; const TexCoord3d &get_uvw(const string &name) const;
void set_uv(const string &name, const TexCoordd &texCoord); void set_uv(const string &name, const TexCoordd &texCoord);
void set_uvw(const string &name, const TexCoord3d &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 set_uv_obj(EggVertexUV *vertex_uv);
void clear_uv(const string &name); void clear_uv(const string &name);