Panda3D
|
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 ©) : 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 ¶ms) { 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 }