Panda3D
 All Classes Functions Variables Enumerations
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(LColor(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(LColor(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   pset<EggVertex *> unique_vertices;
00642   for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00643     bool inserted = unique_vertices.insert(*vi).second;
00644     if (inserted) {
00645       new_vertices.push_back(*vi);
00646     } else {
00647       prepare_remove_vertex(*vi, vi - _vertices.begin() - num_removed,
00648                             _vertices.size() - num_removed);
00649       num_removed++;
00650     }
00651   }
00652 
00653   _vertices.swap(new_vertices);
00654 }
00655 
00656 ////////////////////////////////////////////////////////////////////
00657 //     Function: EggPrimitive::has_primitives
00658 //       Access: Published, Virtual
00659 //  Description: Returns true if there are any primitives
00660 //               (e.g. polygons) defined within this group or below,
00661 //               false otherwise.
00662 ////////////////////////////////////////////////////////////////////
00663 bool EggPrimitive::
00664 has_primitives() const {
00665   return true;
00666 }
00667 
00668 ////////////////////////////////////////////////////////////////////
00669 //     Function: EggPrimitive::joint_has_primitives
00670 //       Access: Published, Virtual
00671 //  Description: Returns true if there are any primitives
00672 //               (e.g. polygons) defined within this group or below,
00673 //               but the search does not include nested joints.
00674 ////////////////////////////////////////////////////////////////////
00675 bool EggPrimitive::
00676 joint_has_primitives() const {
00677   return true;
00678 }
00679 
00680 ////////////////////////////////////////////////////////////////////
00681 //     Function: EggPrimitive::has_normals
00682 //       Access: Published, Virtual
00683 //  Description: Returns true if any of the primitives (e.g. polygons)
00684 //               defined within this group or below have either face
00685 //               or vertex normals defined, false otherwise.
00686 ////////////////////////////////////////////////////////////////////
00687 bool EggPrimitive::
00688 has_normals() const {
00689   if (has_normal()) {
00690     return true;
00691   }
00692 
00693   const_iterator vi;
00694   for (vi = begin(); vi != end(); ++vi) {
00695     if ((*vi)->has_normal()) {
00696       return true;
00697     }
00698   }
00699 
00700   return false;
00701 }
00702 
00703 
00704 ////////////////////////////////////////////////////////////////////
00705 //     Function: EggPrimitive::erase
00706 //       Access: Public
00707 //  Description: Part of the implementaion of the EggPrimitive as an
00708 //               STL container.  Most of the rest of these functions
00709 //               are inline and declared in EggPrimitive.I.
00710 ////////////////////////////////////////////////////////////////////
00711 EggPrimitive::iterator EggPrimitive::
00712 erase(iterator first, iterator last) {
00713   iterator i;
00714   int num_removed = 0;
00715   for (i = first; i != last; ++i) {
00716     prepare_remove_vertex(*i, first - _vertices.begin(), 
00717                           _vertices.size() - num_removed);
00718     num_removed++;
00719   }
00720   iterator result = _vertices.erase((Vertices::iterator &)first,
00721                                     (Vertices::iterator &)last);
00722   test_vref_integrity();
00723   return result;
00724 }
00725 
00726 ////////////////////////////////////////////////////////////////////
00727 //     Function: EggPrimitive::find
00728 //       Access: Public
00729 //  Description: Returns the iterator pointing to the indicated
00730 //               vertex, or end() if the vertex is not part of the
00731 //               primitive.
00732 ////////////////////////////////////////////////////////////////////
00733 EggPrimitive::iterator EggPrimitive::
00734 find(EggVertex *vertex) {
00735   PT_EggVertex vpt = vertex;
00736   return ::find(begin(), end(), vpt);
00737 }
00738 
00739 
00740 ////////////////////////////////////////////////////////////////////
00741 //     Function: EggPrimitive::add_vertex
00742 //       Access: Published
00743 //  Description: Adds the indicated vertex to the end of the
00744 //               primitive's list of vertices, and returns it.
00745 ////////////////////////////////////////////////////////////////////
00746 EggVertex *EggPrimitive::
00747 add_vertex(EggVertex *vertex) {
00748   prepare_add_vertex(vertex, _vertices.size(), _vertices.size() + 1);
00749   _vertices.push_back(vertex);
00750 
00751   vertex->test_pref_integrity();
00752   test_vref_integrity();
00753 
00754   return vertex;
00755 }
00756 
00757 ////////////////////////////////////////////////////////////////////
00758 //     Function: EggPrimitive::remove_vertex
00759 //       Access: Published
00760 //  Description: Removes the indicated vertex from the
00761 //               primitive and returns it.  If the vertex was not
00762 //               already in the primitive, does nothing and returns
00763 //               NULL.
00764 ////////////////////////////////////////////////////////////////////
00765 EggVertex *EggPrimitive::
00766 remove_vertex(EggVertex *vertex) {
00767   PT_EggVertex vpt = vertex;
00768   iterator i = ::find(begin(), end(), vpt);
00769   if (i == end()) {
00770     return PT_EggVertex();
00771   } else {
00772     // erase() calls prepare_remove_vertex().
00773     erase(i);
00774 
00775     vertex->test_pref_integrity();
00776     test_vref_integrity();
00777 
00778     return vertex;
00779   }
00780 }
00781 
00782 
00783 ////////////////////////////////////////////////////////////////////
00784 //     Function: EggPrimitive::copy_vertices
00785 //       Access: Published
00786 //  Description: Replaces the current primitive's list of vertices
00787 //               with a copy of the list of vertices on the other
00788 //               primitive.
00789 ////////////////////////////////////////////////////////////////////
00790 void EggPrimitive::
00791 copy_vertices(const EggPrimitive &other) {
00792   clear();
00793   _vertices.reserve(other.size());
00794 
00795   iterator vi;
00796   for (vi = other.begin(); vi != other.end(); ++vi) {
00797     add_vertex(*vi);
00798   }
00799 
00800   test_vref_integrity();
00801   other.test_vref_integrity();
00802 }
00803 
00804 #ifdef _DEBUG
00805 
00806 ////////////////////////////////////////////////////////////////////
00807 //     Function: EggPrimitive::test_vref_integrity
00808 //       Access: Published
00809 //  Description: Verifies that each vertex in the primitive exists and
00810 //               that it knows it is referenced by the primitive.
00811 ////////////////////////////////////////////////////////////////////
00812 void EggPrimitive::
00813 test_vref_integrity() const {
00814   test_ref_count_integrity();
00815   
00816   if ((int)size() <= egg_test_vref_integrity) {
00817     // First, we need to know how many times each vertex appears.
00818     // Usually, this will be only one, but it's possible for a vertex to
00819     // appear more than once.
00820     typedef pmap<const EggVertex *, int> VertexCount;
00821     VertexCount _count;
00822     
00823     // Now count up the vertices.
00824     iterator vi;
00825     for (vi = begin(); vi != end(); ++vi) {
00826       const EggVertex *vert = *vi;
00827       vert->test_ref_count_integrity();
00828       
00829       VertexCount::iterator vci = _count.find(vert);
00830       if (vci == _count.end()) {
00831         _count[vert] = 1;
00832       } else {
00833         (*vci).second++;
00834       }
00835     }
00836     
00837     // Ok, now walk through the vertices found and make sure the vertex
00838     // has the proper number of entries of this primitive in its pref.
00839     VertexCount::iterator vci;
00840     for (vci = _count.begin(); vci != _count.end(); ++vci) {
00841       const EggVertex *vert = (*vci).first;
00842       
00843       int count = (*vci).second;
00844       int vert_count = vert->has_pref(this);
00845       
00846       nassertv(count == vert_count);
00847     }
00848   }
00849 }
00850 
00851 #endif  // _DEBUG
00852 
00853 ////////////////////////////////////////////////////////////////////
00854 //     Function: EggPrimitive::prepare_add_vertex
00855 //       Access: Protected, Virtual
00856 //  Description: Marks the vertex as belonging to the primitive.  This
00857 //               is an internal function called by the STL-like
00858 //               functions push_back() and insert(), in preparation
00859 //               for actually adding the vertex.
00860 //
00861 //               i indicates the new position of the vertex in the
00862 //               list; n indicates the new number of vertices after
00863 //               the operation has completed.
00864 ////////////////////////////////////////////////////////////////////
00865 void EggPrimitive::
00866 prepare_add_vertex(EggVertex *vertex, int i, int n) {
00867   // We can't test integrity within this function, because it might be
00868   // called when the primitive is in an incomplete state.
00869 
00870   // The vertex must have the same vertex pool as the vertices already
00871   // added.
00872   nassertv(empty() || vertex->get_pool() == get_pool());
00873 
00874   // Since a given vertex might appear more than once in a particular
00875   // primitive, we can't conclude anything about data integrity by
00876   // inspecting the return value of insert().  (In fact, the vertex's
00877   // pref is a multiset, so the insert() will always succeed.)
00878 
00879   vertex->_pref.insert(this);
00880 }
00881 
00882 
00883 ////////////////////////////////////////////////////////////////////
00884 //     Function: EggPrimitive::prepare_remove_vertex
00885 //       Access: Protected, Virtual
00886 //  Description: Marks the vertex as removed from the primitive.  This
00887 //               is an internal function called by the STL-like
00888 //               functions pop_back() and erase(), in preparation for
00889 //               actually doing the removal.
00890 //
00891 //               i indicates the former position of the vertex in the
00892 //               list; n indicates the current number of vertices
00893 //               before the operation has completed.
00894 //
00895 //               It is an error to attempt to remove a vertex that is
00896 //               not already a vertex of this primitive.
00897 ////////////////////////////////////////////////////////////////////
00898 void EggPrimitive::
00899 prepare_remove_vertex(EggVertex *vertex, int i, int n) {
00900   // We can't test integrity within this function, because it might be
00901   // called when the primitive is in an incomplete state.
00902 
00903   // Now we must remove the primitive from the vertex's pref.  We
00904   // can't just use the simple erase() function, since that will
00905   // remove all instances of this primitive from the pref; instead, we
00906   // must find one instance and remove that.
00907 
00908   EggVertex::PrimitiveRef::iterator pri = vertex->_pref.find(this);
00909 
00910   // We should have found the primitive in the vertex's pref.  If we
00911   // did not, something's out of sync internally.
00912   nassertv(pri != vertex->_pref.end());
00913 
00914   vertex->_pref.erase(pri);
00915 }
00916 
00917 ////////////////////////////////////////////////////////////////////
00918 //     Function: EggPrimitive::write_body
00919 //       Access: Protected
00920 //  Description: Writes the attributes and the vertices referenced by
00921 //               the primitive to the indicated output stream in Egg
00922 //               format.
00923 ////////////////////////////////////////////////////////////////////
00924 void EggPrimitive::
00925 write_body(ostream &out, int indent_level) const {
00926   test_vref_integrity();
00927 
00928   EggAttributes::write(out, indent_level);
00929   EggRenderMode::write(out, indent_level);
00930 
00931   int num_textures = get_num_textures();
00932   for (int i = 0; i < num_textures; i++) {
00933     EggTexture *texture = get_texture(i);
00934 
00935     indent(out, indent_level) << "<TRef> { ";
00936     enquote_string(out, texture->get_name())
00937       << " }\n";
00938   }
00939 
00940   if (has_material()) {
00941     EggMaterial *material = get_material();
00942 
00943     indent(out, indent_level) << "<MRef> { ";
00944     enquote_string(out, material->get_name())
00945       << " }\n";
00946   }
00947 
00948   if (get_bface_flag()) {
00949     indent(out, indent_level) << "<BFace> { 1 }\n";
00950   }
00951 
00952   if (!empty()) {
00953     EggVertexPool *pool = get_pool();
00954 
00955     // Make sure the vertices belong to some vertex pool.
00956     nassertv(pool != NULL);
00957 
00958     // Make sure the vertex pool is named.
00959     nassertv(pool->has_name());
00960 
00961     if ((int)size() < 10) {
00962       // A simple primitive gets all its vertex indices written on one
00963       // line.
00964       indent(out, indent_level) << "<VertexRef> {";
00965       const_iterator i;
00966       for (i = begin(); i != end(); ++i) {
00967         EggVertex *vert = *i;
00968         vert->test_pref_integrity();
00969 
00970         // Make sure each vertex belongs to the same pool.
00971         nassertv(vert->get_pool() == pool);
00972 
00973         out << " " << vert->get_index();
00974       }
00975       out << " <Ref> { ";
00976       enquote_string(out, pool->get_name()) << " } }\n";
00977 
00978     } else {
00979 
00980       // A larger primitive gets its vertex indices written as
00981       // multiple lines.
00982       vector_int indices;
00983       const_iterator i;
00984       for (i = begin(); i != end(); ++i) {
00985         EggVertex *vert = *i;
00986         vert->test_pref_integrity();
00987 
00988         // Make sure each vertex belongs to the same pool.
00989         nassertv(vert->get_pool() == pool);
00990 
00991         indices.push_back(vert->get_index());
00992       }
00993 
00994       indent(out, indent_level) << "<VertexRef> {\n";
00995       write_long_list(out, indent_level+2, indices.begin(), indices.end(),
00996                 "", "", 72);
00997       indent(out, indent_level+2) << "<Ref> { ";
00998       enquote_string(out, pool->get_name()) << " }\n";
00999       indent(out, indent_level) << "}\n";
01000     }
01001   }
01002 }
01003 
01004 ////////////////////////////////////////////////////////////////////
01005 //     Function: EggPrimitive::egg_start_parse_body
01006 //       Access: Protected, Virtual
01007 //  Description: This function is called within parse_egg().  It
01008 //               should call the appropriate function on the lexer to
01009 //               initialize the parser into the state associated with
01010 //               this object.  If the object cannot be parsed into
01011 //               directly, it should return false.
01012 ////////////////////////////////////////////////////////////////////
01013 bool EggPrimitive::
01014 egg_start_parse_body() {
01015   egg_start_primitive_body();
01016   return true;
01017 }
01018 
01019 ////////////////////////////////////////////////////////////////////
01020 //     Function: EggPrimitive::r_transform
01021 //       Access: Protected, Virtual
01022 //  Description: This is called from within the egg code by
01023 //               transform().  It applies a transformation matrix
01024 //               to the current node in some sensible way, then
01025 //               continues down the tree.
01026 //
01027 //               The first matrix is the transformation to apply; the
01028 //               second is its inverse.  The third parameter is the
01029 //               coordinate system we are changing to, or CS_default
01030 //               if we are not changing coordinate systems.
01031 ////////////////////////////////////////////////////////////////////
01032 void EggPrimitive::
01033 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
01034   EggAttributes::transform(mat);
01035 }
01036 
01037 ////////////////////////////////////////////////////////////////////
01038 //     Function: EggPrimitive::r_flatten_transforms
01039 //       Access: Protected, Virtual
01040 //  Description: The recursive implementation of flatten_transforms().
01041 ////////////////////////////////////////////////////////////////////
01042 void EggPrimitive::
01043 r_flatten_transforms() {
01044   if (is_local_coord()) {
01045     LMatrix4d mat = get_vertex_frame();
01046     EggAttributes::transform(mat);
01047 
01048     // Transform each vertex by duplicating it in the vertex pool.
01049     size_t num_vertices = size();
01050     for (size_t i = 0; i < num_vertices; i++) {
01051       EggVertex *vertex = get_vertex(i);
01052       EggVertexPool *pool = vertex->get_pool();
01053 
01054       EggVertex new_vertex(*vertex);
01055       new_vertex.transform(mat);
01056       EggVertex *unique = pool->create_unique_vertex(new_vertex);
01057       unique->copy_grefs_from(*vertex);
01058 
01059       set_vertex(i, unique);
01060     }
01061   }
01062 }
01063 
01064 ////////////////////////////////////////////////////////////////////
01065 //     Function: EggPrimitive::r_apply_texmats
01066 //       Access: Protected, Virtual
01067 //  Description: The recursive implementation of apply_texmats().
01068 ////////////////////////////////////////////////////////////////////
01069 void EggPrimitive::
01070 r_apply_texmats(EggTextureCollection &textures) {
01071   Textures new_textures;
01072   Textures::const_iterator ti;
01073   for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
01074     EggTexture *texture = (*ti);
01075 
01076     if (!texture->has_transform()) {
01077       new_textures.push_back(texture);
01078 
01079     } else if (texture->transform_is_identity()) {
01080       // Now, what's the point of a texture with an identity
01081       // transform?
01082       texture->clear_transform();
01083       new_textures.push_back(texture);
01084 
01085     } else {
01086 
01087       // We've got a texture with a matrix applied.  Save the matrix,
01088       // and get a new texture without the matrix.
01089       LMatrix4d mat = texture->get_transform3d();
01090       EggTexture new_texture(*texture);
01091       new_texture.clear_transform();
01092       EggTexture *unique = textures.create_unique_texture(new_texture, ~0);
01093 
01094       new_textures.push_back(unique);
01095       string uv_name = unique->get_uv_name();
01096 
01097       // Now apply the matrix to the vertex UV's.  Create new vertices
01098       // as necessary.
01099       size_t num_vertices = size();
01100       for (size_t i = 0; i < num_vertices; i++) {
01101         EggVertex *vertex = get_vertex(i);
01102 
01103         const EggVertexUV *uv_obj = vertex->get_uv_obj(uv_name);
01104         if (uv_obj != (EggVertexUV *)NULL) {
01105           EggVertex new_vertex(*vertex);
01106           PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj);
01107           LTexCoord3d uvw = uv_obj->get_uvw() * mat;
01108           if (uv_obj->has_w() || texture->has_transform3d()) {
01109             new_uv_obj->set_uvw(uvw);
01110           } else {
01111             new_uv_obj->set_uv(LTexCoordd(uvw[0], uvw[1]));
01112           }
01113           new_vertex.set_uv_obj(new_uv_obj);
01114           
01115           EggVertexPool *pool = vertex->get_pool();
01116           EggVertex *unique = pool->create_unique_vertex(new_vertex);
01117           unique->copy_grefs_from(*vertex);
01118           
01119           set_vertex(i, unique);
01120         }
01121       }
01122     }
01123   }
01124 
01125   _textures.swap(new_textures);
01126 }
01127 
01128 ////////////////////////////////////////////////////////////////////
01129 //     Function: EggPrimitive::apply_attribute_to_vertex
01130 //       Access: Protected
01131 //  Description: This is used to implement apply_first_attribute() and
01132 //               apply_last_attribute().  It copies the indicated
01133 //               attributes to the specified vertex.
01134 ////////////////////////////////////////////////////////////////////
01135 void EggPrimitive::
01136 do_apply_flat_attribute(int vertex_index, EggAttributes *attrib) {
01137   // The significant_change flag is set if we have changed the
01138   // vertex in some important way, that will invalidate it for other
01139   // primitives that might share it.  We don't consider *adding* a
01140   // normal where there wasn't one before to be significant, but we
01141   // do consider it significant to change a vertex's normal to
01142   // something different.  Similarly for color.
01143   bool significant_change = false;
01144 
01145   EggVertex *orig_vertex = get_vertex(vertex_index);
01146   PT(EggVertex) new_vertex = new EggVertex(*orig_vertex);
01147 
01148   if (attrib->has_normal()) {
01149     new_vertex->copy_normal(*attrib);
01150     
01151     if (orig_vertex->has_normal() && 
01152         !orig_vertex->matches_normal(*new_vertex)) {
01153       significant_change = true;
01154     }
01155   } else if (has_normal()) {
01156     new_vertex->copy_normal(*this);
01157     
01158     if (orig_vertex->has_normal() && 
01159         !orig_vertex->matches_normal(*new_vertex)) {
01160       significant_change = true;
01161     }
01162   }
01163 
01164   if (attrib->has_color()) {
01165     new_vertex->copy_color(*attrib);
01166     
01167     if (orig_vertex->has_color() && 
01168         !orig_vertex->matches_color(*new_vertex)) {
01169       significant_change = true;
01170     }
01171   } else if (has_color()) {
01172     new_vertex->copy_color(*this);
01173     
01174     if (orig_vertex->has_color() && 
01175         !orig_vertex->matches_color(*new_vertex)) {
01176       significant_change = true;
01177     }
01178   }
01179 
01180   if (significant_change) {
01181     new_vertex = get_pool()->create_unique_vertex(*new_vertex);
01182     new_vertex->copy_grefs_from(*orig_vertex);
01183     set_vertex(vertex_index, new_vertex);
01184   } else {
01185     // Just copy the new attributes back into the pool.
01186     ((EggAttributes *)orig_vertex)->operator = (*new_vertex);
01187   }
01188 }
01189 
01190 ////////////////////////////////////////////////////////////////////
01191 //     Function: EggPrimitive::set_connected_shading
01192 //       Access: Private
01193 //  Description: Recursively updates the connected_shading member in
01194 //               all connected primitives.
01195 ////////////////////////////////////////////////////////////////////
01196 void EggPrimitive::
01197 set_connected_shading(EggPrimitive::Shading shading, 
01198                       const EggAttributes *neighbor) {
01199   ConnectedShadingNodes connected_nodes;
01200 
01201   r_set_connected_shading(0, shading, neighbor, connected_nodes);
01202   
01203   // Pick up any additional nodes we couldn't visit because of the
01204   // stack depth restrictions.
01205   while (!connected_nodes.empty()) {
01206     ConnectedShadingNodes next_nodes;
01207     next_nodes.swap(connected_nodes);
01208 
01209     ConnectedShadingNodes::iterator ni;
01210     for (ni = next_nodes.begin(); ni != next_nodes.end(); ++ni) {
01211       r_set_connected_shading(0, (*ni)._shading, (*ni)._neighbor, connected_nodes);
01212     }
01213   }
01214 }
01215 
01216 ////////////////////////////////////////////////////////////////////
01217 //     Function: EggPrimitive::r_set_connected_shading
01218 //       Access: Private
01219 //  Description: Implements set_connected_shading, with some
01220 //               restrictions to prevent stack overflow.
01221 ////////////////////////////////////////////////////////////////////
01222 void EggPrimitive::
01223 r_set_connected_shading(int stack_depth, EggPrimitive::Shading shading, 
01224                         const EggAttributes *neighbor, 
01225                         ConnectedShadingNodes &next_nodes) {
01226   if (stack_depth > egg_recursion_limit) {
01227     // Too deep.  Limit recursion.
01228     ConnectedShadingNode next;
01229     next._shading = shading;
01230     next._neighbor = neighbor;
01231     next_nodes.push_back(next);
01232     return;
01233   }
01234 
01235   bool propagate = false;
01236 
01237   if (_connected_shading == S_unknown) {
01238     // We haven't visited this node before; propagate now.
01239     _connected_shading = get_shading();
01240     propagate = true;
01241   }
01242 
01243   if (shading > _connected_shading) {
01244     // More specific information just came in.  Save it, and propagate
01245     // it to all connected primitives.
01246     _connected_shading = shading;
01247     propagate = true;
01248 
01249   } else if (shading == S_overall && _connected_shading == S_overall) {
01250     // If both neighbors are overall shaded, check if the two
01251     // neighbors have different properties.  If they do, elevate to
01252     // per_face.
01253     bool matches_normal = this->matches_normal(*neighbor);
01254     bool matches_color = this->matches_color(*neighbor);
01255 
01256     if (!matches_color) {
01257       // Make a special case for not having an overall color: that's
01258       // implicitly white.
01259       if (!neighbor->has_color() && has_color() && _drgbas.empty() &&
01260           get_color() == LColor(1.0f, 1.0f, 1.0f, 1.0f)) {
01261         matches_color = true;
01262       } else if (!has_color() && neighbor->has_color() && neighbor->_drgbas.empty() &&
01263           neighbor->get_color() == LColor(1.0f, 1.0f, 1.0f, 1.0f)) {
01264         matches_color = true;
01265       }
01266     }
01267     if (!matches_normal || !matches_color) {
01268       _connected_shading = S_per_face;
01269       propagate = true;
01270     }      
01271   }
01272 
01273   if (propagate) {
01274     Vertices::const_iterator vi;
01275     for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
01276       EggVertex *vertex = (*vi);
01277       EggVertex::PrimitiveRef::const_iterator pi;
01278       for (pi = vertex->pref_begin();
01279            pi != vertex->pref_end();
01280            ++pi) {
01281         (*pi)->r_set_connected_shading(stack_depth + 1, _connected_shading, this,
01282                                        next_nodes);
01283       }
01284     }
01285   }
01286 }
 All Classes Functions Variables Enumerations