support quantizing memberships

This commit is contained in:
David Rose 2003-07-21 21:06:46 +00:00
parent ba4ec85c60
commit 0f87a88945
6 changed files with 263 additions and 2 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 &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;
}

View File

@ -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"

View File

@ -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 &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