open_toontown_panda3d/panda/src/egg/eggUtilities.I

122 lines
3.9 KiB
Plaintext

// Filename: eggUtilities.I
// Created by: drose (10Feb99)
//
////////////////////////////////////////////////////////////////////
#include "eggGroup.h"
#include "eggPrimitive.h"
#include <algorithm>
////////////////////////////////////////////////////////////////////
// Function: split_vertex
// Description: Splits a vertex into two or more vertices, each an
// exact copy of the original and in the same vertex
// pool.
//
// The splitting is based on some arbitrary property of
// the primitives that own the vertex. In the extreme,
// each primitive may get a different copy of the
// vertex, although it is also possible for some
// primitives to still share vertices.
//
// This decision is made based on the function object
// 'sequence'. This object must define the following
// function:
//
// int operator () (const EggPrimitive *prim) const;
//
// This function returns a sequence number, which
// determines which primitives will share which
// vertices. The sequence number 0 refers to the
// original vertex pointer; other sequence numbers
// indicate new vertices. Other than that, the sequence
// number is totally arbitrary. Primitives for which
// the sequence number is the same will end up sharing
// the same copy of the vertex.
////////////////////////////////////////////////////////////////////
template<class FunctionObject>
void
split_vertex(EggVertex *vert, const FunctionObject &sequence) {
// Did we start in a happy world?
vert->test_pref_integrity();
vert->test_gref_integrity();
EggVertexPool *pool = vert->get_pool();
// Define a map of ints to vert pointers, to indicate which sequence
// numbers we have already created vertices for.
typedef map<int, EggVertex *> Sequences;
Sequences _sequences;
// Get a copy of the list of primitives that reference this vertex.
// We must have a copy because we will be modifying the list as we
// traverse it.
typedef vector<EggPrimitive *> Prims;
Prims prims;
prims.reserve(vert->pref_size());
copy(vert->pref_begin(), vert->pref_end(), back_inserter(prims));
// Now walk through the list of primitives that reference this
// vertex.
Prims::const_iterator pri;
for (pri = prims.begin(); pri != prims.end(); ++pri) {
EggPrimitive *prim = *pri;
prim->test_ref_count_integrity();
int seq = sequence(prim);
if (seq != 0) {
// Here's a new sequence number! Have we already defined it?
EggVertex *new_vert = NULL;
Sequences::const_iterator si = _sequences.find(seq);
if (si != _sequences.end()) {
// Yes, we've seen this sequence number before. Use the same
// vertex.
new_vert = (*si).second;
} else {
// No, this is the first time we've encountered this sequence.
// Split the vertex.
new_vert = new EggVertex(*vert);
pool->add_vertex(new_vert);
_sequences[seq] = new_vert;
// The new vertex gets all the same group memberships as the
// old one.
EggVertex::GroupRef::const_iterator gri;
for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) {
EggGroup *group = *gri;
group->ref_vertex(new_vert, group->get_vertex_membership(vert));
}
}
// Now replace the vertex in the primitive.
EggPrimitive::iterator pi;
for (pi = prim->begin(); pi != prim->end(); ++pi) {
if (*pi == vert) {
prim->replace(pi, new_vert);
}
}
}
}
#ifndef NDEBUG
// Now verify everything is still happy.
vert->test_pref_integrity();
vert->test_gref_integrity();
Sequences::const_iterator si;
for (si = _sequences.begin();
si != _sequences.end();
++si) {
EggVertex *new_vert = (*si).second;
new_vert->test_gref_integrity();
new_vert->test_pref_integrity();
}
#endif // NDEBUG
}