Panda3D

geomTristrips.cxx

00001 // Filename: geomTristrips.cxx
00002 // Created by:  drose (08Mar05)
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 "geomTristrips.h"
00016 #include "geomTriangles.h"
00017 #include "geomVertexRewriter.h"
00018 #include "pStatTimer.h"
00019 #include "bamReader.h"
00020 #include "bamWriter.h"
00021 #include "graphicsStateGuardianBase.h"
00022 
00023 TypeHandle GeomTristrips::_type_handle;
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: GeomTristrips::Constructor
00027 //       Access: Published
00028 //  Description: 
00029 ////////////////////////////////////////////////////////////////////
00030 GeomTristrips::
00031 GeomTristrips(GeomTristrips::UsageHint usage_hint) :
00032   GeomPrimitive(usage_hint)
00033 {
00034 }
00035  
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: GeomTristrips::Copy Constructor
00038 //       Access: Published
00039 //  Description: 
00040 ////////////////////////////////////////////////////////////////////
00041 GeomTristrips::
00042 GeomTristrips(const GeomTristrips &copy) :
00043   GeomPrimitive(copy)
00044 {
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: GeomTristrips::Destructor
00049 //       Access: Published, Virtual
00050 //  Description: 
00051 ////////////////////////////////////////////////////////////////////
00052 GeomTristrips::
00053 ~GeomTristrips() {
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: GeomTristrips::make_copy
00058 //       Access: Public, Virtual
00059 //  Description: 
00060 ////////////////////////////////////////////////////////////////////
00061 PT(GeomPrimitive) GeomTristrips::
00062 make_copy() const {
00063   return new GeomTristrips(*this);
00064 }
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: GeomTristrips::get_primitive_type
00068 //       Access: Public, Virtual
00069 //  Description: Returns the fundamental rendering type of this
00070 //               primitive: whether it is points, lines, or polygons.
00071 //
00072 //               This is used to set up the appropriate antialiasing
00073 //               settings when AntialiasAttrib::M_auto is in effect;
00074 //               it also implies the type of primitive that will be
00075 //               produced when decompose() is called.
00076 ////////////////////////////////////////////////////////////////////
00077 GeomPrimitive::PrimitiveType GeomTristrips::
00078 get_primitive_type() const {
00079   return PT_polygons;
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: GeomTristrips::get_geom_rendering
00084 //       Access: Published, Virtual
00085 //  Description: Returns the set of GeomRendering bits that represent
00086 //               the rendering properties required to properly render
00087 //               this primitive.
00088 ////////////////////////////////////////////////////////////////////
00089 int GeomTristrips::
00090 get_geom_rendering() const {
00091   if (is_indexed()) {
00092     return GR_triangle_strip | GR_indexed_other;
00093   } else {
00094     return GR_triangle_strip;
00095   }
00096 }
00097 
00098 ////////////////////////////////////////////////////////////////////
00099 //     Function: GeomTristrips::get_num_unused_vertices_per_primitive
00100 //       Access: Public, Virtual
00101 //  Description: Returns the number of vertices that are added between
00102 //               primitives that aren't, strictly speaking, part of
00103 //               the primitives themselves.  This is used, for
00104 //               instance, to define degenerate triangles to connect
00105 //               otherwise disconnected triangle strips.
00106 ////////////////////////////////////////////////////////////////////
00107 int GeomTristrips::
00108 get_num_unused_vertices_per_primitive() const {
00109   return 2;
00110 }
00111 
00112 ////////////////////////////////////////////////////////////////////
00113 //     Function: GeomTristrips::draw
00114 //       Access: Public, Virtual
00115 //  Description: Calls the appropriate method on the GSG to draw the
00116 //               primitive.
00117 ////////////////////////////////////////////////////////////////////
00118 bool GeomTristrips::
00119 draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
00120      bool force) const {
00121   return gsg->draw_tristrips(reader, force);
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: GeomTristrips::decompose_impl
00126 //       Access: Protected, Virtual
00127 //  Description: Decomposes a complex primitive type into a simpler
00128 //               primitive type, for instance triangle strips to
00129 //               triangles, and returns a pointer to the new primitive
00130 //               definition.  If the decomposition cannot be
00131 //               performed, this might return the original object.
00132 //
00133 //               This method is useful for application code that wants
00134 //               to iterate through the set of triangles on the
00135 //               primitive without having to write handlers for each
00136 //               possible kind of primitive type.
00137 ////////////////////////////////////////////////////////////////////
00138 CPT(GeomPrimitive) GeomTristrips::
00139 decompose_impl() const {
00140   PT(GeomTriangles) triangles = new GeomTriangles(get_usage_hint());
00141   triangles->set_shade_model(get_shade_model());
00142   CPTA_int ends = get_ends();
00143 
00144   int num_vertices = get_num_vertices();
00145 
00146   // We need a slightly different algorithm for SM_flat_first_vertex
00147   // than for SM_flat_last_vertex, to preserve the key vertex in the
00148   // right place.  The remaining shade models can use either
00149   // algorithm.
00150   if (get_shade_model() == SM_flat_first_vertex) {
00151     // Preserve the first vertex of each component triangle as the
00152     // first vertex of each generated triangle.
00153     int vi = -2;
00154     int li = 0;
00155     while (li < (int)ends.size()) {
00156       // Skip unused vertices between tristrips.
00157       vi += 2;
00158       int end = ends[li];
00159       nassertr(vi + 2 <= end, NULL);
00160       int v0 = get_vertex(vi);
00161       ++vi;
00162       int v1 = get_vertex(vi);
00163       ++vi;
00164       bool reversed = false;
00165       while (vi < end) {
00166         int v2 = get_vertex(vi);
00167         ++vi;
00168         if (reversed) {
00169           if (v0 != v1 && v0 != v2 && v1 != v2) {
00170             triangles->add_vertex(v0);
00171             triangles->add_vertex(v2);
00172             triangles->add_vertex(v1);
00173             triangles->close_primitive();
00174           }
00175           reversed = false;
00176         } else {
00177           if (v0 != v1 && v0 != v2 && v1 != v2) {
00178             triangles->add_vertex(v0);
00179             triangles->add_vertex(v1);
00180             triangles->add_vertex(v2);
00181             triangles->close_primitive();
00182           }
00183           reversed = true;
00184         }
00185         v0 = v1;
00186         v1 = v2;
00187       }
00188       ++li;
00189     }
00190     nassertr(vi == num_vertices, NULL);
00191 
00192   } else {
00193     // Preserve the last vertex of each component triangle as the
00194     // last vertex of each generated triangle.
00195     int vi = -2;
00196     int li = 0;
00197     while (li < (int)ends.size()) {
00198       // Skip unused vertices between tristrips.
00199       vi += 2;
00200       int end = ends[li];
00201       nassertr(vi + 2 <= end, NULL);
00202       int v0 = get_vertex(vi);
00203       ++vi;
00204       int v1 = get_vertex(vi);
00205       ++vi;
00206       bool reversed = false;
00207       while (vi < end) {
00208         int v2 = get_vertex(vi);
00209         if (reversed) {
00210           if (v0 != v1 && v0 != v2 && v1 != v2) {
00211             triangles->add_vertex(v1);
00212             triangles->add_vertex(v0);
00213             triangles->add_vertex(v2);
00214             triangles->close_primitive();
00215           }
00216           reversed = false;
00217         } else {
00218           if (v0 != v1 && v0 != v2 && v1 != v2) {
00219             triangles->add_vertex(v0);
00220             triangles->add_vertex(v1);
00221             triangles->add_vertex(v2);
00222             triangles->close_primitive();
00223           }
00224           reversed = true;
00225         }
00226         ++vi;
00227         v0 = v1;
00228         v1 = v2;
00229       }
00230       ++li;
00231     }
00232     nassertr(vi == num_vertices, NULL);
00233   }
00234 
00235   return triangles.p();
00236 }
00237 
00238 ////////////////////////////////////////////////////////////////////
00239 //     Function: GeomTristrips::doubleside_impl
00240 //       Access: Protected, Virtual
00241 //  Description: The virtual implementation of doubleside().
00242 ////////////////////////////////////////////////////////////////////
00243 CPT(GeomPrimitive) GeomTristrips::
00244 doubleside_impl() const {
00245   // TODO: implement this properly as triangle strips, without
00246   // requiring a decompose operation first.
00247   return decompose_impl()->doubleside();
00248 }
00249 
00250 ////////////////////////////////////////////////////////////////////
00251 //     Function: GeomTristrips::reverse_impl
00252 //       Access: Protected, Virtual
00253 //  Description: The virtual implementation of reverse().
00254 ////////////////////////////////////////////////////////////////////
00255 CPT(GeomPrimitive) GeomTristrips::
00256 reverse_impl() const {
00257   // TODO: implement this properly as triangle strips, without
00258   // requiring a decompose operation first.
00259   return decompose_impl()->reverse();
00260 }
00261 
00262 ////////////////////////////////////////////////////////////////////
00263 //     Function: GeomTristrips::rotate_impl
00264 //       Access: Protected, Virtual
00265 //  Description: The virtual implementation of do_rotate().
00266 ////////////////////////////////////////////////////////////////////
00267 CPT(GeomVertexArrayData) GeomTristrips::
00268 rotate_impl() const {
00269   // To rotate a triangle strip with an even number of vertices, we
00270   // just reverse the vertices.  But if we have an odd number of
00271   // vertices, that doesn't work--in fact, nothing works (without also
00272   // changing the winding order), so we don't allow an odd number of
00273   // vertices in a flat-shaded tristrip.
00274   CPTA_int ends = get_ends();
00275 
00276   PT(GeomVertexArrayData) new_vertices = make_index_data();
00277   new_vertices->set_num_rows(get_num_vertices());
00278 
00279   if (is_indexed()) {
00280     CPT(GeomVertexArrayData) vertices = get_vertices();
00281     GeomVertexReader from(vertices, 0);
00282     GeomVertexWriter to(new_vertices, 0);
00283     
00284     int begin = 0;
00285     int last_added = 0;
00286     CPTA_int::const_iterator ei;
00287     for (ei = ends.begin(); ei != ends.end(); ++ei) {
00288       int end = (*ei);
00289       int num_vertices = end - begin;
00290       
00291       if (begin != 0) {
00292         // Copy in the unused vertices between tristrips.
00293         to.set_data1i(last_added);
00294         from.set_row_unsafe(end - 1);
00295         to.set_data1i(from.get_data1i());
00296         begin += 2;
00297       }
00298       
00299       // If this assertion is triggered, there was a triangle strip with
00300       // an odd number of vertices, which is not allowed.
00301       nassertr((num_vertices & 1) == 0, NULL);
00302       for (int vi = end - 1; vi >= begin; --vi) {
00303         from.set_row_unsafe(vi);
00304         last_added = from.get_data1i();
00305         to.set_data1i(last_added);
00306       }
00307       
00308       begin = end;
00309     }
00310 
00311     nassertr(to.is_at_end(), NULL);
00312 
00313   } else {
00314     // Nonindexed case.
00315     int first_vertex = get_first_vertex();
00316     GeomVertexWriter to(new_vertices, 0);
00317     
00318     int begin = 0;
00319     int last_added = 0;
00320     CPTA_int::const_iterator ei;
00321     for (ei = ends.begin(); ei != ends.end(); ++ei) {
00322       int end = (*ei);
00323       int num_vertices = end - begin;
00324       
00325       if (begin != 0) {
00326         // Copy in the unused vertices between tristrips.
00327         to.set_data1i(last_added);
00328         to.set_data1i(end - 1 + first_vertex);
00329         begin += 2;
00330       }
00331       
00332       // If this assertion is triggered, there was a triangle strip with
00333       // an odd number of vertices, which is not allowed.
00334       nassertr((num_vertices & 1) == 0, NULL);
00335       for (int vi = end - 1; vi >= begin; --vi) {
00336         last_added = vi + first_vertex;
00337         to.set_data1i(last_added);
00338       }
00339       
00340       begin = end;
00341     }
00342 
00343     nassertr(to.is_at_end(), NULL);
00344   }
00345   return new_vertices;
00346 }
00347 
00348 ////////////////////////////////////////////////////////////////////
00349 //     Function: GeomTristrips::requires_unused_vertices
00350 //       Access: Protected, Virtual
00351 //  Description: Should be redefined to return true in any primitive
00352 //               that implements append_unused_vertices().
00353 ////////////////////////////////////////////////////////////////////
00354 bool GeomTristrips::
00355 requires_unused_vertices() const {
00356   return true;
00357 }
00358 
00359 ////////////////////////////////////////////////////////////////////
00360 //     Function: GeomTristrips::append_unused_vertices
00361 //       Access: Protected, Virtual
00362 //  Description: Called when a new primitive is begun (other than the
00363 //               first primitive), this should add some degenerate
00364 //               vertices between primitives, if the primitive type
00365 //               requires that.  The second parameter is the first
00366 //               vertex that begins the new primitive.
00367 ////////////////////////////////////////////////////////////////////
00368 void GeomTristrips::
00369 append_unused_vertices(GeomVertexArrayData *vertices, int vertex) {
00370   GeomVertexReader from(vertices, 0);
00371   from.set_row_unsafe(vertices->get_num_rows() - 1);
00372   int prev = from.get_data1i();
00373 
00374   GeomVertexWriter to(vertices, 0);
00375   to.set_row_unsafe(vertices->get_num_rows());
00376 
00377   to.add_data1i(prev);
00378   to.add_data1i(vertex);
00379 }
00380 
00381 ////////////////////////////////////////////////////////////////////
00382 //     Function: GeomTristrips::register_with_read_factory
00383 //       Access: Public, Static
00384 //  Description: Tells the BamReader how to create objects of type
00385 //               Geom.
00386 ////////////////////////////////////////////////////////////////////
00387 void GeomTristrips::
00388 register_with_read_factory() {
00389   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00390 }
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: GeomTristrips::make_from_bam
00394 //       Access: Protected, Static
00395 //  Description: This function is called by the BamReader's factory
00396 //               when a new object of type Geom is encountered
00397 //               in the Bam file.  It should create the Geom
00398 //               and extract its information from the file.
00399 ////////////////////////////////////////////////////////////////////
00400 TypedWritable *GeomTristrips::
00401 make_from_bam(const FactoryParams &params) {
00402   GeomTristrips *object = new GeomTristrips(UH_unspecified);
00403   DatagramIterator scan;
00404   BamReader *manager;
00405 
00406   parse_params(params, scan, manager);
00407   object->fillin(scan, manager);
00408 
00409   return object;
00410 }
 All Classes Functions Variables Enumerations