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