Browse Source

support quantizing memberships

David Rose 22 years ago
parent
commit
0f87a88945

+ 2 - 1
pandatool/src/egg-optchar/Sources.pp

@@ -13,6 +13,7 @@
   #define SOURCES \
     config_egg_optchar.cxx config_egg_optchar.h \
     eggOptchar.cxx eggOptchar.h \
-    eggOptcharUserData.I eggOptcharUserData.cxx eggOptcharUserData.h
+    eggOptcharUserData.I eggOptcharUserData.cxx eggOptcharUserData.h \
+    vertexMembership.I vertexMembership.cxx vertexMembership.h
 
 #end bin_target

+ 120 - 1
pandatool/src/egg-optchar/eggOptchar.cxx

@@ -18,16 +18,21 @@
 
 #include "eggOptchar.h"
 #include "eggOptcharUserData.h"
+#include "vertexMembership.h"
 
-#include "dcast.h"
 #include "eggJointData.h"
 #include "eggSliderData.h"
 #include "eggCharacterCollection.h"
 #include "eggCharacterData.h"
 #include "eggBackPointer.h"
+#include "eggGroupNode.h"
+#include "eggVertexPool.h"
 #include "string_utils.h"
+#include "dcast.h"
 #include "pset.h"
 
+#include <algorithm>
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggOptchar::Constructor
 //       Access: Public
@@ -83,6 +88,16 @@ EggOptchar() {
      "is recomputed appropriately under its new parent so that the animation "
      "is not affected (the effect is similar to NodePath::wrt_reparent_to).",
      &EggOptchar::dispatch_vector_string_pair, NULL, &_reparent_joints);
+
+  add_option
+    ("q", "quantum", 0,
+     "Quantize joint membership values to the given unit.  This is "
+     "the smallest significant change in joint membership.  The "
+     "default is 0.01; specifying 0 means to preserve the original "
+     "values.",
+     &EggOptchar::dispatch_double, NULL, &_vref_quantum);
+
+  _vref_quantum = 0.01;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -139,6 +154,11 @@ run() {
       do_reparent();
     }
 
+    // Quantize the vertex memberships.  We call this even if
+    // _vref_quantum is 0, because this also normalizes the vertex
+    // memberships.
+    quantize_vertices();
+
     // We currently do not implement optimizing morph sliders.  Need
     // to add this at some point; it's quite easy.  Identity and empty
     // morph sliders can simply be removed, while static sliders need
