Panda3D
|
00001 // Filename: eggVertexPool.cxx 00002 // Created by: drose (16Jan99) 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 "eggVertexPool.h" 00016 #include "eggPrimitive.h" 00017 #include "eggUtilities.h" 00018 #include <iterator> 00019 00020 #include "indent.h" 00021 00022 #include <iterator> 00023 00024 TypeHandle EggVertexPool::_type_handle; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: EggVertexPool::Constructor 00028 // Access: Public 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 EggVertexPool:: 00032 EggVertexPool(const string &name) : EggNode(name) { 00033 _highest_index = -1; 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: EggVertexPool::Copy Constructor 00038 // Access: Public 00039 // Description: Copying a vertex pool is of questionable value, since 00040 // it will copy all of the vertices and assign new 00041 // pointers to them all. There will be no polygons 00042 // referring to the new vertices. 00043 //////////////////////////////////////////////////////////////////// 00044 EggVertexPool:: 00045 EggVertexPool(const EggVertexPool ©) : EggNode(copy) { 00046 iterator i; 00047 for (i = copy.begin(); i != copy.end(); ++i) { 00048 add_vertex(new EggVertex(*(*i)), (*i)->get_index()); 00049 } 00050 } 00051 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: EggVertexPool::Destructor 00055 // Access: Public 00056 // Description: 00057 //////////////////////////////////////////////////////////////////// 00058 EggVertexPool:: 00059 ~EggVertexPool() { 00060 // Remove all vertices from the pool when it destructs. 00061 00062 // Sanity check. 00063 nassertv(_index_vertices.size() == _unique_vertices.size()); 00064 00065 IndexVertices::iterator ivi; 00066 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00067 int index = (*ivi).first; 00068 EggVertex *vertex = (*ivi).second; 00069 00070 // Sanity checks on our internal data structures. 00071 nassertv(vertex->_pool == this); 00072 nassertv(vertex->get_index() == index); 00073 00074 vertex->_pool = NULL; 00075 vertex->_index = -1; 00076 } 00077 00078 _index_vertices.clear(); 00079 _unique_vertices.clear(); 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: EggVertexPool::has_forward_vertices 00084 // Access: Published 00085 // Description: Returns true if any vertices in the pool are 00086 // undefined forward-reference vertices, false if all 00087 // vertices are defined. 00088 //////////////////////////////////////////////////////////////////// 00089 bool EggVertexPool:: 00090 has_forward_vertices() const { 00091 IndexVertices::const_iterator ivi; 00092 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00093 EggVertex *vertex = (*ivi).second; 00094 if (vertex->is_forward_reference()) { 00095 return true; 00096 } 00097 } 00098 00099 return false; 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: EggVertexPool::has_defined_vertices 00104 // Access: Published 00105 // Description: Returns true if any vertices in the pool are 00106 // fully defined vertices, false if all vertices are 00107 // forward references. 00108 //////////////////////////////////////////////////////////////////// 00109 bool EggVertexPool:: 00110 has_defined_vertices() const { 00111 IndexVertices::const_iterator ivi; 00112 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00113 EggVertex *vertex = (*ivi).second; 00114 if (!vertex->is_forward_reference()) { 00115 return true; 00116 } 00117 } 00118 00119 return false; 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: EggVertexPool::get_vertex 00124 // Access: Public 00125 // Description: Returns the vertex in the pool with the indicated 00126 // index number, or NULL if no vertices have that index 00127 // number. 00128 //////////////////////////////////////////////////////////////////// 00129 EggVertex *EggVertexPool:: 00130 get_vertex(int index) const { 00131 IndexVertices::const_iterator ivi = _index_vertices.find(index); 00132 00133 if (ivi == _index_vertices.end()) { 00134 return NULL; 00135 } else { 00136 EggVertex *vertex = (*ivi).second; 00137 if (vertex->is_forward_reference()) { 00138 return NULL; 00139 } 00140 return vertex; 00141 } 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: EggVertexPool::get_forward_vertex 00146 // Access: Public 00147 // Description: Returns the vertex in the pool with the indicated 00148 // index number. If there is not a vertex in the pool 00149 // with the indicated index number, creates a special 00150 // forward-reference EggVertex that has no data, on the 00151 // assumption that the vertex pool has not yet been 00152 // fully read and more data will be available later. 00153 //////////////////////////////////////////////////////////////////// 00154 EggVertex *EggVertexPool:: 00155 get_forward_vertex(int index) { 00156 nassertr(index >= 0, NULL); 00157 00158 IndexVertices::const_iterator ivi = _index_vertices.find(index); 00159 00160 if (ivi == _index_vertices.end()) { 00161 PT(EggVertex) forward = new EggVertex; 00162 forward->_forward_reference = true; 00163 return add_vertex(forward, index); 00164 } else { 00165 return (*ivi).second; 00166 } 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: EggVertexPool::get_highest_index 00171 // Access: Public 00172 // Description: Returns the highest index number used by any vertex 00173 // in the pool (except forward references). Returns -1 00174 // if the pool is empty. 00175 //////////////////////////////////////////////////////////////////// 00176 int EggVertexPool:: 00177 get_highest_index() const { 00178 return _highest_index; 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: EggVertexPool::set_highest_index 00183 // Access: Public 00184 // Description: Artificially changes the "highest index number", so 00185 // that a newly created vertex will begin at this number 00186 // plus 1. This can be used to default a vertex pool to 00187 // start counting at 1 (or any other index number), 00188 // instead of the default of 0. Use with caution. 00189 //////////////////////////////////////////////////////////////////// 00190 void EggVertexPool:: 00191 set_highest_index(int highest_index) { 00192 _highest_index = highest_index; 00193 } 00194 00195 //////////////////////////////////////////////////////////////////// 00196 // Function: EggVertexPool::get_num_dimensions 00197 // Access: Public 00198 // Description: Returns the maximum number of dimensions used by any 00199 // vertex in the pool. 00200 //////////////////////////////////////////////////////////////////// 00201 int EggVertexPool:: 00202 get_num_dimensions() const { 00203 int num_dimensions = 0; 00204 00205 IndexVertices::const_iterator ivi; 00206 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00207 EggVertex *vertex = (*ivi).second; 00208 num_dimensions = max(num_dimensions, vertex->get_num_dimensions()); 00209 } 00210 00211 return num_dimensions; 00212 } 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: EggVertexPool::has_normals 00216 // Access: Public 00217 // Description: Returns true if any vertex in the pool has a normal 00218 // defined, false if none of them do. 00219 //////////////////////////////////////////////////////////////////// 00220 bool EggVertexPool:: 00221 has_normals() const { 00222 IndexVertices::const_iterator ivi; 00223 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00224 EggVertex *vertex = (*ivi).second; 00225 if (vertex->has_normal()) { 00226 return true; 00227 } 00228 } 00229 00230 return false; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: EggVertexPool::has_colors 00235 // Access: Public 00236 // Description: Returns true if any vertex in the pool has a color 00237 // defined, false if none of them do. 00238 //////////////////////////////////////////////////////////////////// 00239 bool EggVertexPool:: 00240 has_colors() const { 00241 IndexVertices::const_iterator ivi; 00242 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00243 EggVertex *vertex = (*ivi).second; 00244 if (vertex->has_color()) { 00245 return true; 00246 } 00247 } 00248 00249 return false; 00250 } 00251 00252 //////////////////////////////////////////////////////////////////// 00253 // Function: EggVertexPool::has_nonwhite_colors 00254 // Access: Public 00255 // Description: Returns true if any vertex in the pool has a color 00256 // defined other than white, false if no vertices have 00257 // colors, or if all colors are white. 00258 //////////////////////////////////////////////////////////////////// 00259 bool EggVertexPool:: 00260 has_nonwhite_colors() const { 00261 IndexVertices::const_iterator ivi; 00262 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00263 EggVertex *vertex = (*ivi).second; 00264 if (vertex->has_color() && 00265 (vertex->get_color() != LColor(1.0, 1.0, 1.0, 1.0) || 00266 !vertex->_drgbas.empty())) { 00267 return true; 00268 } 00269 } 00270 00271 return false; 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: EggVertexPool::check_overall_color 00276 // Access: Public 00277 // Description: Scans the vertex pool for different colors on 00278 // different vertices. If all vertices are the same 00279 // color, sets has_overall_color to true and fills the 00280 // color into overall_color. If no vertices have any 00281 // color, set has_overall_color to true and fills white 00282 // into overall_color. If at least two vertices have 00283 // different colors, sets has_overall_color to false. 00284 //////////////////////////////////////////////////////////////////// 00285 void EggVertexPool:: 00286 check_overall_color(bool &has_overall_color, LColor &overall_color) const { 00287 if (empty()) { 00288 has_overall_color = true; 00289 overall_color.set(1.0f, 1.0f, 1.0f, 1.0f); 00290 return; 00291 } 00292 00293 IndexVertices::const_iterator ivi; 00294 ivi = _index_vertices.begin(); 00295 EggVertex *vertex = (*ivi).second; 00296 overall_color = vertex->get_color(); 00297 00298 ++ivi; 00299 while (ivi != _index_vertices.end()) { 00300 vertex = (*ivi).second; 00301 if (!vertex->get_color().almost_equal(overall_color)) { 00302 has_overall_color = false; 00303 return; 00304 } 00305 ++ivi; 00306 } 00307 00308 has_overall_color = true; 00309 } 00310 00311 //////////////////////////////////////////////////////////////////// 00312 // Function: EggVertexPool::has_uvs 00313 // Access: Public 00314 // Description: Returns true if any vertex in the pool has a uv 00315 // defined, false if none of them do. 00316 //////////////////////////////////////////////////////////////////// 00317 bool EggVertexPool:: 00318 has_uvs() const { 00319 IndexVertices::const_iterator ivi; 00320 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00321 EggVertex *vertex = (*ivi).second; 00322 if (vertex->has_uv()) { 00323 return true; 00324 } 00325 } 00326 00327 return false; 00328 } 00329 00330 //////////////////////////////////////////////////////////////////// 00331 // Function: EggVertexPool::has_aux 00332 // Access: Public 00333 // Description: Returns true if any vertex in the pool has 00334 // auxiliary data defined, false if none of them do. 00335 //////////////////////////////////////////////////////////////////// 00336 bool EggVertexPool:: 00337 has_aux() const { 00338 IndexVertices::const_iterator ivi; 00339 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00340 EggVertex *vertex = (*ivi).second; 00341 if (vertex->has_aux()) { 00342 return true; 00343 } 00344 } 00345 00346 return false; 00347 } 00348 00349 //////////////////////////////////////////////////////////////////// 00350 // Function: EggVertexPool::get_uv_names 00351 // Access: Public 00352 // Description: Returns the list of UV names that are defined by any 00353 // vertices in the pool, as well as the subset of UV 00354 // names that actually define 3-d texture coordinates 00355 // ("uvw_names"). Also returns the subset of UV/UVW 00356 // names that define a tangent and binormal. It is the 00357 // user's responsibility to clear both vectors before 00358 // calling this method. 00359 //////////////////////////////////////////////////////////////////// 00360 void EggVertexPool:: 00361 get_uv_names(vector_string &uv_names, vector_string &uvw_names, 00362 vector_string &tbn_names) const { 00363 pset<string> uv_names_set, uvw_names_set, tbn_names_set; 00364 IndexVertices::const_iterator ivi; 00365 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00366 EggVertex *vertex = (*ivi).second; 00367 EggVertex::const_uv_iterator uvi; 00368 for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) { 00369 EggVertexUV *uv_obj = (*uvi); 00370 uv_names_set.insert(uv_obj->get_name()); 00371 if (uv_obj->has_w()) { 00372 uvw_names_set.insert(uv_obj->get_name()); 00373 } 00374 if (uv_obj->has_tangent() && uv_obj->has_binormal()) { 00375 tbn_names_set.insert(uv_obj->get_name()); 00376 } 00377 } 00378 } 00379 00380 pset<string>::const_iterator si; 00381 for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) { 00382 uv_names.push_back(*si); 00383 } 00384 for (si = uvw_names_set.begin(); si != uvw_names_set.end(); ++si) { 00385 uvw_names.push_back(*si); 00386 } 00387 for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) { 00388 tbn_names.push_back(*si); 00389 } 00390 } 00391 00392 //////////////////////////////////////////////////////////////////// 00393 // Function: EggVertexPool::get_aux_names 00394 // Access: Public 00395 // Description: Returns the list of auxiliary data names that are 00396 // defined by any vertices in the pool. 00397 //////////////////////////////////////////////////////////////////// 00398 void EggVertexPool:: 00399 get_aux_names(vector_string &aux_names) const { 00400 pset<string> aux_names_set; 00401 IndexVertices::const_iterator ivi; 00402 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00403 EggVertex *vertex = (*ivi).second; 00404 EggVertex::const_aux_iterator uvi; 00405 for (uvi = vertex->aux_begin(); uvi != vertex->aux_end(); ++uvi) { 00406 EggVertexAux *aux_obj = (*uvi); 00407 aux_names_set.insert(aux_obj->get_name()); 00408 } 00409 } 00410 00411 pset<string>::const_iterator si; 00412 for (si = aux_names_set.begin(); si != aux_names_set.end(); ++si) { 00413 aux_names.push_back(*si); 00414 } 00415 } 00416 00417 //////////////////////////////////////////////////////////////////// 00418 // Function: EggVertexPool::begin() 00419 // Access: Public 00420 // Description: Returns an iterator that can be used to traverse 00421 // through all the vertices in the pool. 00422 //////////////////////////////////////////////////////////////////// 00423 EggVertexPool::iterator EggVertexPool:: 00424 begin() const { 00425 nassertr(_index_vertices.size() == _unique_vertices.size(), 00426 iterator(_index_vertices.begin())); 00427 return iterator(_index_vertices.begin()); 00428 } 00429 00430 //////////////////////////////////////////////////////////////////// 00431 // Function: EggVertexPool::end() 00432 // Access: Public 00433 // Description: Returns an iterator that can be used to traverse 00434 // through all the vertices in the pool. 00435 //////////////////////////////////////////////////////////////////// 00436 EggVertexPool::iterator EggVertexPool:: 00437 end() const { 00438 return iterator(_index_vertices.end()); 00439 } 00440 00441 //////////////////////////////////////////////////////////////////// 00442 // Function: EggVertexPool::empty() 00443 // Access: Public 00444 // Description: Returns true if the pool is empty. 00445 //////////////////////////////////////////////////////////////////// 00446 bool EggVertexPool:: 00447 empty() const { 00448 return _index_vertices.empty(); 00449 } 00450 00451 //////////////////////////////////////////////////////////////////// 00452 // Function: EggVertexPool::size() 00453 // Access: Public 00454 // Description: Returns the number of vertices in the pool. 00455 //////////////////////////////////////////////////////////////////// 00456 EggVertexPool::size_type EggVertexPool:: 00457 size() const { 00458 nassertr(_index_vertices.size() == _unique_vertices.size(), 0); 00459 return _index_vertices.size(); 00460 } 00461 00462 //////////////////////////////////////////////////////////////////// 00463 // Function: EggVertexPool::add_vertex 00464 // Access: Public 00465 // Description: Adds the indicated vertex to the pool. It is an 00466 // error if the vertex is already a member of this or 00467 // any other pool. The vertex must have been allocated 00468 // from the free store; its pointer will now be owned by 00469 // the vertex pool. If the index number is supplied, 00470 // tries to assign that index number; it is an error if 00471 // the index number is already in use. 00472 // 00473 // It is possible that a forward reference to this 00474 // vertex was requested in the past; if so, the data 00475 // from the supplied vertex is copied onto the forward 00476 // reference, which becomes the actual vertex. In this 00477 // case, a different pointer is saved (and returned) 00478 // than the one actually passed in. In the usual case, 00479 // however, the vertex pointer passed in is the one that 00480 // is saved in the vertex pool and returned from this 00481 // method. 00482 //////////////////////////////////////////////////////////////////// 00483 EggVertex *EggVertexPool:: 00484 add_vertex(EggVertex *vertex, int index) { 00485 // Save a pointer to the vertex. 00486 PT(EggVertex) vertex_keep = vertex; 00487 00488 // Don't try to add a vertex while it still belongs to another pool. 00489 nassertr(vertex->_pool == NULL, NULL); 00490 00491 if (index == -1) { 00492 index = get_highest_index() + 1; 00493 } 00494 // Always supply an index number >= 0. 00495 nassertr(index >= 0, NULL); 00496 00497 // Check for a forward reference. 00498 IndexVertices::const_iterator ivi = _index_vertices.find(index); 00499 00500 if (ivi != _index_vertices.end()) { 00501 EggVertex *orig_vertex = (*ivi).second; 00502 if (orig_vertex->is_forward_reference() && 00503 !vertex->is_forward_reference()) { 00504 (*orig_vertex) = (*vertex); 00505 orig_vertex->_forward_reference = false; 00506 _highest_index = max(_highest_index, index); 00507 return orig_vertex; 00508 } 00509 00510 // Oops, you duplicated a vertex index. 00511 nassertr(false, NULL); 00512 } 00513 00514 _unique_vertices.insert(vertex); 00515 _index_vertices[index] = vertex; 00516 00517 if (!vertex->is_forward_reference()) { 00518 _highest_index = max(_highest_index, index); 00519 } 00520 00521 vertex->_pool = this; 00522 vertex->_index = index; 00523 00524 return vertex; 00525 } 00526 00527 00528 //////////////////////////////////////////////////////////////////// 00529 // Function: EggVertexPool::create_unique_vertex 00530 // Access: Public 00531 // Description: Creates a new vertex in the pool that is a copy of 00532 // the indicated one and returns it. If there is 00533 // already a vertex in the pool like the indicated one, 00534 // simply returns that one. 00535 //////////////////////////////////////////////////////////////////// 00536 EggVertex *EggVertexPool:: 00537 create_unique_vertex(const EggVertex ©) { 00538 UniqueVertices::iterator uvi; 00539 uvi = _unique_vertices.find((EggVertex *)©); 00540 00541 if (uvi != _unique_vertices.end()) { 00542 // There was already such a vertex. Return it. 00543 return (*uvi); 00544 } 00545 00546 // Create a new vertex. 00547 return add_vertex(new EggVertex(copy)); 00548 } 00549 00550 //////////////////////////////////////////////////////////////////// 00551 // Function: EggVertexPool::find_matching_vertex 00552 // Access: Public 00553 // Description: If the EggVertexPool already has a vertex matching 00554 // the indicated vertex, returns it; otherwise, returns 00555 // NULL. This is similar to create_unique_vertex() 00556 // except that a new vertex is never created. 00557 //////////////////////////////////////////////////////////////////// 00558 EggVertex *EggVertexPool:: 00559 find_matching_vertex(const EggVertex ©) { 00560 UniqueVertices::iterator uvi; 00561 uvi = _unique_vertices.find((EggVertex *)©); 00562 00563 if (uvi != _unique_vertices.end()) { 00564 // There was already such a vertex. Return it. 00565 return (*uvi); 00566 } 00567 00568 // No matching vertex. 00569 return NULL; 00570 } 00571 00572 00573 //////////////////////////////////////////////////////////////////// 00574 // Function: EggVertexPool::remove_vertex 00575 // Access: Public 00576 // Description: Removes the vertex from the pool. It is an error if 00577 // the vertex is not already a member of the pool. 00578 //////////////////////////////////////////////////////////////////// 00579 void EggVertexPool:: 00580 remove_vertex(EggVertex *vertex) { 00581 // Make sure the vertex is already a member of this pool. 00582 nassertv(vertex->_pool == this); 00583 00584 // Sanity check. Is the vertex actually in the pool? 00585 nassertv(get_vertex(vertex->_index) == vertex); 00586 00587 // Removing the vertex from the indexed list is simple. 00588 _index_vertices.erase(vertex->_index); 00589 00590 if (_highest_index == vertex->_index) { 00591 // Find the new highest vertex index. 00592 if (_index_vertices.empty()) { 00593 _highest_index = -1; 00594 } else { 00595 IndexVertices::reverse_iterator ivi = _index_vertices.rbegin(); 00596 while (ivi != _index_vertices.rend() && 00597 (*ivi).second->is_forward_reference()) { 00598 ++ivi; 00599 } 00600 if (ivi != _index_vertices.rend()) { 00601 _highest_index = (*ivi).first; 00602 } else { 00603 _highest_index = -1; 00604 } 00605 } 00606 } 00607 00608 // Removing the vertex from the unique list is a bit trickier--there 00609 // might be several other vertices that are considered identical to 00610 // this one, and so we have to walk through all the identical 00611 // vertices until we find the right one. 00612 UniqueVertices::iterator uvi; 00613 uvi = _unique_vertices.find(vertex); 00614 00615 // Sanity check. Is the vertex actually in the pool? 00616 nassertv(uvi != _unique_vertices.end()); 00617 00618 while ((*uvi) != vertex) { 00619 ++uvi; 00620 // Sanity check. Is the vertex actually in the pool? 00621 nassertv(uvi != _unique_vertices.end()); 00622 } 00623 00624 _unique_vertices.erase(uvi); 00625 00626 vertex->_pool = NULL; 00627 } 00628 00629 //////////////////////////////////////////////////////////////////// 00630 // Function: EggVertexPool::remove_unused_vertices 00631 // Access: Public 00632 // Description: Removes all vertices from the pool that are not 00633 // referenced by at least one primitive. Also collapses 00634 // together equivalent vertices, and renumbers all 00635 // vertices after the operation so their indices are 00636 // consecutive, beginning at zero. Returns the number 00637 // of vertices removed. 00638 //////////////////////////////////////////////////////////////////// 00639 int EggVertexPool:: 00640 remove_unused_vertices() { 00641 int num_removed = 0; 00642 00643 UniqueVertices new_unique_vertices; 00644 IndexVertices new_index_vertices; 00645 00646 IndexVertices::const_iterator ivi; 00647 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00648 EggVertex *vertex = (*ivi).second; 00649 if (vertex->pref_size() == 0) { 00650 // This vertex is not used. Don't add it to the new lists. 00651 vertex->clear_grefs(); 00652 vertex->_pool = NULL; 00653 num_removed++; 00654 00655 } else { 00656 // The vertex *is* used somewhere. Is it identical to an 00657 // existing vertex? 00658 UniqueVertices::iterator uvi; 00659 uvi = new_unique_vertices.find(vertex); 00660 if (uvi != new_unique_vertices.end()) { 00661 // Yes, there's already another vertex just like this one. 00662 // Redirect all the primitives currently referencing this 00663 // vertex to reference the other one instead. 00664 EggVertex *orig_vertex = (*uvi); 00665 00666 EggVertex::PrimitiveRef pref = vertex->_pref; 00667 EggVertex::PrimitiveRef::iterator pi; 00668 for (pi = pref.begin(); pi != pref.end(); ++pi) { 00669 EggPrimitive *prim = (*pi); 00670 EggPrimitive::iterator pvi = prim->find(vertex); 00671 nassertr(pvi != prim->end(), 0); 00672 prim->replace(pvi, orig_vertex); 00673 } 00674 vertex->test_pref_integrity(); 00675 orig_vertex->test_pref_integrity(); 00676 nassertr(vertex->pref_size() == 0, 0); 00677 vertex->clear_grefs(); 00678 vertex->_pool = NULL; 00679 num_removed++; 00680 00681 } else { 00682 // It's a unique vertex. Renumber it and add it to the new 00683 // lists. 00684 vertex->_index = new_index_vertices.size(); 00685 new_index_vertices.insert(IndexVertices::value_type(vertex->_index, vertex)); 00686 new_unique_vertices.insert(vertex); 00687 } 00688 } 00689 } 00690 00691 // All done. Lose the old lists. 00692 _unique_vertices.swap(new_unique_vertices); 00693 _index_vertices.swap(new_index_vertices); 00694 _highest_index = (int)_index_vertices.size() - 1; 00695 00696 nassertr(_index_vertices.size() == _unique_vertices.size(), num_removed); 00697 00698 return num_removed; 00699 } 00700 00701 //////////////////////////////////////////////////////////////////// 00702 // Function: EggVertexPool::add_unused_vertices_to_prim 00703 // Access: Public 00704 // Description: Adds all of the unused vertices in this vertex pool 00705 // to the indicated primitive, in ascending order. 00706 //////////////////////////////////////////////////////////////////// 00707 void EggVertexPool:: 00708 add_unused_vertices_to_prim(EggPrimitive *prim) { 00709 IndexVertices::iterator ivi; 00710 for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { 00711 EggVertex *vertex = (*ivi).second; 00712 if (vertex->pref_size() == 0) { 00713 prim->add_vertex(vertex); 00714 } 00715 } 00716 } 00717 00718 // A function object for split_vertex(), used in transform(), below. 00719 class IsLocalVertexSplitter { 00720 public: 00721 int operator () (const EggPrimitive *prim) const { 00722 return (prim->is_local_coord() ? 1 : 0); 00723 } 00724 }; 00725 00726 //////////////////////////////////////////////////////////////////// 00727 // Function: EggVertexPool::transform 00728 // Access: Public 00729 // Description: Applies the indicated transformation matrix to all 00730 // the vertices. However, vertices that are attached to 00731 // primitives that believe their vertices are in a local 00732 // coordinate system are transformed only by the scale 00733 // and rotation component. If a vertex happens to be 00734 // attached both to a local and a global primitive, and 00735 // the transformation includes a translation component, 00736 // the vertex will be split. 00737 //////////////////////////////////////////////////////////////////// 00738 void EggVertexPool:: 00739 transform(const LMatrix4d &mat) { 00740 LVector3d translation = mat.get_row3(3); 00741 00742 if (translation == LVector3d(0.0, 0.0, 0.0)) { 00743 // If the matrix does not have a translation component, we can 00744 // treat the local and global vertices the same. This makes 00745 // things much easier. 00746 iterator i; 00747 for (i = begin(); i != end(); ++i) { 00748 EggVertex *vert = *i; 00749 vert->transform(mat); 00750 } 00751 00752 } else { 00753 // The matrix does have a translation component. That means we 00754 // have to treat the global and local vertices differently. 00755 // Yucky. 00756 00757 // First, transform the global vertices. Get a copy of the list 00758 // of vertices in this pool. We must have a copy because we might 00759 // be modifying the list as we traverse it. 00760 00761 typedef pvector<EggVertex *> Verts; 00762 Verts verts; 00763 verts.reserve(size()); 00764 copy(begin(), end(), back_inserter(verts)); 00765 00766 Verts::const_iterator vi; 00767 for (vi = verts.begin(); vi != verts.end(); ++vi) { 00768 EggVertex *vert = *vi; 00769 int num_local_coord = vert->get_num_local_coord(); 00770 int num_global_coord = vert->get_num_global_coord(); 00771 00772 if (num_global_coord != 0) { 00773 // This vertex will be transformed. 00774 if (num_local_coord != 0) { 00775 // It also needs to be split! Yuck. 00776 split_vertex(vert, IsLocalVertexSplitter()); 00777 } 00778 00779 vert->transform(mat); 00780 } 00781 } 00782 00783 // Now transform the local vertices. We can walk through the list 00784 // directly now, because we won't be modifying the list this time. 00785 LMatrix4d local_mat = mat; 00786 local_mat.set_row(3, LVector3d(0.0, 0.0, 0.0)); 00787 00788 iterator i; 00789 for (i = begin(); i != end(); ++i) { 00790 EggVertex *vert = *i; 00791 if (vert->get_num_local_coord() != 0) { 00792 00793 // This should be guaranteed by the vertex-splitting logic 00794 // above. 00795 nassertv(vert->get_num_global_coord() == 0); 00796 vert->transform(local_mat); 00797 } 00798 } 00799 } 00800 } 00801 00802 00803 // A function object for sort_by_external_index(), below. 00804 class SortByExternalIndex { 00805 public: 00806 bool operator () (EggVertex *a, EggVertex *b) const { 00807 int ai = a->get_external_index(); 00808 int bi = b->get_external_index(); 00809 if (ai != bi) { 00810 return ai < bi; 00811 } 00812 return a->get_index() < b->get_index(); 00813 } 00814 }; 00815 00816 //////////////////////////////////////////////////////////////////// 00817 // Function: EggVertexPool::sort_by_external_index 00818 // Access: Published 00819 // Description: Re-orders (and re-numbers) the vertices in this 00820 // vertex pool so that they appear in increasing order 00821 // by the optional external_index that has been assigned 00822 // to each vertex. 00823 //////////////////////////////////////////////////////////////////// 00824 void EggVertexPool:: 00825 sort_by_external_index() { 00826 // Copy the vertices into a vector for sorting. 00827 typedef pvector<EggVertex *> SortedVertices; 00828 SortedVertices sorted_vertices; 00829 sorted_vertices.reserve(size()); 00830 iterator i; 00831 for (i = begin(); i != end(); ++i) { 00832 sorted_vertices.push_back(*i); 00833 } 00834 00835 ::sort(sorted_vertices.begin(), sorted_vertices.end(), SortByExternalIndex()); 00836 00837 // Now reassign the indices, and copy them into a new index map. 00838 IndexVertices new_index_vertices; 00839 int vi; 00840 for (vi = 0; vi < (int)sorted_vertices.size(); ++vi) { 00841 EggVertex *vertex = sorted_vertices[vi]; 00842 vertex->_index = vi; 00843 new_index_vertices[vi] = vertex; 00844 } 00845 00846 // Finally, assign the new index map. 00847 _index_vertices.swap(new_index_vertices); 00848 } 00849 00850 //////////////////////////////////////////////////////////////////// 00851 // Function: EggVertexPool::write 00852 // Access: Public 00853 // Description: Writes the vertex pool to the indicated output stream 00854 // in Egg format. 00855 //////////////////////////////////////////////////////////////////// 00856 void EggVertexPool:: 00857 write(ostream &out, int indent_level) const { 00858 write_header(out, indent_level, "<VertexPool>"); 00859 00860 iterator i; 00861 for (i = begin(); i != end(); ++i) { 00862 (*i)->write(out, indent_level+2); 00863 } 00864 00865 indent(out, indent_level) 00866 << "}\n"; 00867 } 00868 00869 00870 //////////////////////////////////////////////////////////////////// 00871 // Function: EggVertexPool::r_transform 00872 // Access: Protected, Virtual 00873 // Description: This is called from within the egg code by 00874 // transform(). It applies a transformation matrix 00875 // to the current node in some sensible way, then 00876 // continues down the tree. 00877 // 00878 // The first matrix is the transformation to apply; the 00879 // second is its inverse. The third parameter is the 00880 // coordinate system we are changing to, or CS_default 00881 // if we are not changing coordinate systems. 00882 //////////////////////////////////////////////////////////////////// 00883 void EggVertexPool:: 00884 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) { 00885 } 00886 00887 //////////////////////////////////////////////////////////////////// 00888 // Function: EggVertexPool::r_transform_vertices 00889 // Access: Protected, Virtual 00890 // Description: This is called from within the egg code by 00891 // transform_vertices_only()(). It applies a 00892 // transformation matrix to the current node in some 00893 // sensible way (if the current node is a vertex pool 00894 // with vertices), then continues down the tree. 00895 //////////////////////////////////////////////////////////////////// 00896 void EggVertexPool:: 00897 r_transform_vertices(const LMatrix4d &mat) { 00898 transform(mat); 00899 }