Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/egg/eggPrimitive.cxx

Go to the documentation of this file.
00001 // Filename: eggPrimitive.cxx
00002 // Created by:  drose (16Jan99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "eggPrimitive.h"
00020 #include "eggVertexPool.h"
00021 #include "eggMiscFuncs.h"
00022 #include "eggTextureCollection.h"
00023 #include "lexerDefs.h"
00024 
00025 #include <indent.h>
00026 #include <vector_int.h>
00027 
00028 TypeHandle EggPrimitive::_type_handle;
00029 
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: EggPrimitive::determine_alpha_mode
00033 //       Access: Public, Virtual
00034 //  Description: Walks back up the hierarchy, looking for an EggPrimitive
00035 //               or EggPrimitive or some such object at this level or
00036 //               above this primitive that has an alpha_mode other than
00037 //               AM_unspecified.  Returns a valid EggRenderMode pointer
00038 //               if one is found, or NULL otherwise.
00039 ////////////////////////////////////////////////////////////////////
00040 EggRenderMode *EggPrimitive::
00041 determine_alpha_mode() {
00042   if (get_alpha_mode() != AM_unspecified) {
00043     return this;
00044   }
00045 
00046   EggRenderMode *result = EggNode::determine_alpha_mode();
00047   if (result == (EggRenderMode *)NULL) {
00048     if (has_texture() && get_texture()->get_alpha_mode() != AM_unspecified) {
00049       result = get_texture();
00050     }
00051   }
00052   return result;
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: EggPrimitive::determine_depth_write_mode
00057 //       Access: Public, Virtual
00058 //  Description: Walks back up the hierarchy, looking for an EggGroup
00059 //               or EggPrimitive or some such object at this level or
00060 //               above this node that has a depth_write_mode other than
00061 //               DWM_unspecified.  Returns a valid EggRenderMode pointer
00062 //               if one is found, or NULL otherwise.
00063 ////////////////////////////////////////////////////////////////////
00064 EggRenderMode *EggPrimitive::
00065 determine_depth_write_mode() {
00066   if (get_depth_write_mode() != DWM_unspecified) {
00067     return this;
00068   }
00069 
00070   EggRenderMode *result = EggNode::determine_depth_write_mode();
00071   if (result == (EggRenderMode *)NULL) {
00072     if (has_texture() &&
00073         get_texture()->get_depth_write_mode() != DWM_unspecified) {
00074       result = get_texture();
00075     }
00076   }
00077   return result;
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: EggPrimitive::determine_depth_test_mode
00082 //       Access: Public, Virtual
00083 //  Description: Walks back up the hierarchy, looking for an EggGroup
00084 //               or EggPrimitive or some such object at this level or
00085 //               above this node that has a depth_test_mode other than
00086 //               DTM_unspecified.  Returns a valid EggRenderMode pointer
00087 //               if one is found, or NULL otherwise.
00088 ////////////////////////////////////////////////////////////////////
00089 EggRenderMode *EggPrimitive::
00090 determine_depth_test_mode() {
00091   if (get_depth_test_mode() != DTM_unspecified) {
00092     return this;
00093   }
00094 
00095   EggRenderMode *result = EggNode::determine_depth_test_mode();
00096   if (result == (EggRenderMode *)NULL) {
00097     if (has_texture() &&
00098         get_texture()->get_depth_test_mode() != DTM_unspecified) {
00099       result = get_texture();
00100     }
00101   }
00102   return result;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: EggPrimitive::determine_draw_order
00107 //       Access: Public, Virtual
00108 //  Description: Walks back up the hierarchy, looking for an EggPrimitive
00109 //               or EggPrimitive or some such object at this level or
00110 //               above this primitive that has a draw_order specified.
00111 //               Returns a valid EggRenderMode pointer if one is found,
00112 //               or NULL otherwise.
00113 ////////////////////////////////////////////////////////////////////
00114 EggRenderMode *EggPrimitive::
00115 determine_draw_order() {
00116   if (has_draw_order()) {
00117     return this;
00118   }
00119 
00120   EggRenderMode *result = EggNode::determine_draw_order();
00121   if (result == (EggRenderMode *)NULL) {
00122     if (has_texture() && get_texture()->has_draw_order()) {
00123       result = get_texture();
00124     }
00125   }
00126   return result;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: EggPrimitive::determine_bin
00131 //       Access: Public, Virtual
00132 //  Description: Walks back up the hierarchy, looking for an EggPrimitive
00133 //               or EggPrimitive or some such object at this level or
00134 //               above this primitive that has a bin specified.  Returns a
00135 //               valid EggRenderMode pointer if one is found, or NULL
00136 //               otherwise.
00137 ////////////////////////////////////////////////////////////////////
00138 EggRenderMode *EggPrimitive::
00139 determine_bin() {
00140   if (has_bin()) {
00141     return this;
00142   }
00143 
00144   EggRenderMode *result = EggNode::determine_bin();
00145   if (result == (EggRenderMode *)NULL) {
00146     if (has_texture() && get_texture()->has_bin()) {
00147       result = get_texture();
00148     }
00149   }
00150   return result;
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////
00154 //     Function: EggPrimitive::has_vertex_normal
00155 //       Access: Public
00156 //  Description: Returns true if any vertex on the primitive has a
00157 //               specific normal set, false otherwise.
00158 ////////////////////////////////////////////////////////////////////
00159 bool EggPrimitive::
00160 has_vertex_normal() const {
00161   Vertices::const_iterator vi;
00162   for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00163     if ((*vi)->has_normal()) {
00164       return true;
00165     }
00166   }
00167   return false;
00168 }
00169 
00170 ////////////////////////////////////////////////////////////////////
00171 //     Function: EggPrimitive::has_vertex_color
00172 //       Access: Public
00173 //  Description: Returns true if any vertex on the primitive has a
00174 //               specific color set, false otherwise.
00175 ////////////////////////////////////////////////////////////////////
00176 bool EggPrimitive::
00177 has_vertex_color() const {
00178   Vertices::const_iterator vi;
00179   for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00180     if ((*vi)->has_color()) {
00181       return true;
00182     }
00183   }
00184   return false;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: EggPrimitive::reverse_vertex_ordering
00189 //       Access: Public, Virtual
00190 //  Description: Reverses the ordering of the vertices in this
00191 //               primitive, if appropriate, in order to change the
00192 //               direction the polygon appears to be facing.  Does not
00193 //               adjust the surface normal, if any.
00194 ////////////////////////////////////////////////////////////////////
00195 void EggPrimitive::
00196 reverse_vertex_ordering() {
00197   // This really only makes sense for polygons.  Lights don't care
00198   // about vertex ordering, and NURBS surfaces have to do a bit more
00199   // work in addition to this.
00200   reverse(_vertices.begin(), _vertices.end());
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: EggPrimitive::cleanup
00205 //       Access: Public, Virtual
00206 //  Description: Cleans up modeling errors in whatever context this
00207 //               makes sense.  For instance, for a polygon, this calls
00208 //               remove_doubled_verts(true).  For a point, it calls
00209 //               remove_nonunique_verts().  Returns true if the
00210 //               primitive is valid, or false if it is degenerate.
00211 ////////////////////////////////////////////////////////////////////
00212 bool EggPrimitive::
00213 cleanup() {
00214   return !empty();
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: EggPrimitive::remove_doubled_verts
00219 //       Access: Public
00220 //  Description: Certain kinds of primitives, particularly polygons,
00221 //               don't like to have the same vertex repeated
00222 //               consecutively.  Unfortunately, some modeling programs
00223 //               (like MultiGen) make this an easy mistake to make.
00224 //
00225 //               It's handy to have a function to remove these
00226 //               redundant vertices.  If closed is true, it also
00227 //               checks that the first and last vertices are not the
00228 //               same.
00229 //
00230 //               This function identifies repeated vertices by pointer
00231 //               only; it does not remove consecutive equivalent but
00232 //               different vertices.
00233 ////////////////////////////////////////////////////////////////////
00234 void EggPrimitive::
00235 remove_doubled_verts(bool closed) {
00236   if (!_vertices.empty()) {
00237     Vertices new_vertices;
00238     Vertices::iterator vi, vlast;
00239     vi = _vertices.begin();
00240     new_vertices.push_back(*vi);
00241 
00242     vlast = vi;
00243     ++vi;
00244     while (vi != _vertices.end()) {
00245       if ((*vi) != (*vlast)) {
00246         new_vertices.push_back(*vi);
00247       } else {
00248         prepare_remove_vertex(*vi);
00249       }
00250       vlast = vi;
00251       ++vi;
00252     }
00253     _vertices.swap(new_vertices);
00254   }
00255 
00256   if (closed) {
00257     // Then, if this is a polygon (which will be closed anyway),
00258     // remove the vertex from the end if it's a repeat of the
00259     // beginning.
00260     while (_vertices.size() > 1 && _vertices.back() == _vertices.front()) {
00261       prepare_remove_vertex(_vertices.back());
00262       _vertices.pop_back();
00263     }
00264   }
00265 }
00266 
00267 ////////////////////////////////////////////////////////////////////
00268 //     Function: EggPrimitive::remove_nonunique_verts
00269 //       Access: Public
00270 //  Description: Removes any multiple appearances of the same vertex
00271 //               from the primitive.  This primarily makes sense for a
00272 //               point primitive, which is really a collection of
00273 //               points and which doesn't make sense to include the
00274 //               same point twice, in any order.
00275 ////////////////////////////////////////////////////////////////////
00276 void EggPrimitive::
00277 remove_nonunique_verts() {
00278   Vertices::iterator vi, vj;
00279   Vertices new_vertices;
00280 
00281   for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
00282     bool okflag = true;
00283     for (vj = _vertices.begin(); vj != vi && okflag; ++vj) {
00284       okflag = ((*vi) != (*vj));
00285     }
00286     if (okflag) {
00287       new_vertices.push_back(*vi);
00288     } else {
00289       prepare_remove_vertex(*vi);
00290     }
00291   }
00292 
00293   _vertices.swap(new_vertices);
00294 }
00295 
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: EggPrimitive::erase
00299 //       Access: Public
00300 //  Description: Part of the implementaion of the EggPrimitive as an
00301 //               STL container.  Most of the rest of these functions
00302 //               are inline and declared in EggPrimitive.I.
00303 ////////////////////////////////////////////////////////////////////
00304 EggPrimitive::iterator EggPrimitive::
00305 erase(iterator first, iterator last) {
00306   iterator i;
00307   for (i = first; i != last; ++i) {
00308     prepare_remove_vertex(*i);
00309   }
00310   iterator result = _vertices.erase((Vertices::iterator &)first,
00311                                     (Vertices::iterator &)last);
00312   test_vref_integrity();
00313   return result;
00314 }
00315 
00316 
00317 ////////////////////////////////////////////////////////////////////
00318 //     Function: EggPrimitive::add_vertex
00319 //       Access: Public
00320 //  Description: Adds the indicated vertex to the end of the
00321 //               primitive's list of vertices, and returns it.
00322 ////////////////////////////////////////////////////////////////////
00323 EggVertex *EggPrimitive::
00324 add_vertex(EggVertex *vertex) {
00325   prepare_add_vertex(vertex);
00326   _vertices.push_back(vertex);
00327 
00328   vertex->test_pref_integrity();
00329   test_vref_integrity();
00330 
00331   return vertex;
00332 }
00333 
00334 ////////////////////////////////////////////////////////////////////
00335 //     Function: EggPrimitive::remove_vertex
00336 //       Access: Public
00337 //  Description: Removes the indicated vertex vertex from the
00338 //               primitive and returns it.  If the vertex was not
00339 //               already in the primitive, does nothing and returns
00340 //               NULL.
00341 ////////////////////////////////////////////////////////////////////
00342 EggVertex *EggPrimitive::
00343 remove_vertex(EggVertex *vertex) {
00344   PT_EggVertex vpt = vertex;
00345   iterator i = find(begin(), end(), vpt);
00346   if (i == end()) {
00347     return PT_EggVertex();
00348   } else {
00349     // erase() calls prepare_remove_vertex().
00350     erase(i);
00351 
00352     vertex->test_pref_integrity();
00353     test_vref_integrity();
00354 
00355     return vertex;
00356   }
00357 }
00358 
00359 
00360 ////////////////////////////////////////////////////////////////////
00361 //     Function: EggPrimitive::copy_vertices
00362 //       Access: Public
00363 //  Description: Replaces the current primitive's list of vertices
00364 //               with a copy of the list of vertices on the other
00365 //               primitive.
00366 ////////////////////////////////////////////////////////////////////
00367 void EggPrimitive::
00368 copy_vertices(const EggPrimitive &other) {
00369   clear();
00370   _vertices.reserve(other.size());
00371 
00372   iterator vi;
00373   for (vi = other.begin(); vi != other.end(); ++vi) {
00374     add_vertex(*vi);
00375   }
00376 
00377   test_vref_integrity();
00378   other.test_vref_integrity();
00379 }
00380 
00381 #ifndef NDEBUG
00382 
00383 ////////////////////////////////////////////////////////////////////
00384 //     Function: EggPrimitive::test_vref_integrity
00385 //       Access: Public
00386 //  Description: Verifies that each vertex in the primitive exists and
00387 //               that it knows it is referenced by the primitive.
00388 ////////////////////////////////////////////////////////////////////
00389 void EggPrimitive::
00390 test_vref_integrity() const {
00391   test_ref_count_integrity();
00392 
00393   // First, we need to know how many times each vertex appears.
00394   // Usually, this will be only one, but it's possible for a vertex to
00395   // appear more than once.
00396   typedef pmap<const EggVertex *, int> VertexCount;
00397   VertexCount _count;
00398 
00399   // Now count up the vertices.
00400   iterator vi;
00401   for (vi = begin(); vi != end(); ++vi) {
00402     const EggVertex *vert = *vi;
00403     vert->test_ref_count_integrity();
00404 
00405     VertexCount::iterator vci = _count.find(vert);
00406     if (vci == _count.end()) {
00407       _count[vert] = 1;
00408     } else {
00409       (*vci).second++;
00410     }
00411   }
00412 
00413   // Ok, now walk through the vertices found and make sure the vertex
00414   // has the proper number of entries of this primitive in its pref.
00415   VertexCount::iterator vci;
00416   for (vci = _count.begin(); vci != _count.end(); ++vci) {
00417     const EggVertex *vert = (*vci).first;
00418 
00419     int count = (*vci).second;
00420     int vert_count = vert->has_pref(this);
00421 
00422     nassertv(count == vert_count);
00423   }
00424 }
00425 
00426 #endif  // NDEBUG
00427 
00428 ////////////////////////////////////////////////////////////////////
00429 //     Function: EggPrimitive::prepare_add_vertex
00430 //       Access: Private
00431 //  Description: Marks the vertex as belonging to the primitive.  This
00432 //               is an internal function called by the STL-like
00433 //               functions push_back() and insert(), in preparation
00434 //               for actually adding the vertex.
00435 ////////////////////////////////////////////////////////////////////
00436 void EggPrimitive::
00437 prepare_add_vertex(EggVertex *vertex) {
00438   // We can't test integrity within this function, because it might be
00439   // called when the primitive is in an incomplete state.
00440 
00441   // The vertex must have the same vertex pool as the vertices already
00442   // added.
00443   nassertv(empty() || vertex->get_pool() == get_pool());
00444 
00445   // Since a given vertex might appear more than once in a particular
00446   // primitive, we can't conclude anything about data integrity by
00447   // inspecting the return value of insert().  (In fact, the vertex's
00448   // pref is a multiset, so the insert() will always succeed.)
00449 
00450   vertex->_pref.insert(this);
00451 }
00452 
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: EggPrimitive::prepare_remove_vertex
00456 //       Access: Private
00457 //  Description: Marks the vertex as removed from the primitive.  This
00458 //               is an internal function called by the STL-like
00459 //               functions pop_back() and erase(), in preparation for
00460 //               actually doing the removal.
00461 //
00462 //               It is an error to attempt to remove a vertex that is
00463 //               not already a vertex of this primitive.
00464 ////////////////////////////////////////////////////////////////////
00465 void EggPrimitive::
00466 prepare_remove_vertex(EggVertex *vertex) {
00467   // We can't test integrity within this function, because it might be
00468   // called when the primitive is in an incomplete state.
00469 
00470   // Now we must remove the primitive from the vertex's pref.  We
00471   // can't just use the simple erase() function, since that will
00472   // remove all instances of this primitive from the pref; instead, we
00473   // must find one instance and remove that.
00474 
00475   EggVertex::PrimitiveRef::iterator pri = vertex->_pref.find(this);
00476 
00477   // We should have found the primitive in the vertex's pref.  If we
00478   // did not, something's out of sync internally.
00479   nassertv(pri != vertex->_pref.end());
00480 
00481   vertex->_pref.erase(pri);
00482 }
00483 
00484 ////////////////////////////////////////////////////////////////////
00485 //     Function: EggPrimitive::write_body
00486 //       Access: Protected
00487 //  Description: Writes the attributes and the vertices referenced by
00488 //               the primitive to the indicated output stream in Egg
00489 //               format.
00490 ////////////////////////////////////////////////////////////////////
00491 void EggPrimitive::
00492 write_body(ostream &out, int indent_level) const {
00493   test_vref_integrity();
00494 
00495   EggAttributes::write(out, indent_level);
00496   EggRenderMode::write(out, indent_level);
00497 
00498   if (has_texture()) {
00499     EggTexture *texture = get_texture();
00500 
00501     // Make sure the texture is named.
00502     nassertv(texture->has_name());
00503 
00504     indent(out, indent_level) << "<TRef> { ";
00505     enquote_string(out, texture->get_name())
00506       << " }\n";
00507   }
00508 
00509   if (has_material()) {
00510     EggMaterial *material = get_material();
00511 
00512     // Make sure the material is named.
00513     nassertv(material->has_name());
00514 
00515     indent(out, indent_level) << "<MRef> { ";
00516     enquote_string(out, material->get_name())
00517       << " }\n";
00518   }
00519 
00520   if (get_bface_flag()) {
00521     indent(out, indent_level) << "<BFace> { 1 }\n";
00522   }
00523 
00524   if (!empty()) {
00525     EggVertexPool *pool = get_pool();
00526 
00527     // Make sure the vertices belong to some vertex pool.
00528     nassertv(pool != NULL);
00529 
00530     // Make sure the vertex pool is named.
00531     nassertv(pool->has_name());
00532 
00533     if ((int)size() < 10) {
00534       // A simple primitive gets all its vertex indices written on one
00535       // line.
00536       indent(out, indent_level) << "<VertexRef> {";
00537       const_iterator i;
00538       for (i = begin(); i != end(); ++i) {
00539         EggVertex *vert = *i;
00540         vert->test_pref_integrity();
00541 
00542         // Make sure each vertex belongs to the same pool.
00543         nassertv(vert->get_pool() == pool);
00544 
00545         out << " " << vert->get_index();
00546       }
00547       out << " <Ref> { ";
00548       enquote_string(out, pool->get_name()) << " } }\n";
00549 
00550     } else {
00551 
00552       // A larger primitive gets its vertex indices written as
00553       // multiple lines.
00554       vector_int indices;
00555       const_iterator i;
00556       for (i = begin(); i != end(); ++i) {
00557         EggVertex *vert = *i;
00558         vert->test_pref_integrity();
00559 
00560         // Make sure each vertex belongs to the same pool.
00561         nassertv(vert->get_pool() == pool);
00562 
00563         indices.push_back(vert->get_index());
00564       }
00565 
00566       indent(out, indent_level) << "<VertexRef> {\n";
00567       write_long_list(out, indent_level+2, indices.begin(), indices.end(),
00568                 "", "", 72);
00569       indent(out, indent_level+2) << "<Ref> { ";
00570       enquote_string(out, pool->get_name()) << " }\n";
00571       indent(out, indent_level) << "}\n";
00572     }
00573   }
00574 }
00575 
00576 ////////////////////////////////////////////////////////////////////
00577 //     Function: EggPrimitive::egg_start_parse_body
00578 //       Access: Protected, Virtual
00579 //  Description: This function is called within parse_egg().  It
00580 //               should call the appropriate function on the lexer to
00581 //               initialize the parser into the state associated with
00582 //               this object.  If the object cannot be parsed into
00583 //               directly, it should return false.
00584 ////////////////////////////////////////////////////////////////////
00585 bool EggPrimitive::
00586 egg_start_parse_body() {
00587   egg_start_primitive_body();
00588   return true;
00589 }
00590 
00591 ////////////////////////////////////////////////////////////////////
00592 //     Function: EggPrimitive::r_transform
00593 //       Access: Protected, Virtual
00594 //  Description: This is called from within the egg code by
00595 //               transform().  It applies a transformation matrix
00596 //               to the current node in some sensible way, then
00597 //               continues down the tree.
00598 //
00599 //               The first matrix is the transformation to apply; the
00600 //               second is its inverse.  The third parameter is the
00601 //               coordinate system we are changing to, or CS_default
00602 //               if we are not changing coordinate systems.
00603 ////////////////////////////////////////////////////////////////////
00604 void EggPrimitive::
00605 r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
00606   EggAttributes::transform(mat);
00607 }
00608 
00609 ////////////////////////////////////////////////////////////////////
00610 //     Function: EggPrimitive::r_flatten_transforms
00611 //       Access: Protected, Virtual
00612 //  Description: The recursive implementation of flatten_transforms().
00613 ////////////////////////////////////////////////////////////////////
00614 void EggPrimitive::
00615 r_flatten_transforms() {
00616   if (is_local_coord()) {
00617     LMatrix4d mat = get_vertex_frame();
00618     EggAttributes::transform(mat);
00619 
00620     // Transform each vertex by duplicating it in the vertex pool.
00621     size_t num_vertices = size();
00622     for (size_t i = 0; i < num_vertices; i++) {
00623       EggVertex *vertex = get_vertex(i);
00624       EggVertexPool *pool = vertex->get_pool();
00625 
00626       EggVertex new_vertex(*vertex);
00627       new_vertex.transform(mat);
00628       EggVertex *unique = pool->create_unique_vertex(new_vertex);
00629       unique->copy_grefs_from(*vertex);
00630 
00631       set_vertex(i, unique);
00632     }
00633   }
00634 }
00635 
00636 ////////////////////////////////////////////////////////////////////
00637 //     Function: EggPrimitive::r_apply_texmats
00638 //       Access: Protected, Virtual
00639 //  Description: The recursive implementation of apply_texmats().
00640 ////////////////////////////////////////////////////////////////////
00641 void EggPrimitive::
00642 r_apply_texmats(EggTextureCollection &textures) {
00643   if (has_texture()) {
00644     EggTexture *texture = get_texture();
00645     if (texture->has_transform()) {
00646       if (texture->transform_is_identity()) {
00647         // Now, what's the point of a texture with an identity
00648         // transform?
00649         texture->clear_transform();
00650         return;
00651       }
00652 
00653       // We've got a texture with a matrix applied.  Save the matrix,
00654       // and get a new texture without the matrix.
00655       LMatrix3d mat = texture->get_transform();
00656       EggTexture new_texture(*texture);
00657       new_texture.clear_transform();
00658       EggTexture *unique = textures.create_unique_texture(new_texture, ~0);
00659 
00660       set_texture(unique);
00661 
00662       // Now apply the matrix to the vertex UV's.  Create new vertices
00663       // as necessary.
00664       size_t num_vertices = size();
00665       for (size_t i = 0; i < num_vertices; i++) {
00666         EggVertex *vertex = get_vertex(i);
00667 
00668         if (vertex->has_uv()) {
00669           EggVertexPool *pool = vertex->get_pool();
00670 
00671           EggVertex new_vertex(*vertex);
00672           new_vertex.set_uv(vertex->get_uv() * mat);
00673           EggVertex *unique = pool->create_unique_vertex(new_vertex);
00674           unique->copy_grefs_from(*vertex);
00675 
00676           set_vertex(i, unique);
00677         }
00678       }
00679     }
00680   }
00681 }

Generated on Fri May 2 00:37:52 2003 for Panda by doxygen1.3