@@ -633,6 +653,105 @@ do_reparent() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggOptchar::quantize_vertices
+//       Access: Private
+//  Description: Walks through all of the loaded egg files, looking
+//               for vertices whose joint memberships are then
+//               quantized according to _vref_quantum.
+////////////////////////////////////////////////////////////////////
+void EggOptchar::
+quantize_vertices() {
+  Eggs::iterator ei;
+  for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
+    quantize_vertices(*ei);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggOptchar::quantize_vertices
+//       Access: Private
+//  Description: Recursively walks through the indicated egg
+//               hierarchy, looking for vertices whose joint
+//               memberships are then quantized according to
+//               _vref_quantum.
+////////////////////////////////////////////////////////////////////
+void EggOptchar::
+quantize_vertices(EggNode *egg_node) {
+  if (egg_node->is_of_type(EggVertexPool::get_class_type())) {
+    EggVertexPool *vpool = DCAST(EggVertexPool, egg_node);
+    EggVertexPool::iterator vi;
+    for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
+      quantize_vertex(*vi);
+    }
+    
+  } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
+    EggGroupNode *group = DCAST(EggGroupNode, egg_node);
+    EggGroupNode::iterator ci;
+    for (ci = group->begin(); ci != group->end(); ++ci) {
+      quantize_vertices(*ci);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggOptchar::quantize_vertex
+//       Access: Private
+//  Description: Quantizes the indicated vertex's joint membership.
+////////////////////////////////////////////////////////////////////
+void EggOptchar::
+quantize_vertex(EggVertex *egg_vertex) {
+  if (egg_vertex->gref_size() == 0) {
+    // Never mind on this vertex.
+    return;
+  }
+
+  // First, get a copy of the existing membership.
+  VertexMemberships memberships;
+  EggVertex::GroupRef::const_iterator gi;
+  double net_membership = 0.0;
+  for (gi = egg_vertex->gref_begin(); gi != egg_vertex->gref_end(); ++gi) {
+    EggGroup *group = (*gi);
+    double membership = group->get_vertex_membership(egg_vertex);
+    memberships.push_back(VertexMembership(group, membership));
+    net_membership += membership;
+  }
+  nassertv(net_membership != 0.0);
+
+  // Now normalize all the memberships so the net membership is 1.0,
+  // and then quantize the result (if the user so requested).
+  double factor = 1.0 / net_membership;
+  net_membership = 0.0;
+  VertexMemberships::iterator mi;
+  VertexMemberships::iterator largest = memberships.begin();
+
+  for (mi = memberships.begin(); mi != memberships.end(); ++mi) {
+    if ((*largest) < (*mi)) {
+      // Remember the largest membership value, so we can readjust it
+      // at the end.
+      largest = mi;
+    }
+
+    double value = (*mi)._membership * factor;
+    if (_vref_quantum != 0.0) {
+      value = floor(value / _vref_quantum + 0.5) * _vref_quantum;
+    }
+    (*mi)._membership = value;
+
+    net_membership += value;
+  }
+
+  // The the largest membership value gets corrected again by the
+  // roundoff error.
+  (*largest)._membership += 1.0 - net_membership;
+
+  // Finally, walk back through and apply these computed values to the
+  // vertex.
+  for (mi = memberships.begin(); mi != memberships.end(); ++mi) {
+    (*mi)._group->set_vertex_membership(egg_vertex, (*mi)._membership);
+  }
+}
+
 
 int main(int argc, char *argv[]) {
   EggOptchar prog;

+ 6 - 0
pandatool/src/egg-optchar/eggOptchar.h

@@ -65,6 +65,10 @@ private:
   void describe_component(EggComponentData *comp_data, int indent_level);
   void do_reparent();
 
+  void quantize_vertices();
+  void quantize_vertices(EggNode *egg_node);
+  void quantize_vertex(EggVertex *egg_vertex);
+
   bool _list_hierarchy;
   bool _list_hierarchy_p;
   bool _keep_all;
@@ -79,6 +83,8 @@ private:
 
   vector_string _keep_components;
   vector_string _expose_components;
+
+  double _vref_quantum;
 };
 
 #endif

+ 66 - 0
pandatool/src/egg-optchar/vertexMembership.I

@@ -0,0 +1,66 @@
+// Filename: vertexMembership.I
+// Created by:  drose (21Jul03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: VertexMembership::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE VertexMembership::
+VertexMembership(EggGroup *group, double membership) :
+  _group(group),
+  _membership(membership)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: VertexMembership::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE VertexMembership::
+VertexMembership(const VertexMembership &copy) :
+  _group(copy._group),
+  _membership(copy._membership)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: VertexMembership::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void VertexMembership::
+operator = (const VertexMembership &copy) {
+  _group = copy._group;
+  _membership = copy._membership;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: VertexMembership::Ordering Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool VertexMembership::
+operator < (const VertexMembership &other) const {
+  if (_membership != other._membership) {
+    return _membership < other._membership;
+  }
+  return _group < other._group;
+}

+ 19 - 0
pandatool/src/egg-optchar/vertexMembership.cxx

@@ -0,0 +1,19 @@
+// Filename: vertexMembership.cxx
+// Created by:  drose (21Jul03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "vertexMembership.h"

+ 50 - 0
pandatool/src/egg-optchar/vertexMembership.h

@@ -0,0 +1,50 @@
+// Filename: vertexMembership.h
+// Created by:  drose (21Jul03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef VERTEXMEMBERSHIP_H
+#define VERTEXMEMBERSHIP_H
+
+#include "pandatoolbase.h"
+
+#include "pvector.h"
+
+class EggGroup;
+
+////////////////////////////////////////////////////////////////////
+//       Class : VertexMembership
+// Description : This class is used to help EggOptchar quantize the
+//               membership of one vertex among its various groups.
+////////////////////////////////////////////////////////////////////
+class VertexMembership {
+public:
+  INLINE VertexMembership(EggGroup *group, double membership);
+  INLINE VertexMembership(const VertexMembership &copy);
+  INLINE void operator = (const VertexMembership &copy);
+
+  INLINE bool operator < (const VertexMembership &other) const;
+
+  EggGroup *_group;
+  double _membership;
+};
+
+typedef pvector<VertexMembership> VertexMemberships;
+
+#include "vertexMembership.I"
+
+#endif
+