00001 // Filename: eggUtilities.I 00002 // Created by: drose (10Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "eggGroup.h" 00016 #include "eggPrimitive.h" 00017 #include "eggVertexPool.h" 00018 00019 #include <algorithm> 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: split_vertex 00023 // Description: Splits a vertex into two or more vertices, each an 00024 // exact copy of the original and in the same vertex 00025 // pool. 00026 // 00027 // The splitting is based on some arbitrary property of 00028 // the primitives that own the vertex. In the extreme, 00029 // each primitive may get a different copy of the 00030 // vertex, although it is also possible for some 00031 // primitives to still share vertices. 00032 // 00033 // This decision is made based on the function object 00034 // 'sequence'. This object must define the following 00035 // function: 00036 // 00037 // int operator () (const EggPrimitive *prim) const; 00038 // 00039 // This function returns a sequence number, which 00040 // determines which primitives will share which 00041 // vertices. The sequence number 0 refers to the 00042 // original vertex pointer; other sequence numbers 00043 // indicate new vertices. Other than that, the sequence 00044 // number is totally arbitrary. Primitives for which 00045 // the sequence number is the same will end up sharing 00046 // the same copy of the vertex. 00047 //////////////////////////////////////////////////////////////////// 00048 template<class FunctionObject> 00049 void 00050 split_vertex(EggVertex *vert, const FunctionObject &sequence) { 00051 // Did we start in a happy world? 00052 vert->test_pref_integrity(); 00053 vert->test_gref_integrity(); 00054 00055 EggVertexPool *pool = vert->get_pool(); 00056 00057 // Define a map of ints to vert pointers, to indicate which sequence 00058 // numbers we have already created vertices for. 00059 typedef pmap<int, EggVertex *> Sequences; 00060 Sequences _sequences; 00061 00062 // Get a copy of the list of primitives that reference this vertex. 00063 // We must have a copy because we will be modifying the list as we 00064 // traverse it. 00065 typedef pvector<EggPrimitive *> Prims; 00066 Prims prims; 00067 prims.reserve(vert->pref_size()); 00068 copy(vert->pref_begin(), vert->pref_end(), back_inserter(prims)); 00069 00070 // Now walk through the list of primitives that reference this 00071 // vertex. 00072 Prims::const_iterator pri; 00073 for (pri = prims.begin(); pri != prims.end(); ++pri) { 00074 EggPrimitive *prim = *pri; 00075 prim->test_ref_count_integrity(); 00076 00077 int seq = sequence(prim); 00078 00079 if (seq != 0) { 00080 // Here's a new sequence number! Have we already defined it? 00081 EggVertex *new_vert = NULL; 00082 00083 Sequences::const_iterator si = _sequences.find(seq); 00084 00085 if (si != _sequences.end()) { 00086 // Yes, we've seen this sequence number before. Use the same 00087 // vertex. 00088 new_vert = (*si).second; 00089 00090 } else { 00091 // No, this is the first time we've encountered this sequence. 00092 // Split the vertex. 00093 new_vert = new EggVertex(*vert); 00094 pool->add_vertex(new_vert); 00095 _sequences[seq] = new_vert; 00096 00097 // The new vertex gets all the same group memberships as the 00098 // old one. 00099 EggVertex::GroupRef::const_iterator gri; 00100 for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) { 00101 EggGroup *group = *gri; 00102 group->ref_vertex(new_vert, group->get_vertex_membership(vert)); 00103 } 00104 } 00105 00106 // Now replace the vertex in the primitive. 00107 EggPrimitive::iterator pi; 00108 for (pi = prim->begin(); pi != prim->end(); ++pi) { 00109 if (*pi == vert) { 00110 prim->replace(pi, new_vert); 00111 } 00112 } 00113 } 00114 } 00115 00116 #ifndef NDEBUG 00117 // Now verify everything is still happy. 00118 vert->test_pref_integrity(); 00119 vert->test_gref_integrity(); 00120 00121 Sequences::const_iterator si; 00122 for (si = _sequences.begin(); 00123 si != _sequences.end(); 00124 ++si) { 00125 EggVertex *new_vert = (*si).second; 00126 new_vert->test_gref_integrity(); 00127 new_vert->test_pref_integrity(); 00128 } 00129 #endif // NDEBUG 00130 00131 }