Browse Source

Add EggVertex::make_average(v1, v2)

rdb 11 years ago
parent
commit
91568b02bc

+ 119 - 0
panda/src/egg/eggVertex.cxx

@@ -398,6 +398,125 @@ clear_aux(const string &name) {
   _aux_map.erase(name);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::make_average
+//       Access: Published, Static
+//  Description: Creates a new vertex that lies in between the two
+//               given vertices.  The attributes for the UV sets
+//               they have in common are averaged.
+//
+//               Both vertices need to be either in no pool, or in
+//               the same pool.  In the latter case, the new vertex
+//               will be placed in that pool.
+///////////////////////////////////////////////////////////////////
+PT(EggVertex) EggVertex::
+make_average(const EggVertex *first, const EggVertex *second) {
+  PT(EggVertexPool) pool = first->get_pool();
+  nassertr(pool == second->get_pool(), NULL);
+
+  // If both vertices are in a pool, the new vertex will be part of
+  // the pool as well.
+  PT(EggVertex) middle;
+  if (pool == NULL) {
+    middle = new EggVertex;
+  } else {
+    middle = pool->make_new_vertex();
+  }
+
+  middle->set_pos4((first->get_pos4() + second->get_pos4()) / 2);
+
+  if (first->has_normal() && second->has_normal()) {
+    LNormald normal = (first->get_normal() + second->get_normal()) / 2;
+    normal.normalize();
+    middle->set_normal(normal);
+  }
+  if (first->has_color() && second->has_color()) {
+    middle->set_color((first->get_color() + second->get_color()) / 2);
+  }
+
+  // Average out the EggVertexUV objects, but only for the UV sets
+  // that they have in common.
+  const_uv_iterator it;
+  for (it = first->uv_begin(); it != first->uv_end(); ++it) {
+    const EggVertexUV *first_uv = it->second;
+    const EggVertexUV *second_uv = second->get_uv_obj(it->first);
+
+    if (first_uv != NULL && second_uv != NULL) {
+      middle->set_uv_obj(EggVertexUV::make_average(first_uv, second_uv));
+    }
+  }
+
+  // Same for EggVertexAux.
+  const_aux_iterator ai;
+  for (ai = first->aux_begin(); ai != first->aux_end(); ++ai) {
+    const EggVertexAux *first_aux = ai->second;
+    const EggVertexAux *second_aux = second->get_aux_obj(ai->first);
+
+    if (first_aux != NULL && second_aux != NULL) {
+      middle->set_aux_obj(EggVertexAux::make_average(first_aux, second_aux));
+    }
+  }
+
+  // Now process the morph targets.
+  EggMorphVertexList::const_iterator vi, vi2;
+  for (vi = first->_dxyzs.begin(); vi != first->_dxyzs.end(); ++vi) {
+    for (vi2 = second->_dxyzs.begin(); vi2 != second->_dxyzs.end(); ++vi2) {
+      if (vi->get_name() == vi2->get_name()) {
+        middle->_dxyzs.insert(EggMorphVertex(vi->get_name(),
+                              (vi->get_offset() + vi2->get_offset()) / 2));
+        break;
+      }
+    }
+  }
+
+  EggMorphNormalList::const_iterator ni, ni2;
+  for (ni = first->_dxyzs.begin(); ni != first->_dxyzs.end(); ++ni) {
+    for (ni2 = second->_dxyzs.begin(); ni2 != second->_dxyzs.end(); ++ni2) {
+      if (ni->get_name() == ni2->get_name()) {
+        middle->_dnormals.insert(EggMorphNormal(ni->get_name(),
+                                 (ni->get_offset() + ni2->get_offset()) / 2));
+        break;
+      }
+    }
+  }
+
+  EggMorphColorList::const_iterator ci, ci2;
+  for (ci = first->_drgbas.begin(); ci != first->_drgbas.end(); ++ci) {
+    for (ci2 = second->_drgbas.begin(); ci2 != second->_drgbas.end(); ++ci2) {
+      if (ci->get_name() == ci2->get_name()) {
+        middle->_drgbas.insert(EggMorphColor(ci->get_name(),
+                               (ci->get_offset() + ci2->get_offset()) / 2));
+        break;
+      }
+    }
+  }
+
+  // Now merge the vertex memberships.
+  GroupRef::iterator gi;
+  for (gi = first->_gref.begin(); gi != first->_gref.end(); ++gi) {
+    EggGroup *group = *gi;
+    if (second->_gref.count(group)) {
+      group->set_vertex_membership(middle,
+        (group->get_vertex_membership(first) +
+         group->get_vertex_membership(second)) / 2.);
+    } else {
+      // Hmm, unfortunate, only one of the vertices is member of this
+      // group, so we can't make an average.  We'll have to assign the
+      // only group membership we have.
+      group->set_vertex_membership(middle, group->get_vertex_membership(first));
+    }
+  }
+  // Also assign memberships to the grefs in the second vertex that
+  // aren't part of the first vertex.
+  for (gi = second->_gref.begin(); gi != second->_gref.end(); ++gi) {
+    EggGroup *group = *gi;
+    if (second->_gref.count(group) == 0) {
+      group->set_vertex_membership(middle, group->get_vertex_membership(second));
+    }
+  }
+
+  return middle;
+}
 
 ///////////////////////////////////////////////////////////////////
 //       Class : GroupRefEntry

+ 3 - 0
panda/src/egg/eggVertex.h

@@ -109,6 +109,9 @@ PUBLISHED:
   void set_aux_obj(EggVertexAux *vertex_aux);
   void clear_aux(const string &name);
 
+  static PT(EggVertex) make_average(const EggVertex *first,
+                                    const EggVertex *second);
+
 public:
   INLINE const_uv_iterator uv_begin() const;
   INLINE const_uv_iterator uv_end() const;

+ 20 - 5
panda/src/egg/eggVertexAux.cxx

@@ -22,7 +22,7 @@ TypeHandle EggVertexAux::_type_handle;
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexAux::Constructor
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexAux::
 EggVertexAux(const string &name, const LVecBase4d &aux) :
@@ -34,7 +34,7 @@ EggVertexAux(const string &name, const LVecBase4d &aux) :
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexAux::Copy Constructor
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexAux::
 EggVertexAux(const EggVertexAux &copy) :
@@ -46,7 +46,7 @@ EggVertexAux(const EggVertexAux &copy) :
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexAux::Copy Assignment Operator
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexAux &EggVertexAux::
 operator = (const EggVertexAux &copy) {
@@ -59,16 +59,31 @@ operator = (const EggVertexAux &copy) {
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexAux::Destructor
 //       Access: Published, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexAux::
 ~EggVertexAux() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexAux::make_average
+//       Access: Published, Static
+//  Description: Creates a new EggVertexAux that contains the
+//               averaged values of the two given objects.  It is
+//               an error if they don't have the same name.
+///////////////////////////////////////////////////////////////////
+PT(EggVertexAux) EggVertexAux::
+make_average(const EggVertexAux *first, const EggVertexAux *second) {
+  nassertr(first->get_name() == second->get_name(), NULL);
+
+  LVecBase4d aux = (first->_aux + second->_aux) / 2;
+  return new EggVertexAux(first->get_name(), aux);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexAux::write
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 void EggVertexAux::
 write(ostream &out, int indent_level) const {

+ 3 - 0
panda/src/egg/eggVertexAux.h

@@ -42,6 +42,9 @@ PUBLISHED:
   INLINE const LVecBase4d &get_aux() const;
   INLINE void set_aux(const LVecBase4d &aux);
 
+  static PT(EggVertexAux) make_average(const EggVertexAux *first,
+                                       const EggVertexAux *second);
+
   void write(ostream &out, int indent_level) const;
   int compare_to(const EggVertexAux &other) const;
 

+ 31 - 6
panda/src/egg/eggVertexUV.cxx

@@ -22,7 +22,7 @@ TypeHandle EggVertexUV::_type_handle;
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::Constructor
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexUV::
 EggVertexUV(const string &name, const LTexCoordd &uv) :
@@ -38,7 +38,7 @@ EggVertexUV(const string &name, const LTexCoordd &uv) :
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::Constructor
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexUV::
 EggVertexUV(const string &name, const LTexCoord3d &uvw) :
@@ -54,7 +54,7 @@ EggVertexUV(const string &name, const LTexCoord3d &uvw) :
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::Copy Constructor
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexUV::
 EggVertexUV(const EggVertexUV &copy) :
@@ -70,7 +70,7 @@ EggVertexUV(const EggVertexUV &copy) :
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::Copy Assignment Operator
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexUV &EggVertexUV::
 operator = (const EggVertexUV &copy) {
@@ -87,12 +87,37 @@ operator = (const EggVertexUV &copy) {
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::Destructor
 //       Access: Published, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 EggVertexUV::
 ~EggVertexUV() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::make_average
+//       Access: Published, Static
+//  Description: Creates a new EggVertexUV that contains the
+//               averaged values of the two given objects.  It is
+//               an error if they don't have the same name.
+///////////////////////////////////////////////////////////////////
+PT(EggVertexUV) EggVertexUV::
+make_average(const EggVertexUV *first, const EggVertexUV *second) {
+  nassertr(first->get_name() == second->get_name(), NULL);
+  int flags = first->_flags & second->_flags;
+
+  LTexCoord3d uvw = (first->_uvw + second->_uvw) / 2;
+
+  PT(EggVertexUV) new_obj = new EggVertexUV(first->get_name(), uvw);
+  new_obj->_flags = flags;
+  new_obj->_tangent = (first->_tangent + second->_tangent) / 2;
+  new_obj->_binormal = (first->_binormal + second->_binormal) / 2;
+
+  // Normalize because we're polite.
+  new_obj->_tangent.normalize();
+  new_obj->_binormal.normalize();
+  return new_obj;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::transform
 //       Access: Published, Virtual
@@ -115,7 +140,7 @@ transform(const LMatrix4d &mat) {
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::write
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 void EggVertexUV::
 write(ostream &out, int indent_level) const {

+ 3 - 0
panda/src/egg/eggVertexUV.h

@@ -57,6 +57,9 @@ PUBLISHED:
   INLINE void set_binormal(const LNormald &binormal);
   INLINE void clear_binormal();
 
+  static PT(EggVertexUV) make_average(const EggVertexUV *first,
+                                      const EggVertexUV *second);
+
   void transform(const LMatrix4d &mat);
 
   void write(ostream &out, int indent_level) const;