Panda3D
|
00001 // Filename: eggPrimitive.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 "eggPrimitive.h" 00016 #include "eggVertexPool.h" 00017 #include "eggMiscFuncs.h" 00018 #include "eggTextureCollection.h" 00019 #include "lexerDefs.h" 00020 #include "config_egg.h" 00021 00022 #include "indent.h" 00023 #include "vector_int.h" 00024 00025 TypeHandle EggPrimitive::_type_handle; 00026 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: EggPrimitive::determine_alpha_mode 00030 // Access: Published, Virtual 00031 // Description: Walks back up the hierarchy, looking for an EggGroup 00032 // or EggPrimitive or some such object at this level or 00033 // above this primitive that has an alpha_mode other than 00034 // AM_unspecified. Returns a valid EggRenderMode pointer 00035 // if one is found, or NULL otherwise. 00036 //////////////////////////////////////////////////////////////////// 00037 EggRenderMode *EggPrimitive:: 00038 determine_alpha_mode() { 00039 if (get_alpha_mode() != AM_unspecified) { 00040 return this; 00041 } 00042 00043 EggRenderMode *result = EggNode::determine_alpha_mode(); 00044 if (result == (EggRenderMode *)NULL) { 00045 int num_textures = get_num_textures(); 00046 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00047 EggTexture *egg_tex = get_texture(i); 00048 00049 // We only want to consider the alpha mode on those textures 00050 // that can affect the transparency of the polygon. This 00051 // mostly depends on the envtype flag. 00052 if (egg_tex->affects_polygon_alpha()) { 00053 // This texture might affect the polygon alpha, so it gets to 00054 // decide the polygon transparency mode. 00055 if (egg_tex->get_alpha_mode() != AM_unspecified) { 00056 result = get_texture(i); 00057 } 00058 } 00059 } 00060 } 00061 return result; 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function: EggPrimitive::determine_depth_write_mode 00066 // Access: Published, Virtual 00067 // Description: Walks back up the hierarchy, looking for an EggGroup 00068 // or EggPrimitive or some such object at this level or 00069 // above this node that has a depth_write_mode other than 00070 // DWM_unspecified. Returns a valid EggRenderMode pointer 00071 // if one is found, or NULL otherwise. 00072 //////////////////////////////////////////////////////////////////// 00073 EggRenderMode *EggPrimitive:: 00074 determine_depth_write_mode() { 00075 if (get_depth_write_mode() != DWM_unspecified) { 00076 return this; 00077 } 00078 00079 EggRenderMode *result = EggNode::determine_depth_write_mode(); 00080 if (result == (EggRenderMode *)NULL) { 00081 int num_textures = get_num_textures(); 00082 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00083 if (get_texture(i)->get_depth_write_mode() != DWM_unspecified) { 00084 result = get_texture(i); 00085 } 00086 } 00087 } 00088 return result; 00089 } 00090 00091 //////////////////////////////////////////////////////////////////// 00092 // Function: EggPrimitive::determine_depth_test_mode 00093 // Access: Published, Virtual 00094 // Description: Walks back up the hierarchy, looking for an EggGroup 00095 // or EggPrimitive or some such object at this level or 00096 // above this node that has a depth_test_mode other than 00097 // DTM_unspecified. Returns a valid EggRenderMode pointer 00098 // if one is found, or NULL otherwise. 00099 //////////////////////////////////////////////////////////////////// 00100 EggRenderMode *EggPrimitive:: 00101 determine_depth_test_mode() { 00102 if (get_depth_test_mode() != DTM_unspecified) { 00103 return this; 00104 } 00105 00106 EggRenderMode *result = EggNode::determine_depth_test_mode(); 00107 if (result == (EggRenderMode *)NULL) { 00108 int num_textures = get_num_textures(); 00109 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00110 if (get_texture(i)->get_depth_test_mode() != DTM_unspecified) { 00111 result = get_texture(i); 00112 } 00113 } 00114 } 00115 return result; 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: EggPrimitive::determine_visibility_mode 00120 // Access: Published, Virtual 00121 // Description: Walks back up the hierarchy, looking for an EggGroup 00122 // or EggPrimitive or some such object at this level or 00123 // above this node that has a visibility_mode other than 00124 // VM_unspecified. Returns a valid EggRenderMode pointer 00125 // if one is found, or NULL otherwise. 00126 //////////////////////////////////////////////////////////////////// 00127 EggRenderMode *EggPrimitive:: 00128 determine_visibility_mode() { 00129 if (get_visibility_mode() != VM_unspecified) { 00130 return this; 00131 } 00132 00133 EggRenderMode *result = EggNode::determine_visibility_mode(); 00134 if (result == (EggRenderMode *)NULL) { 00135 int num_textures = get_num_textures(); 00136 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00137 if (get_texture(i)->get_visibility_mode() != VM_unspecified) { 00138 result = get_texture(i); 00139 } 00140 } 00141 } 00142 return result; 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: EggPrimitive::determine_depth_offset 00147 // Access: Published, Virtual 00148 // Description: Walks back up the hierarchy, looking for an EggGroup 00149 // or EggPrimitive or some such object at this level or 00150 // above this primitive that has a depth_offset specified. 00151 // Returns a valid EggRenderMode pointer if one is found, 00152 // or NULL otherwise. 00153 //////////////////////////////////////////////////////////////////// 00154 EggRenderMode *EggPrimitive:: 00155 determine_depth_offset() { 00156 if (has_depth_offset()) { 00157 return this; 00158 } 00159 00160 EggRenderMode *result = EggNode::determine_depth_offset(); 00161 if (result == (EggRenderMode *)NULL) { 00162 int num_textures = get_num_textures(); 00163 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00164 if (get_texture(i)->has_depth_offset()) { 00165 result = get_texture(i); 00166 } 00167 } 00168 } 00169 return result; 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: EggPrimitive::determine_draw_order 00174 // Access: Published, Virtual 00175 // Description: Walks back up the hierarchy, looking for an EggGroup 00176 // or EggPrimitive or some such object at this level or 00177 // above this primitive that has a draw_order specified. 00178 // Returns a valid EggRenderMode pointer if one is found, 00179 // or NULL otherwise. 00180 //////////////////////////////////////////////////////////////////// 00181 EggRenderMode *EggPrimitive:: 00182 determine_draw_order() { 00183 if (has_draw_order()) { 00184 return this; 00185 } 00186 00187 EggRenderMode *result = EggNode::determine_draw_order(); 00188 if (result == (EggRenderMode *)NULL) { 00189 int num_textures = get_num_textures(); 00190 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00191 if (get_texture(i)->has_draw_order()) { 00192 result = get_texture(i); 00193 } 00194 } 00195 } 00196 return result; 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function: EggPrimitive::determine_bin 00201 // Access: Published, Virtual 00202 // Description: Walks back up the hierarchy, looking for an EggGroup 00203 // or EggPrimitive or some such object at this level or 00204 // above this primitive that has a bin specified. Returns a 00205 // valid EggRenderMode pointer if one is found, or NULL 00206 // otherwise. 00207 //////////////////////////////////////////////////////////////////// 00208 EggRenderMode *EggPrimitive:: 00209 determine_bin() { 00210 if (has_bin()) { 00211 return this; 00212 } 00213 00214 EggRenderMode *result = EggNode::determine_bin(); 00215 if (result == (EggRenderMode *)NULL) { 00216 int num_textures = get_num_textures(); 00217 for (int i = 0; i < num_textures && result == (EggRenderMode *)NULL; i++) { 00218 if (get_texture(i)->has_bin()) { 00219 result = get_texture(i); 00220 } 00221 } 00222 } 00223 return result; 00224 } 00225 00226 00227 //////////////////////////////////////////////////////////////////// 00228 // Function: EggPrimitive::get_shading 00229 // Access: Published, Virtual 00230 // Description: Returns the shading properties apparent on this 00231 // particular primitive. This returns S_per_vertex if 00232 // the vertices have colors or normals (and they are not 00233 // all the same values), or for a simple primitive, 00234 // S_overall otherwise. A composite primitive may also 00235 // return S_per_face if the individual component 00236 // primitives have colors or normals that are not all 00237 // the same values. 00238 // 00239 // To get the most accurate results, you should call 00240 // clear_shading() on all connected primitives (or on 00241 // all primitives in the egg file), followed by 00242 // get_shading() on each primitive. You may find it 00243 // easiest to call these methods on the EggData root 00244 // node (they are defined on EggGroupNode). 00245 //////////////////////////////////////////////////////////////////// 00246 EggPrimitive::Shading EggPrimitive:: 00247 get_shading() const { 00248 if (empty()) { 00249 return S_overall; 00250 } 00251 00252 if (has_vertex_normal()) { 00253 // Check if the vertices all have the same normal. 00254 const EggAttributes *first_vertex = get_vertex(0); 00255 if (!first_vertex->has_normal()) { 00256 first_vertex = this; 00257 } 00258 for (int i = 1; i < get_num_vertices(); i++) { 00259 const EggAttributes *vertex = get_vertex(i); 00260 if (!vertex->has_normal()) { 00261 vertex = this; 00262 } 00263 if (!vertex->matches_normal(*first_vertex)) { 00264 return S_per_vertex; 00265 } 00266 } 00267 } 00268 00269 if (has_vertex_color()) { 00270 // Check if the vertices all have the same color. 00271 const EggAttributes *first_vertex = get_vertex(0); 00272 if (!first_vertex->has_color()) { 00273 first_vertex = this; 00274 } 00275 for (int i = 1; i < get_num_vertices(); i++) { 00276 const EggAttributes *vertex = get_vertex(i); 00277 if (!vertex->has_color()) { 00278 vertex = this; 00279 } 00280 if (!vertex->matches_color(*first_vertex)) { 00281 return S_per_vertex; 00282 } 00283 } 00284 } 00285 00286 return S_overall; 00287 } 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: EggPrimitive::copy_attributes 00291 // Access: Published 00292 // Description: Copies the rendering attributes from the indicated 00293 // primitive. 00294 //////////////////////////////////////////////////////////////////// 00295 void EggPrimitive:: 00296 copy_attributes(const EggAttributes &other) { 00297 EggAttributes::operator = (other); 00298 } 00299 00300 //////////////////////////////////////////////////////////////////// 00301 // Function: EggPrimitive::copy_attributes 00302 // Access: Published 00303 // Description: Copies the rendering attributes from the indicated 00304 // primitive. 00305 //////////////////////////////////////////////////////////////////// 00306 void EggPrimitive:: 00307 copy_attributes(const EggPrimitive &other) { 00308 EggAttributes::operator = (other); 00309 _textures = other._textures; 00310 set_material(other.get_material()); 00311 set_bface_flag(other.get_bface_flag()); 00312 } 00313 00314 //////////////////////////////////////////////////////////////////// 00315 // Function: EggPrimitive::has_vertex_normal 00316 // Access: Published 00317 // Description: Returns true if any vertex on the primitive has a 00318 // specific normal set, false otherwise. 00319 // 00320 // If you call unify_attributes() first, this will also 00321 // return false even if all the vertices were set to the 00322 // same value (since unify_attributes() removes 00323 // redundant vertex properties). 00324 //////////////////////////////////////////////////////////////////// 00325 bool EggPrimitive:: 00326 has_vertex_normal() const { 00327 Vertices::const_iterator vi; 00328 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 00329 if ((*vi)->has_normal()) { 00330 return true; 00331 } 00332 } 00333 return false; 00334 } 00335 00336 //////////////////////////////////////////////////////////////////// 00337 // Function: EggPrimitive::has_vertex_color 00338 // Access: Published 00339 // Description: Returns true if any vertex on the primitive has a 00340 // specific color set, false otherwise. 00341 // 00342 // If you call unify_attributes() first, this will also 00343 // return false even if all the vertices were set to the 00344 // same value (since unify_attributes() removes 00345 // redundant vertex properties). 00346 //////////////////////////////////////////////////////////////////// 00347 bool EggPrimitive:: 00348 has_vertex_color() const { 00349 Vertices::const_iterator vi; 00350 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 00351 if ((*vi)->has_color()) { 00352 return true; 00353 } 00354 } 00355 return false; 00356 } 00357 00358 //////////////////////////////////////////////////////////////////// 00359 // Function: EggPrimitive::unify_attributes 00360 // Access: Published, Virtual 00361 // Description: If the shading property is S_per_vertex, ensures that 00362 // all vertices have a normal and a color, and the 00363 // overall primitive does not. 00364 // 00365 // If the shading property is S_per_face, and this is a 00366 // composite primitive, ensures that all components have 00367 // a normal and a color, and the vertices and overall 00368 // primitive do not. (If this is a simple primitive, 00369 // S_per_face works the same as S_overall, below). 00370 // 00371 // If the shading property is S_overall, ensures that no 00372 // vertices or components have a normal or a color, and 00373 // the overall primitive does (if any exists at all). 00374 // 00375 // After this call, either the primitive will have 00376 // normals or its vertices will, but not both. Ditto 00377 // for colors. 00378 // 00379 // This may create redundant vertices in the vertex 00380 // pool. 00381 //////////////////////////////////////////////////////////////////// 00382 void EggPrimitive:: 00383 unify_attributes(EggPrimitive::Shading shading) { 00384 if (shading == S_unknown) { 00385 shading = get_shading(); 00386 } 00387 00388 // Does the primitive have an explicit color? 00389 if (!has_color() && shading != S_overall) { 00390 if (shading != S_per_vertex) { 00391 // If there is no color set, first we check the vertices. If the 00392 // vertices have a color, we inherit the color from there. 00393 iterator pi; 00394 for (pi = begin(); pi != end() && !has_color(); ++pi) { 00395 EggVertex *vertex = (*pi); 00396 if (vertex->has_color()) { 00397 set_color(vertex->get_color()); 00398 } 00399 } 00400 } 00401 if (!has_color()) { 00402 // If we still don't have a color, the implicit color is white. 00403 set_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 00404 } 00405 } 00406 00407 switch (shading) { 00408 case S_per_vertex: 00409 // Propagate everything to the vertices. 00410 { 00411 iterator pi; 00412 for (pi = begin(); pi != end(); ++pi) { 00413 EggVertex *orig_vertex = (*pi); 00414 PT(EggVertex) vertex = new EggVertex(*orig_vertex); 00415 if (!vertex->has_normal() && has_normal()) { 00416 vertex->copy_normal(*this); 00417 } 00418 if (!vertex->has_color() && has_color()) { 00419 vertex->copy_color(*this); 00420 } 00421 00422 EggVertexPool *vertex_pool = orig_vertex->get_pool(); 00423 nassertv(vertex_pool != (EggVertexPool *)NULL); 00424 vertex = vertex_pool->create_unique_vertex(*vertex); 00425 vertex->copy_grefs_from(*orig_vertex); 00426 replace(pi, vertex); 00427 } 00428 clear_normal(); 00429 clear_color(); 00430 } 00431 break; 00432 00433 case S_per_face: 00434 case S_overall: 00435 // Remove everything from the vertices. 00436 { 00437 iterator pi; 00438 for (pi = begin(); pi != end(); ++pi) { 00439 EggVertex *orig_vertex = (*pi); 00440 PT(EggVertex) vertex = new EggVertex(*orig_vertex); 00441 if (vertex->has_normal()) { 00442 if (!has_normal()) { 00443 copy_normal(*vertex); 00444 } 00445 vertex->clear_normal(); 00446 } 00447 if (vertex->has_color()) { 00448 if (!has_color()) { 00449 copy_color(*vertex); 00450 } 00451 vertex->clear_color(); 00452 } 00453 00454 EggVertexPool *vertex_pool = orig_vertex->get_pool(); 00455 nassertv(vertex_pool != (EggVertexPool *)NULL); 00456 vertex = vertex_pool->create_unique_vertex(*vertex); 00457 vertex->copy_grefs_from(*orig_vertex); 00458 replace(pi, vertex); 00459 } 00460 } 00461 break; 00462 00463 case S_unknown: 00464 break; 00465 } 00466 00467 if (!has_color() && shading == S_overall) { 00468 set_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 00469 } 00470 } 00471 00472 //////////////////////////////////////////////////////////////////// 00473 // Function: EggPrimitive::apply_last_attribute 00474 // Access: Published, Virtual 00475 // Description: Sets the last vertex of the triangle (or each 00476 // component) to the primitive normal and/or color, if 00477 // the primitive is flat-shaded. This reflects the 00478 // OpenGL convention of storing flat-shaded properties on 00479 // the last vertex, although it is not usually a 00480 // convention in Egg. 00481 // 00482 // This may introduce redundant vertices to the vertex 00483 // pool. 00484 //////////////////////////////////////////////////////////////////// 00485 void EggPrimitive:: 00486 apply_last_attribute() { 00487 if (!empty()) { 00488 do_apply_flat_attribute(size() - 1, this); 00489 } 00490 } 00491 00492 //////////////////////////////////////////////////////////////////// 00493 // Function: EggPrimitive::apply_first_attribute 00494 // Access: Published, Virtual 00495 // Description: Sets the first vertex of the triangle (or each 00496 // component) to the primitive normal and/or color, if 00497 // the primitive is flat-shaded. This reflects the 00498 // DirectX convention of storing flat-shaded properties on 00499 // the first vertex, although it is not usually a 00500 // convention in Egg. 00501 // 00502 // This may introduce redundant vertices to the vertex 00503 // pool. 00504 //////////////////////////////////////////////////////////////////// 00505 void EggPrimitive:: 00506 apply_first_attribute() { 00507 if (!empty()) { 00508 do_apply_flat_attribute(0, this); 00509 } 00510 } 00511 00512 //////////////////////////////////////////////////////////////////// 00513 // Function: EggPrimitive::post_apply_flat_attribute 00514 // Access: Published, Virtual 00515 // Description: Intended as a followup to apply_last_attribute(), 00516 // this also sets an attribute on the first vertices of 00517 // the primitive, if they don't already have an 00518 // attribute set, just so they end up with *something*. 00519 //////////////////////////////////////////////////////////////////// 00520 void EggPrimitive:: 00521 post_apply_flat_attribute() { 00522 if (!empty()) { 00523 for (int i = 0; i < (int)size(); i++) { 00524 EggVertex *vertex = get_vertex(i); 00525 00526 // Use set_normal() instead of copy_normal(), to avoid getting 00527 // the morphs--we don't want them here, since we're just putting 00528 // a bogus value on the normal anyway. 00529 00530 if (has_normal() && !vertex->has_normal()) { 00531 vertex->set_normal(get_normal()); 00532 } 00533 if (has_color() && !vertex->has_color()) { 00534 vertex->set_color(get_color()); 00535 } 00536 } 00537 } 00538 } 00539 00540 //////////////////////////////////////////////////////////////////// 00541 // Function: EggPrimitive::reverse_vertex_ordering 00542 // Access: Published, Virtual 00543 // Description: Reverses the ordering of the vertices in this 00544 // primitive, if appropriate, in order to change the 00545 // direction the polygon appears to be facing. Does not 00546 // adjust the surface normal, if any. 00547 //////////////////////////////////////////////////////////////////// 00548 void EggPrimitive:: 00549 reverse_vertex_ordering() { 00550 // This really only makes sense for polygons. Lights don't care 00551 // about vertex ordering, and NURBS surfaces have to do a bit more 00552 // work in addition to this. 00553 reverse(_vertices.begin(), _vertices.end()); 00554 } 00555 00556 //////////////////////////////////////////////////////////////////// 00557 // Function: EggPrimitive::cleanup 00558 // Access: Published, Virtual 00559 // Description: Cleans up modeling errors in whatever context this 00560 // makes sense. For instance, for a polygon, this calls 00561 // remove_doubled_verts(true). For a point, it calls 00562 // remove_nonunique_verts(). Returns true if the 00563 // primitive is valid, or false if it is degenerate. 00564 //////////////////////////////////////////////////////////////////// 00565 bool EggPrimitive:: 00566 cleanup() { 00567 return !empty(); 00568 } 00569 00570 //////////////////////////////////////////////////////////////////// 00571 // Function: EggPrimitive::remove_doubled_verts 00572 // Access: Published 00573 // Description: Certain kinds of primitives, particularly polygons, 00574 // don't like to have the same vertex repeated 00575 // consecutively. Unfortunately, some modeling programs 00576 // (like MultiGen) make this an easy mistake to make. 00577 // 00578 // It's handy to have a function to remove these 00579 // redundant vertices. If closed is true, it also 00580 // checks that the first and last vertices are not the 00581 // same. 00582 // 00583 // This function identifies repeated vertices by 00584 // position only; it does not consider any other 00585 // properties, such as color or UV, significant in 00586 // differentiating vertices. 00587 //////////////////////////////////////////////////////////////////// 00588 void EggPrimitive:: 00589 remove_doubled_verts(bool closed) { 00590 if (!_vertices.empty()) { 00591 Vertices new_vertices; 00592 Vertices::iterator vi, vlast; 00593 vi = _vertices.begin(); 00594 new_vertices.push_back(*vi); 00595 int num_removed = 0; 00596 00597 vlast = vi; 00598 ++vi; 00599 while (vi != _vertices.end()) { 00600 if ((*vi)->get_pos4() != (*vlast)->get_pos4()) { 00601 new_vertices.push_back(*vi); 00602 } else { 00603 prepare_remove_vertex(*vi, vi - _vertices.begin() - num_removed, 00604 _vertices.size() - num_removed); 00605 num_removed++; 00606 } 00607 vlast = vi; 00608 ++vi; 00609 } 00610 _vertices.swap(new_vertices); 00611 } 00612 00613 if (closed) { 00614 // Then, if this is a polygon (which will be closed anyway), 00615 // remove the vertex from the end if it's a repeat of the 00616 // beginning. 00617 while (_vertices.size() > 1 && 00618 _vertices.back()->get_pos4() == _vertices.front()->get_pos4()) { 00619 prepare_remove_vertex(_vertices.back(), _vertices.size() - 1, 00620 _vertices.size()); 00621 _vertices.pop_back(); 00622 } 00623 } 00624 } 00625 00626 //////////////////////////////////////////////////////////////////// 00627 // Function: EggPrimitive::remove_nonunique_verts 00628 // Access: Published 00629 // Description: Removes any multiple appearances of the same vertex 00630 // from the primitive. This primarily makes sense for a 00631 // point primitive, which is really a collection of 00632 // points and which doesn't make sense to include the 00633 // same point twice, in any order. 00634 //////////////////////////////////////////////////////////////////// 00635 void EggPrimitive:: 00636 remove_nonunique_verts() { 00637 Vertices::iterator vi, vj; 00638 Vertices new_vertices; 00639 int num_removed = 0; 00640 00641 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 00642 bool okflag = true; 00643 for (vj = _vertices.begin(); vj != vi && okflag; ++vj) { 00644 okflag = ((*vi) != (*vj)); 00645 } 00646 if (okflag) { 00647 new_vertices.push_back(*vi); 00648 } else { 00649 prepare_remove_vertex(*vi, vi - _vertices.begin() - num_removed, 00650 _vertices.size() - num_removed); 00651 num_removed++; 00652 } 00653 } 00654 00655 _vertices.swap(new_vertices); 00656 } 00657 00658 //////////////////////////////////////////////////////////////////// 00659 // Function: EggPrimitive::has_primitives 00660 // Access: Published, Virtual 00661 // Description: Returns true if there are any primitives 00662 // (e.g. polygons) defined within this group or below, 00663 // false otherwise. 00664 //////////////////////////////////////////////////////////////////// 00665 bool EggPrimitive:: 00666 has_primitives() const { 00667 return true; 00668 } 00669 00670 //////////////////////////////////////////////////////////////////// 00671 // Function: EggPrimitive::joint_has_primitives 00672 // Access: Published, Virtual 00673 // Description: Returns true if there are any primitives 00674 // (e.g. polygons) defined within this group or below, 00675 // but the search does not include nested joints. 00676 //////////////////////////////////////////////////////////////////// 00677 bool EggPrimitive:: 00678 joint_has_primitives() const { 00679 return true; 00680 } 00681 00682 //////////////////////////////////////////////////////////////////// 00683 // Function: EggPrimitive::has_normals 00684 // Access: Published, Virtual 00685 // Description: Returns true if any of the primitives (e.g. polygons) 00686 // defined within this group or below have either face 00687 // or vertex normals defined, false otherwise. 00688 //////////////////////////////////////////////////////////////////// 00689 bool EggPrimitive:: 00690 has_normals() const { 00691 if (has_normal()) { 00692 return true; 00693 } 00694 00695 const_iterator vi; 00696 for (vi = begin(); vi != end(); ++vi) { 00697 if ((*vi)->has_normal()) { 00698 return true; 00699 } 00700 } 00701 00702 return false; 00703 } 00704 00705 00706 //////////////////////////////////////////////////////////////////// 00707 // Function: EggPrimitive::erase 00708 // Access: Public 00709 // Description: Part of the implementaion of the EggPrimitive as an 00710 // STL container. Most of the rest of these functions 00711 // are inline and declared in EggPrimitive.I. 00712 //////////////////////////////////////////////////////////////////// 00713 EggPrimitive::iterator EggPrimitive:: 00714 erase(iterator first, iterator last) { 00715 iterator i; 00716 int num_removed = 0; 00717 for (i = first; i != last; ++i) { 00718 prepare_remove_vertex(*i, first - _vertices.begin(), 00719 _vertices.size() - num_removed); 00720 num_removed++; 00721 } 00722 iterator result = _vertices.erase((Vertices::iterator &)first, 00723 (Vertices::iterator &)last); 00724 test_vref_integrity(); 00725 return result; 00726 } 00727 00728 //////////////////////////////////////////////////////////////////// 00729 // Function: EggPrimitive::find 00730 // Access: Public 00731 // Description: Returns the iterator pointing to the indicated 00732 // vertex, or end() if the vertex is not part of the 00733 // primitive. 00734 //////////////////////////////////////////////////////////////////// 00735 EggPrimitive::iterator EggPrimitive:: 00736 find(EggVertex *vertex) { 00737 PT_EggVertex vpt = vertex; 00738 return ::find(begin(), end(), vpt); 00739 } 00740 00741 00742 //////////////////////////////////////////////////////////////////// 00743 // Function: EggPrimitive::add_vertex 00744 // Access: Published 00745 // Description: Adds the indicated vertex to the end of the 00746 // primitive's list of vertices, and returns it. 00747 //////////////////////////////////////////////////////////////////// 00748 EggVertex *EggPrimitive:: 00749 add_vertex(EggVertex *vertex) { 00750 prepare_add_vertex(vertex, _vertices.size(), _vertices.size() + 1); 00751 _vertices.push_back(vertex); 00752 00753 vertex->test_pref_integrity(); 00754 test_vref_integrity(); 00755 00756 return vertex; 00757 } 00758 00759 //////////////////////////////////////////////////////////////////// 00760 // Function: EggPrimitive::remove_vertex 00761 // Access: Published 00762 // Description: Removes the indicated vertex from the 00763 // primitive and returns it. If the vertex was not 00764 // already in the primitive, does nothing and returns 00765 // NULL. 00766 //////////////////////////////////////////////////////////////////// 00767 EggVertex *EggPrimitive:: 00768 remove_vertex(EggVertex *vertex) { 00769 PT_EggVertex vpt = vertex; 00770 iterator i = ::find(begin(), end(), vpt); 00771 if (i == end()) { 00772 return PT_EggVertex(); 00773 } else { 00774 // erase() calls prepare_remove_vertex(). 00775 erase(i); 00776 00777 vertex->test_pref_integrity(); 00778 test_vref_integrity(); 00779 00780 return vertex; 00781 } 00782 } 00783 00784 00785 //////////////////////////////////////////////////////////////////// 00786 // Function: EggPrimitive::copy_vertices 00787 // Access: Published 00788 // Description: Replaces the current primitive's list of vertices 00789 // with a copy of the list of vertices on the other 00790 // primitive. 00791 //////////////////////////////////////////////////////////////////// 00792 void EggPrimitive:: 00793 copy_vertices(const EggPrimitive &other) { 00794 clear(); 00795 _vertices.reserve(other.size()); 00796 00797 iterator vi; 00798 for (vi = other.begin(); vi != other.end(); ++vi) { 00799 add_vertex(*vi); 00800 } 00801 00802 test_vref_integrity(); 00803 other.test_vref_integrity(); 00804 } 00805 00806 #ifndef NDEBUG 00807 00808 //////////////////////////////////////////////////////////////////// 00809 // Function: EggPrimitive::test_vref_integrity 00810 // Access: Published 00811 // Description: Verifies that each vertex in the primitive exists and 00812 // that it knows it is referenced by the primitive. 00813 //////////////////////////////////////////////////////////////////// 00814 void EggPrimitive:: 00815 test_vref_integrity() const { 00816 test_ref_count_integrity(); 00817 00818 if ((int)size() <= egg_test_vref_integrity) { 00819 // First, we need to know how many times each vertex appears. 00820 // Usually, this will be only one, but it's possible for a vertex to 00821 // appear more than once. 00822 typedef pmap<const EggVertex *, int> VertexCount; 00823 VertexCount _count; 00824 00825 // Now count up the vertices. 00826 iterator vi; 00827 for (vi = begin(); vi != end(); ++vi) { 00828 const EggVertex *vert = *vi; 00829 vert->test_ref_count_integrity(); 00830 00831 VertexCount::iterator vci = _count.find(vert); 00832 if (vci == _count.end()) { 00833 _count[vert] = 1; 00834 } else { 00835 (*vci).second++; 00836 } 00837 } 00838 00839 // Ok, now walk through the vertices found and make sure the vertex 00840 // has the proper number of entries of this primitive in its pref. 00841 VertexCount::iterator vci; 00842 for (vci = _count.begin(); vci != _count.end(); ++vci) { 00843 const EggVertex *vert = (*vci).first; 00844 00845 int count = (*vci).second; 00846 int vert_count = vert->has_pref(this); 00847 00848 nassertv(count == vert_count); 00849 } 00850 } 00851 } 00852 00853 #endif // NDEBUG 00854 00855 //////////////////////////////////////////////////////////////////// 00856 // Function: EggPrimitive::prepare_add_vertex 00857 // Access: Protected, Virtual 00858 // Description: Marks the vertex as belonging to the primitive. This 00859 // is an internal function called by the STL-like 00860 // functions push_back() and insert(), in preparation 00861 // for actually adding the vertex. 00862 // 00863 // i indicates the new position of the vertex in the 00864 // list; n indicates the new number of vertices after 00865 // the operation has completed. 00866 //////////////////////////////////////////////////////////////////// 00867 void EggPrimitive:: 00868 prepare_add_vertex(EggVertex *vertex, int i, int n) { 00869 // We can't test integrity within this function, because it might be 00870 // called when the primitive is in an incomplete state. 00871 00872 // The vertex must have the same vertex pool as the vertices already 00873 // added. 00874 nassertv(empty() || vertex->get_pool() == get_pool()); 00875 00876 // Since a given vertex might appear more than once in a particular 00877 // primitive, we can't conclude anything about data integrity by 00878 // inspecting the return value of insert(). (In fact, the vertex's 00879 // pref is a multiset, so the insert() will always succeed.) 00880 00881 vertex->_pref.insert(this); 00882 } 00883 00884 00885 //////////////////////////////////////////////////////////////////// 00886 // Function: EggPrimitive::prepare_remove_vertex 00887 // Access: Protected, Virtual 00888 // Description: Marks the vertex as removed from the primitive. This 00889 // is an internal function called by the STL-like 00890 // functions pop_back() and erase(), in preparation for 00891 // actually doing the removal. 00892 // 00893 // i indicates the former position of the vertex in the 00894 // list; n indicates the current number of vertices 00895 // before the operation has completed. 00896 // 00897 // It is an error to attempt to remove a vertex that is 00898 // not already a vertex of this primitive. 00899 //////////////////////////////////////////////////////////////////// 00900 void EggPrimitive:: 00901 prepare_remove_vertex(EggVertex *vertex, int i, int n) { 00902 // We can't test integrity within this function, because it might be 00903 // called when the primitive is in an incomplete state. 00904 00905 // Now we must remove the primitive from the vertex's pref. We 00906 // can't just use the simple erase() function, since that will 00907 // remove all instances of this primitive from the pref; instead, we 00908 // must find one instance and remove that. 00909 00910 EggVertex::PrimitiveRef::iterator pri = vertex->_pref.find(this); 00911 00912 // We should have found the primitive in the vertex's pref. If we 00913 // did not, something's out of sync internally. 00914 nassertv(pri != vertex->_pref.end()); 00915 00916 vertex->_pref.erase(pri); 00917 } 00918 00919 //////////////////////////////////////////////////////////////////// 00920 // Function: EggPrimitive::write_body 00921 // Access: Protected 00922 // Description: Writes the attributes and the vertices referenced by 00923 // the primitive to the indicated output stream in Egg 00924 // format. 00925 //////////////////////////////////////////////////////////////////// 00926 void EggPrimitive:: 00927 write_body(ostream &out, int indent_level) const { 00928 test_vref_integrity(); 00929 00930 EggAttributes::write(out, indent_level); 00931 EggRenderMode::write(out, indent_level); 00932 00933 int num_textures = get_num_textures(); 00934 for (int i = 0; i < num_textures; i++) { 00935 EggTexture *texture = get_texture(i); 00936 00937 indent(out, indent_level) << "<TRef> { "; 00938 enquote_string(out, texture->get_name()) 00939 << " }\n"; 00940 } 00941 00942 if (has_material()) { 00943 EggMaterial *material = get_material(); 00944 00945 indent(out, indent_level) << "<MRef> { "; 00946 enquote_string(out, material->get_name()) 00947 << " }\n"; 00948 } 00949 00950 if (get_bface_flag()) { 00951 indent(out, indent_level) << "<BFace> { 1 }\n"; 00952 } 00953 00954 if (!empty()) { 00955 EggVertexPool *pool = get_pool(); 00956 00957 // Make sure the vertices belong to some vertex pool. 00958 nassertv(pool != NULL); 00959 00960 // Make sure the vertex pool is named. 00961 nassertv(pool->has_name()); 00962 00963 if ((int)size() < 10) { 00964 // A simple primitive gets all its vertex indices written on one 00965 // line. 00966 indent(out, indent_level) << "<VertexRef> {"; 00967 const_iterator i; 00968 for (i = begin(); i != end(); ++i) { 00969 EggVertex *vert = *i; 00970 vert->test_pref_integrity(); 00971 00972 // Make sure each vertex belongs to the same pool. 00973 nassertv(vert->get_pool() == pool); 00974 00975 out << " " << vert->get_index(); 00976 } 00977 out << " <Ref> { "; 00978 enquote_string(out, pool->get_name()) << " } }\n"; 00979 00980 } else { 00981 00982 // A larger primitive gets its vertex indices written as 00983 // multiple lines. 00984 vector_int indices; 00985 const_iterator i; 00986 for (i = begin(); i != end(); ++i) { 00987 EggVertex *vert = *i; 00988 vert->test_pref_integrity(); 00989 00990 // Make sure each vertex belongs to the same pool. 00991 nassertv(vert->get_pool() == pool); 00992 00993 indices.push_back(vert->get_index()); 00994 } 00995 00996 indent(out, indent_level) << "<VertexRef> {\n"; 00997 write_long_list(out, indent_level+2, indices.begin(), indices.end(), 00998 "", "", 72); 00999 indent(out, indent_level+2) << "<Ref> { "; 01000 enquote_string(out, pool->get_name()) << " }\n"; 01001 indent(out, indent_level) << "}\n"; 01002 } 01003 } 01004 } 01005 01006 //////////////////////////////////////////////////////////////////// 01007 // Function: EggPrimitive::egg_start_parse_body 01008 // Access: Protected, Virtual 01009 // Description: This function is called within parse_egg(). It 01010 // should call the appropriate function on the lexer to 01011 // initialize the parser into the state associated with 01012 // this object. If the object cannot be parsed into 01013 // directly, it should return false. 01014 //////////////////////////////////////////////////////////////////// 01015 bool EggPrimitive:: 01016 egg_start_parse_body() { 01017 egg_start_primitive_body(); 01018 return true; 01019 } 01020 01021 //////////////////////////////////////////////////////////////////// 01022 // Function: EggPrimitive::r_transform 01023 // Access: Protected, Virtual 01024 // Description: This is called from within the egg code by 01025 // transform(). It applies a transformation matrix 01026 // to the current node in some sensible way, then 01027 // continues down the tree. 01028 // 01029 // The first matrix is the transformation to apply; the 01030 // second is its inverse. The third parameter is the 01031 // coordinate system we are changing to, or CS_default 01032 // if we are not changing coordinate systems. 01033 //////////////////////////////////////////////////////////////////// 01034 void EggPrimitive:: 01035 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) { 01036 EggAttributes::transform(mat); 01037 } 01038 01039 //////////////////////////////////////////////////////////////////// 01040 // Function: EggPrimitive::r_flatten_transforms 01041 // Access: Protected, Virtual 01042 // Description: The recursive implementation of flatten_transforms(). 01043 //////////////////////////////////////////////////////////////////// 01044 void EggPrimitive:: 01045 r_flatten_transforms() { 01046 if (is_local_coord()) { 01047 LMatrix4d mat = get_vertex_frame(); 01048 EggAttributes::transform(mat); 01049 01050 // Transform each vertex by duplicating it in the vertex pool. 01051 size_t num_vertices = size(); 01052 for (size_t i = 0; i < num_vertices; i++) { 01053 EggVertex *vertex = get_vertex(i); 01054 EggVertexPool *pool = vertex->get_pool(); 01055 01056 EggVertex new_vertex(*vertex); 01057 new_vertex.transform(mat); 01058 EggVertex *unique = pool->create_unique_vertex(new_vertex); 01059 unique->copy_grefs_from(*vertex); 01060 01061 set_vertex(i, unique); 01062 } 01063 } 01064 } 01065 01066 //////////////////////////////////////////////////////////////////// 01067 // Function: EggPrimitive::r_apply_texmats 01068 // Access: Protected, Virtual 01069 // Description: The recursive implementation of apply_texmats(). 01070 //////////////////////////////////////////////////////////////////// 01071 void EggPrimitive:: 01072 r_apply_texmats(EggTextureCollection &textures) { 01073 Textures new_textures; 01074 Textures::const_iterator ti; 01075 for (ti = _textures.begin(); ti != _textures.end(); ++ti) { 01076 EggTexture *texture = (*ti); 01077 01078 if (!texture->has_transform()) { 01079 new_textures.push_back(texture); 01080 01081 } else if (texture->transform_is_identity()) { 01082 // Now, what's the point of a texture with an identity 01083 // transform? 01084 texture->clear_transform(); 01085 new_textures.push_back(texture); 01086 01087 } else { 01088 01089 // We've got a texture with a matrix applied. Save the matrix, 01090 // and get a new texture without the matrix. 01091 LMatrix4d mat = texture->get_transform3d(); 01092 EggTexture new_texture(*texture); 01093 new_texture.clear_transform(); 01094 EggTexture *unique = textures.create_unique_texture(new_texture, ~0); 01095 01096 new_textures.push_back(unique); 01097 string uv_name = unique->get_uv_name(); 01098 01099 // Now apply the matrix to the vertex UV's. Create new vertices 01100 // as necessary. 01101 size_t num_vertices = size(); 01102 for (size_t i = 0; i < num_vertices; i++) { 01103 EggVertex *vertex = get_vertex(i); 01104 01105 const EggVertexUV *uv_obj = vertex->get_uv_obj(uv_name); 01106 if (uv_obj != (EggVertexUV *)NULL) { 01107 EggVertex new_vertex(*vertex); 01108 PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj); 01109 TexCoord3d uvw = uv_obj->get_uvw() * mat; 01110 if (uv_obj->has_w() || texture->has_transform3d()) { 01111 new_uv_obj->set_uvw(uvw); 01112 } else { 01113 new_uv_obj->set_uv(TexCoordd(uvw[0], uvw[1])); 01114 } 01115 new_vertex.set_uv_obj(new_uv_obj); 01116 01117 EggVertexPool *pool = vertex->get_pool(); 01118 EggVertex *unique = pool->create_unique_vertex(new_vertex); 01119 unique->copy_grefs_from(*vertex); 01120 01121 set_vertex(i, unique); 01122 } 01123 } 01124 } 01125 } 01126 01127 _textures.swap(new_textures); 01128 } 01129 01130 //////////////////////////////////////////////////////////////////// 01131 // Function: EggPrimitive::apply_attribute_to_vertex 01132 // Access: Protected 01133 // Description: This is used to implement apply_first_attribute() and 01134 // apply_last_attribute(). It copies the indicated 01135 // attributes to the specified vertex. 01136 //////////////////////////////////////////////////////////////////// 01137 void EggPrimitive:: 01138 do_apply_flat_attribute(int vertex_index, EggAttributes *attrib) { 01139 // The significant_change flag is set if we have changed the 01140 // vertex in some important way, that will invalidate it for other 01141 // primitives that might share it. We don't consider *adding* a 01142 // normal where there wasn't one before to be significant, but we 01143 // do consider it significant to change a vertex's normal to 01144 // something different. Similarly for color. 01145 bool significant_change = false; 01146 01147 EggVertex *orig_vertex = get_vertex(vertex_index); 01148 PT(EggVertex) new_vertex = new EggVertex(*orig_vertex); 01149 01150 if (attrib->has_normal()) { 01151 new_vertex->copy_normal(*attrib); 01152 01153 if (orig_vertex->has_normal() && 01154 !orig_vertex->matches_normal(*new_vertex)) { 01155 significant_change = true; 01156 } 01157 } else if (has_normal()) { 01158 new_vertex->copy_normal(*this); 01159 01160 if (orig_vertex->has_normal() && 01161 !orig_vertex->matches_normal(*new_vertex)) { 01162 significant_change = true; 01163 } 01164 } 01165 01166 if (attrib->has_color()) { 01167 new_vertex->copy_color(*attrib); 01168 01169 if (orig_vertex->has_color() && 01170 !orig_vertex->matches_color(*new_vertex)) { 01171 significant_change = true; 01172 } 01173 } else if (has_color()) { 01174 new_vertex->copy_color(*this); 01175 01176 if (orig_vertex->has_color() && 01177 !orig_vertex->matches_color(*new_vertex)) { 01178 significant_change = true; 01179 } 01180 } 01181 01182 if (significant_change) { 01183 new_vertex = get_pool()->create_unique_vertex(*new_vertex); 01184 new_vertex->copy_grefs_from(*orig_vertex); 01185 set_vertex(vertex_index, new_vertex); 01186 } else { 01187 // Just copy the new attributes back into the pool. 01188 ((EggAttributes *)orig_vertex)->operator = (*new_vertex); 01189 } 01190 } 01191 01192 //////////////////////////////////////////////////////////////////// 01193 // Function: EggPrimitive::set_connected_shading 01194 // Access: Private 01195 // Description: Recursively updates the connected_shading member in 01196 // all connected primitives. 01197 //////////////////////////////////////////////////////////////////// 01198 void EggPrimitive:: 01199 set_connected_shading(EggPrimitive::Shading shading, 01200 const EggAttributes *neighbor) { 01201 ConnectedShadingNodes connected_nodes; 01202 01203 r_set_connected_shading(0, shading, neighbor, connected_nodes); 01204 01205 // Pick up any additional nodes we couldn't visit because of the 01206 // stack depth restrictions. 01207 while (!connected_nodes.empty()) { 01208 ConnectedShadingNodes next_nodes; 01209 next_nodes.swap(connected_nodes); 01210 01211 ConnectedShadingNodes::iterator ni; 01212 for (ni = next_nodes.begin(); ni != next_nodes.end(); ++ni) { 01213 r_set_connected_shading(0, (*ni)._shading, (*ni)._neighbor, connected_nodes); 01214 } 01215 } 01216 } 01217 01218 //////////////////////////////////////////////////////////////////// 01219 // Function: EggPrimitive::r_set_connected_shading 01220 // Access: Private 01221 // Description: Implements set_connected_shading, with some 01222 // restrictions to prevent stack overflow. 01223 //////////////////////////////////////////////////////////////////// 01224 void EggPrimitive:: 01225 r_set_connected_shading(int stack_depth, EggPrimitive::Shading shading, 01226 const EggAttributes *neighbor, 01227 ConnectedShadingNodes &next_nodes) { 01228 if (stack_depth > 10000) { 01229 // Too deep. Limit recursion. 01230 ConnectedShadingNode next; 01231 next._shading = shading; 01232 next._neighbor = neighbor; 01233 next_nodes.push_back(next); 01234 return; 01235 } 01236 01237 bool propagate = false; 01238 01239 if (_connected_shading == S_unknown) { 01240 // We haven't visited this node before; propagate now. 01241 _connected_shading = get_shading(); 01242 propagate = true; 01243 } 01244 01245 if (shading > _connected_shading) { 01246 // More specific information just came in. Save it, and propagate 01247 // it to all connected primitives. 01248 _connected_shading = shading; 01249 propagate = true; 01250 01251 } else if (shading == S_overall && _connected_shading == S_overall) { 01252 // If both neighbors are overall shaded, check if the two 01253 // neighbors have different properties. If they do, elevate to 01254 // per_face. 01255 bool matches_normal = this->matches_normal(*neighbor); 01256 bool matches_color = this->matches_color(*neighbor); 01257 01258 if (!matches_color) { 01259 // Make a special case for not having an overall color: that's 01260 // implicitly white. 01261 if (!neighbor->has_color() && has_color() && _drgbas.empty() && 01262 get_color() == Colorf(1.0f, 1.0f, 1.0f, 1.0f)) { 01263 matches_color = true; 01264 } else if (!has_color() && neighbor->has_color() && neighbor->_drgbas.empty() && 01265 neighbor->get_color() == Colorf(1.0f, 1.0f, 1.0f, 1.0f)) { 01266 matches_color = true; 01267 } 01268 } 01269 if (!matches_normal || !matches_color) { 01270 _connected_shading = S_per_face; 01271 propagate = true; 01272 } 01273 } 01274 01275 if (propagate) { 01276 Vertices::const_iterator vi; 01277 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { 01278 EggVertex *vertex = (*vi); 01279 EggVertex::PrimitiveRef::const_iterator pi; 01280 for (pi = vertex->pref_begin(); 01281 pi != vertex->pref_end(); 01282 ++pi) { 01283 (*pi)->r_set_connected_shading(stack_depth + 1, _connected_shading, this, 01284 next_nodes); 01285 } 01286 } 01287 } 01288 }