Panda3D

eggPrimitive.cxx

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 }
 All Classes Functions Variables Enumerations