From 0f87a88945c5c59323649019201535b7b34c8836 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 21 Jul 2003 21:06:46 +0000 Subject: [PATCH] support quantizing memberships --- pandatool/src/egg-optchar/Sources.pp | 3 +- pandatool/src/egg-optchar/eggOptchar.cxx | 121 +++++++++++++++++- pandatool/src/egg-optchar/eggOptchar.h | 6 + pandatool/src/egg-optchar/vertexMembership.I | 66 ++++++++++ .../src/egg-optchar/vertexMembership.cxx | 19 +++ pandatool/src/egg-optchar/vertexMembership.h | 50 ++++++++ 6 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 pandatool/src/egg-optchar/vertexMembership.I create mode 100644 pandatool/src/egg-optchar/vertexMembership.cxx create mode 100644 pandatool/src/egg-optchar/vertexMembership.h diff --git a/pandatool/src/egg-optchar/Sources.pp b/pandatool/src/egg-optchar/Sources.pp index 7ebeaad653..c63c69c328 100644 --- a/pandatool/src/egg-optchar/Sources.pp +++ b/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 diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx index b0a2faf77c..e4873a9d05 100644 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ b/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 + //////////////////////////////////////////////////////////////////// // 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; diff --git a/pandatool/src/egg-optchar/eggOptchar.h b/pandatool/src/egg-optchar/eggOptchar.h index 459841706f..1a556009cc 100644 --- a/pandatool/src/egg-optchar/eggOptchar.h +++ b/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 diff --git a/pandatool/src/egg-optchar/vertexMembership.I b/pandatool/src/egg-optchar/vertexMembership.I new file mode 100644 index 0000000000..bda215a55e --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// 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 ©) : + _group(copy._group), + _membership(copy._membership) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: VertexMembership::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void VertexMembership:: +operator = (const VertexMembership ©) { + _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; +} diff --git a/pandatool/src/egg-optchar/vertexMembership.cxx b/pandatool/src/egg-optchar/vertexMembership.cxx new file mode 100644 index 0000000000..de592c143c --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "vertexMembership.h" diff --git a/pandatool/src/egg-optchar/vertexMembership.h b/pandatool/src/egg-optchar/vertexMembership.h new file mode 100644 index 0000000000..4363174a62 --- /dev/null +++ b/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 +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#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 ©); + INLINE void operator = (const VertexMembership ©); + + INLINE bool operator < (const VertexMembership &other) const; + + EggGroup *_group; + double _membership; +}; + +typedef pvector VertexMemberships; + +#include "vertexMembership.I" + +#endif +