Panda3D
|
00001 // Filename: geomPrimitive.cxx 00002 // Created by: drose (06Mar05) 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 "geomPrimitive.h" 00016 #include "geom.h" 00017 #include "geomVertexData.h" 00018 #include "geomVertexArrayFormat.h" 00019 #include "geomVertexColumn.h" 00020 #include "geomVertexReader.h" 00021 #include "geomVertexWriter.h" 00022 #include "geomVertexRewriter.h" 00023 #include "geomPoints.h" 00024 #include "preparedGraphicsObjects.h" 00025 #include "internalName.h" 00026 #include "bamReader.h" 00027 #include "bamWriter.h" 00028 #include "ioPtaDatagramInt.h" 00029 #include "indent.h" 00030 #include "pStatTimer.h" 00031 00032 TypeHandle GeomPrimitive::_type_handle; 00033 TypeHandle GeomPrimitive::CData::_type_handle; 00034 TypeHandle GeomPrimitivePipelineReader::_type_handle; 00035 00036 PStatCollector GeomPrimitive::_decompose_pcollector("*:Munge:Decompose"); 00037 PStatCollector GeomPrimitive::_doubleside_pcollector("*:Munge:Doubleside"); 00038 PStatCollector GeomPrimitive::_reverse_pcollector("*:Munge:Reverse"); 00039 PStatCollector GeomPrimitive::_rotate_pcollector("*:Munge:Rotate"); 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: GeomPrimitive::Default Constructor 00043 // Access: Protected 00044 // Description: Constructs an invalid object. Only used when reading 00045 // from bam. 00046 //////////////////////////////////////////////////////////////////// 00047 GeomPrimitive:: 00048 GeomPrimitive() { 00049 } 00050 00051 //////////////////////////////////////////////////////////////////// 00052 // Function: GeomPrimitive::make_cow_copy 00053 // Access: Protected, Virtual 00054 // Description: Required to implement CopyOnWriteObject. 00055 //////////////////////////////////////////////////////////////////// 00056 PT(CopyOnWriteObject) GeomPrimitive:: 00057 make_cow_copy() { 00058 return make_copy().p(); 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: GeomPrimitive::Constructor 00063 // Access: Published 00064 // Description: 00065 //////////////////////////////////////////////////////////////////// 00066 GeomPrimitive:: 00067 GeomPrimitive(GeomPrimitive::UsageHint usage_hint) { 00068 CDWriter cdata(_cycler, true); 00069 cdata->_usage_hint = usage_hint; 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: GeomPrimitive::Copy Constructor 00074 // Access: Published 00075 // Description: 00076 //////////////////////////////////////////////////////////////////// 00077 GeomPrimitive:: 00078 GeomPrimitive(const GeomPrimitive ©) : 00079 CopyOnWriteObject(copy), 00080 _cycler(copy._cycler) 00081 { 00082 } 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: GeomPrimitive::Copy Assignment Operator 00086 // Access: Published 00087 // Description: The copy assignment operator is not pipeline-safe. 00088 // This will completely obliterate all stages of the 00089 // pipeline, so don't do it for a GeomPrimitive that is 00090 // actively being used for rendering. 00091 //////////////////////////////////////////////////////////////////// 00092 void GeomPrimitive:: 00093 operator = (const GeomPrimitive ©) { 00094 CopyOnWriteObject::operator = (copy); 00095 _cycler = copy._cycler; 00096 } 00097 00098 //////////////////////////////////////////////////////////////////// 00099 // Function: GeomPrimitive::Destructor 00100 // Access: Published, Virtual 00101 // Description: 00102 //////////////////////////////////////////////////////////////////// 00103 GeomPrimitive:: 00104 ~GeomPrimitive() { 00105 release_all(); 00106 } 00107 00108 //////////////////////////////////////////////////////////////////// 00109 // Function: GeomPrimitive::get_geom_rendering 00110 // Access: Published, Virtual 00111 // Description: Returns the set of GeomRendering bits that represent 00112 // the rendering properties required to properly render 00113 // this primitive. 00114 //////////////////////////////////////////////////////////////////// 00115 int GeomPrimitive:: 00116 get_geom_rendering() const { 00117 if (is_indexed()) { 00118 return GR_indexed_other; 00119 } else { 00120 return 0; 00121 } 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: GeomPrimitive::set_usage_hint 00126 // Access: Published 00127 // Description: Changes the UsageHint hint for this primitive. See 00128 // get_usage_hint(). 00129 // 00130 // Don't call this in a downstream thread unless you 00131 // don't mind it blowing away other changes you might 00132 // have recently made in an upstream thread. 00133 //////////////////////////////////////////////////////////////////// 00134 void GeomPrimitive:: 00135 set_usage_hint(GeomPrimitive::UsageHint usage_hint) { 00136 CDWriter cdata(_cycler, true); 00137 cdata->_usage_hint = usage_hint; 00138 00139 if (!cdata->_vertices.is_null()) { 00140 cdata->_modified = Geom::get_next_modified(); 00141 cdata->_usage_hint = usage_hint; 00142 } 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: GeomPrimitive::set_index_type 00147 // Access: Published 00148 // Description: Changes the numeric type of the index column. 00149 // Normally, this should be either NT_uint16 or 00150 // NT_uint32. 00151 // 00152 // The index type must be large enough to include all of 00153 // the index values in the primitive. It may be 00154 // automatically elevated, if necessary, to a larger 00155 // index type, by a subsequent call to add_index() that 00156 // names an index value that does not fit in the index 00157 // type you specify. 00158 // 00159 // Don't call this in a downstream thread unless you 00160 // don't mind it blowing away other changes you might 00161 // have recently made in an upstream thread. 00162 //////////////////////////////////////////////////////////////////// 00163 void GeomPrimitive:: 00164 set_index_type(GeomPrimitive::NumericType index_type) { 00165 nassertv(get_max_vertex() <= get_highest_index_value(index_type)); 00166 00167 CDWriter cdata(_cycler, true); 00168 if (cdata->_index_type != index_type) { 00169 do_set_index_type(cdata, index_type); 00170 } 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: GeomPrimitive::add_vertex 00175 // Access: Published 00176 // Description: Adds the indicated vertex to the list of vertex 00177 // indices used by the graphics primitive type. To 00178 // define a primitive, you must call add_vertex() for 00179 // each vertex of the new primitive, and then call 00180 // close_primitive() after you have specified the last 00181 // vertex of each primitive. 00182 // 00183 // Don't call this in a downstream thread unless you 00184 // don't mind it blowing away other changes you might 00185 // have recently made in an upstream thread. 00186 //////////////////////////////////////////////////////////////////// 00187 void GeomPrimitive:: 00188 add_vertex(int vertex) { 00189 CDWriter cdata(_cycler, true); 00190 00191 if (gobj_cat.is_spam()) { 00192 gobj_cat.spam() 00193 << this << ".add_vertex(" << vertex << ")\n"; 00194 } 00195 00196 consider_elevate_index_type(cdata, vertex); 00197 00198 int num_primitives = get_num_primitives(); 00199 if (num_primitives > 0 && 00200 requires_unused_vertices() && 00201 get_num_vertices() == get_primitive_end(num_primitives - 1)) { 00202 // If we are beginning a new primitive, give the derived class a 00203 // chance to insert some degenerate vertices. 00204 if (cdata->_vertices.is_null()) { 00205 do_make_indexed(cdata); 00206 } 00207 append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex); 00208 } 00209 00210 if (cdata->_vertices.is_null()) { 00211 // The nonindexed case. We can keep the primitive nonindexed only 00212 // if the vertex number happens to be the next available vertex. 00213 nassertv(cdata->_num_vertices != -1); 00214 if (cdata->_num_vertices == 0) { 00215 cdata->_first_vertex = vertex; 00216 cdata->_num_vertices = 1; 00217 cdata->_modified = Geom::get_next_modified(); 00218 cdata->_got_minmax = false; 00219 return; 00220 00221 } else if (vertex == cdata->_first_vertex + cdata->_num_vertices) { 00222 ++cdata->_num_vertices; 00223 cdata->_modified = Geom::get_next_modified(); 00224 cdata->_got_minmax = false; 00225 return; 00226 } 00227 00228 // Otherwise, we need to suddenly become an indexed primitive. 00229 do_make_indexed(cdata); 00230 } 00231 00232 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer(); 00233 GeomVertexWriter index(array_obj, 0); 00234 index.set_row_unsafe(array_obj->get_num_rows()); 00235 00236 index.add_data1i(vertex); 00237 00238 cdata->_modified = Geom::get_next_modified(); 00239 cdata->_got_minmax = false; 00240 } 00241 00242 //////////////////////////////////////////////////////////////////// 00243 // Function: GeomPrimitive::add_consecutive_vertices 00244 // Access: Published 00245 // Description: Adds a consecutive sequence of vertices, beginning at 00246 // start, to the primitive. 00247 // 00248 // Don't call this in a downstream thread unless you 00249 // don't mind it blowing away other changes you might 00250 // have recently made in an upstream thread. 00251 //////////////////////////////////////////////////////////////////// 00252 void GeomPrimitive:: 00253 add_consecutive_vertices(int start, int num_vertices) { 00254 if (num_vertices == 0) { 00255 return; 00256 } 00257 int end = (start + num_vertices) - 1; 00258 00259 CDWriter cdata(_cycler, true); 00260 00261 consider_elevate_index_type(cdata, end); 00262 00263 int num_primitives = get_num_primitives(); 00264 if (num_primitives > 0 && 00265 get_num_vertices() == get_primitive_end(num_primitives - 1)) { 00266 // If we are beginning a new primitive, give the derived class a 00267 // chance to insert some degenerate vertices. 00268 if (cdata->_vertices.is_null()) { 00269 do_make_indexed(cdata); 00270 } 00271 append_unused_vertices(cdata->_vertices.get_write_pointer(), start); 00272 } 00273 00274 if (cdata->_vertices.is_null()) { 00275 // The nonindexed case. We can keep the primitive nonindexed only 00276 // if the vertex number happens to be the next available vertex. 00277 nassertv(cdata->_num_vertices != -1); 00278 if (cdata->_num_vertices == 0) { 00279 cdata->_first_vertex = start; 00280 cdata->_num_vertices = num_vertices; 00281 cdata->_modified = Geom::get_next_modified(); 00282 cdata->_got_minmax = false; 00283 return; 00284 00285 } else if (start == cdata->_first_vertex + cdata->_num_vertices) { 00286 cdata->_num_vertices += num_vertices; 00287 cdata->_modified = Geom::get_next_modified(); 00288 cdata->_got_minmax = false; 00289 return; 00290 } 00291 00292 // Otherwise, we need to suddenly become an indexed primitive. 00293 do_make_indexed(cdata); 00294 } 00295 00296 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer(); 00297 GeomVertexWriter index(array_obj, 0); 00298 index.set_row_unsafe(array_obj->get_num_rows()); 00299 00300 for (int v = start; v <= end; ++v) { 00301 index.add_data1i(v); 00302 } 00303 00304 cdata->_modified = Geom::get_next_modified(); 00305 cdata->_got_minmax = false; 00306 } 00307 00308 //////////////////////////////////////////////////////////////////// 00309 // Function: GeomPrimitive::add_next_vertices 00310 // Access: Published 00311 // Description: Adds the next n vertices in sequence, beginning from 00312 // the last vertex added to the primitive + 1. 00313 // 00314 // This is most useful when you are building up a 00315 // primitive and a GeomVertexData at the same time, and 00316 // you just want the primitive to reference the first n 00317 // vertices from the data, then the next n, and so on. 00318 //////////////////////////////////////////////////////////////////// 00319 void GeomPrimitive:: 00320 add_next_vertices(int num_vertices) { 00321 if (get_num_vertices() == 0) { 00322 add_consecutive_vertices(0, num_vertices); 00323 } else { 00324 add_consecutive_vertices(get_vertex(get_num_vertices() - 1) + 1, num_vertices); 00325 } 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: GeomPrimitive::reserve_num_vertices 00330 // Access: Published 00331 // Description: This ensures that enough memory space for n vertices 00332 // is allocated, so that you may increase the number of 00333 // vertices to n without causing a new memory 00334 // allocation. This is a performance optimization only; 00335 // it is especially useful when you know ahead of time 00336 // that you will be adding n vertices to the primitive. 00337 // 00338 // Note that the total you specify here should also 00339 // include implicit vertices which may be added at each 00340 // close_primitive() call, according to 00341 // get_num_unused_vertices_per_primitive(). 00342 // 00343 // Note also that making this call will implicitly make 00344 // the primitive indexed if it is not already, which 00345 // could result in a performance *penalty*. If you 00346 // would prefer not to lose the nonindexed nature of 00347 // your existing GeomPrimitives, check is_indexed() 00348 // before making this call. 00349 //////////////////////////////////////////////////////////////////// 00350 void GeomPrimitive:: 00351 reserve_num_vertices(int num_vertices) { 00352 if (gobj_cat.is_debug()) { 00353 gobj_cat.debug() 00354 << this << ".reserve_num_vertices(" << num_vertices << ")\n"; 00355 } 00356 00357 CDWriter cdata(_cycler, true); 00358 consider_elevate_index_type(cdata, num_vertices); 00359 do_make_indexed(cdata); 00360 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer(); 00361 array_obj->reserve_num_rows(num_vertices); 00362 } 00363 00364 //////////////////////////////////////////////////////////////////// 00365 // Function: GeomPrimitive::close_primitive 00366 // Access: Published 00367 // Description: Indicates that the previous n calls to add_vertex(), 00368 // since the last call to close_primitive(), have fully 00369 // defined a new primitive. Returns true if successful, 00370 // false otherwise. 00371 // 00372 // Don't call this in a downstream thread unless you 00373 // don't mind it blowing away other changes you might 00374 // have recently made in an upstream thread. 00375 //////////////////////////////////////////////////////////////////// 00376 bool GeomPrimitive:: 00377 close_primitive() { 00378 int num_vertices_per_primitive = get_num_vertices_per_primitive(); 00379 00380 CDWriter cdata(_cycler, true); 00381 if (num_vertices_per_primitive == 0) { 00382 // This is a complex primitive type like a triangle strip: each 00383 // primitive uses a different number of vertices. 00384 #ifndef NDEBUG 00385 int num_added; 00386 if (cdata->_ends.empty()) { 00387 num_added = get_num_vertices(); 00388 } else { 00389 num_added = get_num_vertices() - cdata->_ends.back(); 00390 num_added -= get_num_unused_vertices_per_primitive(); 00391 } 00392 nassertr(num_added >= get_min_num_vertices_per_primitive(), false); 00393 #endif 00394 if (cdata->_ends.get_ref_count() > 1) { 00395 PTA_int new_ends; 00396 new_ends.v() = cdata->_ends.v(); 00397 cdata->_ends = new_ends; 00398 } 00399 cdata->_ends.push_back(get_num_vertices()); 00400 00401 } else { 00402 #ifndef NDEBUG 00403 // This is a simple primitive type like a triangle: each primitive 00404 // uses the same number of vertices. Assert that we added the 00405 // correct number of vertices. 00406 int num_vertices_per_primitive = get_num_vertices_per_primitive(); 00407 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); 00408 00409 int num_vertices = get_num_vertices(); 00410 nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false) 00411 #endif 00412 } 00413 00414 cdata->_modified = Geom::get_next_modified(); 00415 00416 return true; 00417 } 00418 00419 //////////////////////////////////////////////////////////////////// 00420 // Function: GeomPrimitive::clear_vertices 00421 // Access: Published 00422 // Description: Removes all of the vertices and primitives from the 00423 // object, so they can be re-added. 00424 // 00425 // Don't call this in a downstream thread unless you 00426 // don't mind it blowing away other changes you might 00427 // have recently made in an upstream thread. 00428 //////////////////////////////////////////////////////////////////// 00429 void GeomPrimitive:: 00430 clear_vertices() { 00431 CDWriter cdata(_cycler, true); 00432 cdata->_first_vertex = 0; 00433 cdata->_num_vertices = 0; 00434 00435 // Since we might have automatically elevated the index type by 00436 // adding vertices, we should automatically lower it again when we 00437 // call clear_vertices(). 00438 cdata->_index_type = NT_uint16; 00439 00440 cdata->_vertices.clear(); 00441 cdata->_ends.clear(); 00442 cdata->_mins.clear(); 00443 cdata->_maxs.clear(); 00444 cdata->_modified = Geom::get_next_modified(); 00445 cdata->_got_minmax = false; 00446 } 00447 00448 //////////////////////////////////////////////////////////////////// 00449 // Function: GeomPrimitive::offset_vertices 00450 // Access: Published 00451 // Description: Adds the indicated offset to all vertices used by the 00452 // primitive. 00453 // 00454 // Don't call this in a downstream thread unless you 00455 // don't mind it blowing away other changes you might 00456 // have recently made in an upstream thread. 00457 //////////////////////////////////////////////////////////////////// 00458 void GeomPrimitive:: 00459 offset_vertices(int offset) { 00460 if (is_indexed()) { 00461 CDWriter cdata(_cycler, true); 00462 00463 if (!cdata->_got_minmax) { 00464 recompute_minmax(cdata); 00465 nassertv(cdata->_got_minmax); 00466 } 00467 00468 consider_elevate_index_type(cdata, cdata->_max_vertex + offset); 00469 00470 GeomVertexRewriter index(do_modify_vertices(cdata), 0); 00471 while (!index.is_at_end()) { 00472 index.set_data1i(index.get_data1i() + offset); 00473 } 00474 00475 } else { 00476 CDWriter cdata(_cycler, true); 00477 00478 cdata->_first_vertex += offset; 00479 cdata->_modified = Geom::get_next_modified(); 00480 cdata->_got_minmax = false; 00481 00482 consider_elevate_index_type(cdata, 00483 cdata->_first_vertex + cdata->_num_vertices - 1); 00484 } 00485 } 00486 00487 //////////////////////////////////////////////////////////////////// 00488 // Function: GeomPrimitive::make_nonindexed 00489 // Access: Published 00490 // Description: Converts the primitive from indexed to nonindexed by 00491 // duplicating vertices as necessary into the indicated 00492 // dest GeomVertexData. 00493 //////////////////////////////////////////////////////////////////// 00494 void GeomPrimitive:: 00495 make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) { 00496 Thread *current_thread = Thread::get_current_thread(); 00497 int num_vertices = get_num_vertices(); 00498 int dest_start = dest->get_num_rows(); 00499 00500 dest->set_num_rows(dest_start + num_vertices); 00501 for (int i = 0; i < num_vertices; ++i) { 00502 int v = get_vertex(i); 00503 dest->copy_row_from(dest_start + i, source, v, current_thread); 00504 } 00505 00506 set_nonindexed_vertices(dest_start, num_vertices); 00507 } 00508 00509 //////////////////////////////////////////////////////////////////// 00510 // Function: GeomPrimitive::pack_vertices 00511 // Access: Published 00512 // Description: Packs the vertices used by the primitive from the 00513 // indicated source array onto the end of the indicated 00514 // destination array. 00515 //////////////////////////////////////////////////////////////////// 00516 void GeomPrimitive:: 00517 pack_vertices(GeomVertexData *dest, const GeomVertexData *source) { 00518 Thread *current_thread = Thread::get_current_thread(); 00519 if (!is_indexed()) { 00520 // If the primitive is nonindexed, packing is the same as 00521 // converting (again) to nonindexed. 00522 make_nonindexed(dest, source); 00523 00524 } else { 00525 // The indexed case: build up a new index as we go. 00526 CPT(GeomVertexArrayData) orig_vertices = get_vertices(); 00527 PT(GeomVertexArrayData) new_vertices = make_index_data(); 00528 GeomVertexWriter index(new_vertices, 0); 00529 typedef pmap<int, int> CopiedIndices; 00530 CopiedIndices copied_indices; 00531 00532 int num_vertices = get_num_vertices(); 00533 int dest_start = dest->get_num_rows(); 00534 00535 for (int i = 0; i < num_vertices; ++i) { 00536 int v = get_vertex(i); 00537 00538 // Try to add the relation { v : size() }. If that succeeds, 00539 // great; if it doesn't, look up whatever we previously added 00540 // for v. 00541 pair<CopiedIndices::iterator, bool> result = 00542 copied_indices.insert(CopiedIndices::value_type(v, (int)copied_indices.size())); 00543 int v2 = (*result.first).second + dest_start; 00544 index.add_data1i(v2); 00545 00546 if (result.second) { 00547 // This is the first time we've seen vertex v. 00548 dest->copy_row_from(v2, source, v, current_thread); 00549 } 00550 } 00551 00552 set_vertices(new_vertices); 00553 } 00554 } 00555 00556 //////////////////////////////////////////////////////////////////// 00557 // Function: GeomPrimitive::make_indexed 00558 // Access: Published 00559 // Description: Converts the primitive from nonindexed form to 00560 // indexed form. This will simply create an index table 00561 // that is numbered consecutively from 00562 // get_first_vertex(); it does not automatically 00563 // collapse together identical vertices that may have 00564 // been split apart by a previous call to 00565 // make_nonindexed(). 00566 // 00567 // Don't call this in a downstream thread unless you 00568 // don't mind it blowing away other changes you might 00569 // have recently made in an upstream thread. 00570 //////////////////////////////////////////////////////////////////// 00571 void GeomPrimitive:: 00572 make_indexed() { 00573 CDWriter cdata(_cycler, true); 00574 do_make_indexed(cdata); 00575 } 00576 00577 //////////////////////////////////////////////////////////////////// 00578 // Function: GeomPrimitive::get_primitive_start 00579 // Access: Published 00580 // Description: Returns the element within the _vertices list at which 00581 // the nth primitive starts. 00582 // 00583 // If i is one more than the highest valid primitive 00584 // vertex, the return value will be one more than the 00585 // last valid vertex. Thus, it is generally true that 00586 // the vertices used by a particular primitive i are the 00587 // set get_primitive_start(n) <= vi < 00588 // get_primitive_start(n + 1) (although this range also 00589 // includes the unused vertices between primitives). 00590 //////////////////////////////////////////////////////////////////// 00591 int GeomPrimitive:: 00592 get_primitive_start(int n) const { 00593 int num_vertices_per_primitive = get_num_vertices_per_primitive(); 00594 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); 00595 00596 if (num_vertices_per_primitive == 0) { 00597 // This is a complex primitive type like a triangle strip: each 00598 // primitive uses a different number of vertices. 00599 CDReader cdata(_cycler); 00600 nassertr(n >= 0 && n <= (int)cdata->_ends.size(), -1); 00601 if (n == 0) { 00602 return 0; 00603 } else { 00604 return cdata->_ends[n - 1] + num_unused_vertices_per_primitive; 00605 } 00606 00607 } else { 00608 // This is a simple primitive type like a triangle: each primitive 00609 // uses the same number of vertices. 00610 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive); 00611 } 00612 } 00613 00614 //////////////////////////////////////////////////////////////////// 00615 // Function: GeomPrimitive::get_primitive_end 00616 // Access: Published 00617 // Description: Returns the element within the _vertices list at which 00618 // the nth primitive ends. This is one past the last 00619 // valid element for the nth primitive. 00620 //////////////////////////////////////////////////////////////////// 00621 int GeomPrimitive:: 00622 get_primitive_end(int n) const { 00623 int num_vertices_per_primitive = get_num_vertices_per_primitive(); 00624 00625 if (num_vertices_per_primitive == 0) { 00626 // This is a complex primitive type like a triangle strip: each 00627 // primitive uses a different number of vertices. 00628 CDReader cdata(_cycler); 00629 nassertr(n >= 0 && n < (int)cdata->_ends.size(), -1); 00630 return cdata->_ends[n]; 00631 00632 } else { 00633 // This is a simple primitive type like a triangle: each primitive 00634 // uses the same number of vertices. 00635 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); 00636 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive; 00637 } 00638 } 00639 00640 //////////////////////////////////////////////////////////////////// 00641 // Function: GeomPrimitive::get_primitive_num_vertices 00642 // Access: Published 00643 // Description: Returns the number of vertices used by the nth 00644 // primitive. This is the same thing as 00645 // get_primitive_end(n) - get_primitive_start(n). 00646 //////////////////////////////////////////////////////////////////// 00647 int GeomPrimitive:: 00648 get_primitive_num_vertices(int n) const { 00649 int num_vertices_per_primitive = get_num_vertices_per_primitive(); 00650 00651 if (num_vertices_per_primitive == 0) { 00652 // This is a complex primitive type like a triangle strip: each 00653 // primitive uses a different number of vertices. 00654 CDReader cdata(_cycler); 00655 nassertr(n >= 0 && n < (int)cdata->_ends.size(), 0); 00656 if (n == 0) { 00657 return cdata->_ends[0]; 00658 } else { 00659 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); 00660 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive; 00661 } 00662 00663 } else { 00664 // This is a simple primitive type like a triangle: each primitive 00665 // uses the same number of vertices. 00666 return num_vertices_per_primitive; 00667 } 00668 } 00669 00670 //////////////////////////////////////////////////////////////////// 00671 // Function: GeomPrimitive::get_primitive_min_vertex 00672 // Access: Published 00673 // Description: Returns the minimum vertex index number used by the 00674 // nth primitive in this object. 00675 //////////////////////////////////////////////////////////////////// 00676 int GeomPrimitive:: 00677 get_primitive_min_vertex(int n) const { 00678 if (is_indexed()) { 00679 CPT(GeomVertexArrayData) mins = get_mins(); 00680 nassertr(n >= 0 && n < mins->get_num_rows(), -1); 00681 00682 GeomVertexReader index(mins, 0); 00683 index.set_row_unsafe(n); 00684 return index.get_data1i(); 00685 } else { 00686 return get_primitive_start(n); 00687 } 00688 } 00689 00690 //////////////////////////////////////////////////////////////////// 00691 // Function: GeomPrimitive::get_primitive_max_vertex 00692 // Access: Published 00693 // Description: Returns the maximum vertex index number used by the 00694 // nth primitive in this object. 00695 //////////////////////////////////////////////////////////////////// 00696 int GeomPrimitive:: 00697 get_primitive_max_vertex(int n) const { 00698 if (is_indexed()) { 00699 CPT(GeomVertexArrayData) maxs = get_maxs(); 00700 nassertr(n >= 0 && n < maxs->get_num_rows(), -1); 00701 00702 GeomVertexReader index(maxs, 0); 00703 index.set_row_unsafe(n); 00704 return index.get_data1i(); 00705 } else { 00706 return get_primitive_end(n) - 1; 00707 } 00708 } 00709 00710 //////////////////////////////////////////////////////////////////// 00711 // Function: GeomPrimitive::decompose 00712 // Access: Published 00713 // Description: Decomposes a complex primitive type into a simpler 00714 // primitive type, for instance triangle strips to 00715 // triangles, and returns a pointer to the new primitive 00716 // definition. If the decomposition cannot be 00717 // performed, this might return the original object. 00718 // 00719 // This method is useful for application code that wants 00720 // to iterate through the set of triangles on the 00721 // primitive without having to write handlers for each 00722 // possible kind of primitive type. 00723 //////////////////////////////////////////////////////////////////// 00724 CPT(GeomPrimitive) GeomPrimitive:: 00725 decompose() const { 00726 if (gobj_cat.is_debug()) { 00727 gobj_cat.debug() 00728 << "Decomposing " << get_type() << ": " << (void *)this << "\n"; 00729 } 00730 00731 PStatTimer timer(_decompose_pcollector); 00732 return decompose_impl(); 00733 } 00734 00735 //////////////////////////////////////////////////////////////////// 00736 // Function: GeomPrimitive::rotate 00737 // Access: Published 00738 // Description: Returns a new primitive with the shade_model reversed 00739 // (if it is flat shaded), if possible. If the 00740 // primitive type cannot be rotated, returns the 00741 // original primitive, unrotated. 00742 // 00743 // If the current shade_model indicates 00744 // flat_vertex_last, this should bring the last vertex 00745 // to the first position; if it indicates 00746 // flat_vertex_first, this should bring the first vertex 00747 // to the last position. 00748 //////////////////////////////////////////////////////////////////// 00749 CPT(GeomPrimitive) GeomPrimitive:: 00750 rotate() const { 00751 if (gobj_cat.is_debug()) { 00752 gobj_cat.debug() 00753 << "Rotating " << get_type() << ": " << (void *)this << "\n"; 00754 } 00755 00756 PStatTimer timer(_rotate_pcollector); 00757 CPT(GeomVertexArrayData) rotated_vertices = rotate_impl(); 00758 00759 if (rotated_vertices == (GeomVertexArrayData *)NULL) { 00760 // This primitive type can't be rotated. 00761 return this; 00762 } 00763 00764 PT(GeomPrimitive) new_prim = make_copy(); 00765 new_prim->set_vertices(rotated_vertices); 00766 00767 switch (get_shade_model()) { 00768 case SM_flat_first_vertex: 00769 new_prim->set_shade_model(SM_flat_last_vertex); 00770 break; 00771 00772 case SM_flat_last_vertex: 00773 new_prim->set_shade_model(SM_flat_first_vertex); 00774 break; 00775 00776 default: 00777 break; 00778 } 00779 00780 return new_prim; 00781 } 00782 00783 //////////////////////////////////////////////////////////////////// 00784 // Function: GeomPrimitive::doubleside 00785 // Access: Published 00786 // Description: Duplicates triangles in the primitive so that each 00787 // triangle is back-to-back with another triangle facing 00788 // in the opposite direction. Note that this doesn't 00789 // affect vertex normals, so this operation alone won't 00790 // work in the presence of lighting (but see 00791 // SceneGraphReducer::doubleside()). 00792 // 00793 // Also see CullFaceAttrib, which can enable rendering 00794 // of both sides of a triangle without having to 00795 // duplicate it (but which doesn't necessarily work in 00796 // the presence of lighting). 00797 //////////////////////////////////////////////////////////////////// 00798 CPT(GeomPrimitive) GeomPrimitive:: 00799 doubleside() const { 00800 if (gobj_cat.is_debug()) { 00801 gobj_cat.debug() 00802 << "Doublesiding " << get_type() << ": " << (void *)this << "\n"; 00803 } 00804 00805 PStatTimer timer(_doubleside_pcollector); 00806 return doubleside_impl(); 00807 } 00808 00809 //////////////////////////////////////////////////////////////////// 00810 // Function: GeomPrimitive::reverse 00811 // Access: Published 00812 // Description: Reverses the winding order in the primitive so that 00813 // each triangle is facing in the opposite direction it 00814 // was originally. Note that this doesn't affect vertex 00815 // normals, so this operation alone won't work in the 00816 // presence of lighting (but see 00817 // SceneGraphReducer::reverse()). 00818 // 00819 // Also see CullFaceAttrib, which can change the visible 00820 // direction of a triangle without having to duplicate 00821 // it (but which doesn't necessarily work in the 00822 // presence of lighting). 00823 //////////////////////////////////////////////////////////////////// 00824 CPT(GeomPrimitive) GeomPrimitive:: 00825 reverse() const { 00826 if (gobj_cat.is_debug()) { 00827 gobj_cat.debug() 00828 << "Reversing " << get_type() << ": " << (void *)this << "\n"; 00829 } 00830 00831 PStatTimer timer(_reverse_pcollector); 00832 return reverse_impl(); 00833 } 00834 00835 //////////////////////////////////////////////////////////////////// 00836 // Function: GeomPrimitive::match_shade_model 00837 // Access: Published 00838 // Description: Returns a new primitive that is compatible with the 00839 // indicated shade model, if possible, or NULL if this 00840 // is not possible. 00841 // 00842 // In most cases, this will return either NULL or the 00843 // original primitive. In the case of a 00844 // SM_flat_first_vertex vs. a SM_flat_last_vertex (or 00845 // vice-versa), however, it will return a rotated 00846 // primitive. 00847 //////////////////////////////////////////////////////////////////// 00848 CPT(GeomPrimitive) GeomPrimitive:: 00849 match_shade_model(GeomPrimitive::ShadeModel shade_model) const { 00850 ShadeModel this_shade_model = get_shade_model(); 00851 if (this_shade_model == shade_model) { 00852 // Trivially compatible. 00853 return this; 00854 } 00855 00856 if (this_shade_model == SM_uniform || shade_model == SM_uniform) { 00857 // SM_uniform is compatible with anything. 00858 return this; 00859 } 00860 00861 if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) || 00862 (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) { 00863 // Needs to be rotated. 00864 CPT(GeomPrimitive) rotated = rotate(); 00865 if (rotated.p() == this) { 00866 // Oops, can't be rotated, sorry. 00867 return NULL; 00868 } 00869 return rotated; 00870 } 00871 00872 // Not compatible, sorry. 00873 return NULL; 00874 } 00875 00876 //////////////////////////////////////////////////////////////////// 00877 // Function: GeomPrimitive::make_points 00878 // Access: Published 00879 // Description: Returns a new GeomPoints primitive that represents 00880 // each of the vertices in the original primitive, 00881 // rendered exactly once. If the original primitive is 00882 // already a GeomPoints primitive, returns the original 00883 // primitive unchanged. 00884 //////////////////////////////////////////////////////////////////// 00885 CPT(GeomPrimitive) GeomPrimitive:: 00886 make_points() const { 00887 if (is_exact_type(GeomPoints::get_class_type())) { 00888 return this; 00889 } 00890 00891 // First, get a list of all of the vertices referenced by the 00892 // original primitive. 00893 BitArray bits; 00894 int num_vertices = get_num_vertices(); 00895 if (is_indexed()) { 00896 CPT(GeomVertexArrayData) vertices = get_vertices(); 00897 GeomVertexReader index(vertices, 0); 00898 for (int vi = 0; vi < num_vertices; ++vi) { 00899 nassertr(!index.is_at_end(), NULL); 00900 bits.set_bit(index.get_data1i()); 00901 } 00902 } else { 00903 int first_vertex = get_first_vertex(); 00904 bits.set_range(first_vertex, num_vertices); 00905 } 00906 00907 // Now construct a new index array with just those bits. 00908 PT(GeomVertexArrayData) new_vertices = make_index_data(); 00909 GeomVertexWriter new_index(new_vertices, 0); 00910 int p = bits.get_lowest_on_bit(); 00911 while (p != -1) { 00912 while (bits.get_bit(p)) { 00913 new_index.add_data1i(p); 00914 ++p; 00915 } 00916 int q = bits.get_next_higher_different_bit(p); 00917 if (q == p) { 00918 break; 00919 } 00920 p = q; 00921 } 00922 00923 PT(GeomPrimitive) points = new GeomPoints(UH_dynamic); 00924 points->set_vertices(new_vertices); 00925 00926 return points; 00927 } 00928 00929 //////////////////////////////////////////////////////////////////// 00930 // Function: GeomPrimitive::get_num_bytes 00931 // Access: Published 00932 // Description: Returns the number of bytes consumed by the primitive 00933 // and its index table(s). 00934 //////////////////////////////////////////////////////////////////// 00935 int GeomPrimitive:: 00936 get_num_bytes() const { 00937 CDReader cdata(_cycler); 00938 int num_bytes = cdata->_ends.size() * sizeof(int) + sizeof(GeomPrimitive); 00939 if (!cdata->_vertices.is_null()) { 00940 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes(); 00941 } 00942 00943 return num_bytes; 00944 } 00945 00946 //////////////////////////////////////////////////////////////////// 00947 // Function: GeomPrimitive::request_resident 00948 // Access: Published 00949 // Description: Returns true if the primitive data is currently 00950 // resident in memory. If this returns false, the 00951 // primitive data will be brought back into memory 00952 // shortly; try again later. 00953 //////////////////////////////////////////////////////////////////// 00954 bool GeomPrimitive:: 00955 request_resident() const { 00956 CDReader cdata(_cycler); 00957 00958 bool resident = true; 00959 00960 if (!cdata->_vertices.is_null() && 00961 !cdata->_vertices.get_read_pointer()->request_resident()) { 00962 resident = false; 00963 } 00964 00965 if (is_composite() && cdata->_got_minmax) { 00966 if (!cdata->_mins.is_null() && 00967 !cdata->_mins.get_read_pointer()->request_resident()) { 00968 resident = false; 00969 } 00970 if (!cdata->_maxs.is_null() && 00971 !cdata->_maxs.get_read_pointer()->request_resident()) { 00972 resident = false; 00973 } 00974 } 00975 00976 return resident; 00977 } 00978 00979 //////////////////////////////////////////////////////////////////// 00980 // Function: GeomPrimitive::output 00981 // Access: Published, Virtual 00982 // Description: 00983 //////////////////////////////////////////////////////////////////// 00984 void GeomPrimitive:: 00985 output(ostream &out) const { 00986 out << get_type() << ", " << get_num_primitives() 00987 << ", " << get_num_vertices(); 00988 } 00989 00990 //////////////////////////////////////////////////////////////////// 00991 // Function: GeomPrimitive::write 00992 // Access: Published, Virtual 00993 // Description: 00994 //////////////////////////////////////////////////////////////////// 00995 void GeomPrimitive:: 00996 write(ostream &out, int indent_level) const { 00997 indent(out, indent_level) 00998 << get_type(); 00999 if (is_indexed()) { 01000 out << " (indexed)"; 01001 } else { 01002 out << " (nonindexed)"; 01003 } 01004 out << ":\n"; 01005 int num_primitives = get_num_primitives(); 01006 int num_vertices = get_num_vertices(); 01007 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive(); 01008 for (int i = 0; i < num_primitives; ++i) { 01009 indent(out, indent_level + 2) 01010 << "["; 01011 int begin = get_primitive_start(i); 01012 int end = get_primitive_end(i); 01013 for (int vi = begin; vi < end; vi++) { 01014 out << " " << get_vertex(vi); 01015 } 01016 out << " ]"; 01017 if (end < num_vertices) { 01018 for (int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) { 01019 if (end + ui < num_vertices) { 01020 out << " " << get_vertex(end + ui); 01021 } else { 01022 out << " ?"; 01023 } 01024 } 01025 } 01026 out << "\n"; 01027 } 01028 } 01029 01030 //////////////////////////////////////////////////////////////////// 01031 // Function: GeomPrimitive::modify_vertices 01032 // Access: Published 01033 // Description: Returns a modifiable pointer to the vertex index 01034 // list, so application code can directly fiddle with 01035 // this data. Use with caution, since there are no 01036 // checks that the data will be left in a stable state. 01037 // 01038 // If this is called on a nonindexed primitive, it will 01039 // implicitly be converted to an indexed primitive. 01040 // 01041 // If num_vertices is not -1, it specifies an artificial 01042 // limit to the number of vertices in the array. 01043 // Otherwise, all of the vertices in the array will be 01044 // used. 01045 // 01046 // Don't call this in a downstream thread unless you 01047 // don't mind it blowing away other changes you might 01048 // have recently made in an upstream thread. 01049 // 01050 // This method is intended for low-level usage only. 01051 // There are higher-level methods for more common usage. 01052 // We recommend you do not use this method directly. If 01053 // you do, be sure you know what you are doing! 01054 //////////////////////////////////////////////////////////////////// 01055 PT(GeomVertexArrayData) GeomPrimitive:: 01056 modify_vertices(int num_vertices) { 01057 CDWriter cdata(_cycler, true); 01058 PT(GeomVertexArrayData) vertices = do_modify_vertices(cdata); 01059 cdata->_num_vertices = num_vertices; 01060 return vertices; 01061 } 01062 01063 //////////////////////////////////////////////////////////////////// 01064 // Function: GeomPrimitive::set_vertices 01065 // Access: Published 01066 // Description: Completely replaces the vertex index list with a new 01067 // table. Chances are good that you should also replace 01068 // the ends list with set_ends() at the same time. 01069 // 01070 // If num_vertices is not -1, it specifies an artificial 01071 // limit to the number of vertices in the array. 01072 // Otherwise, all of the vertices in the array will be 01073 // used. 01074 // 01075 // Don't call this in a downstream thread unless you 01076 // don't mind it blowing away other changes you might 01077 // have recently made in an upstream thread. 01078 // 01079 // This method is intended for low-level usage only. 01080 // There are higher-level methods for more common usage. 01081 // We recommend you do not use this method directly. If 01082 // you do, be sure you know what you are doing! 01083 //////////////////////////////////////////////////////////////////// 01084 void GeomPrimitive:: 01085 set_vertices(const GeomVertexArrayData *vertices, int num_vertices) { 01086 CDWriter cdata(_cycler, true); 01087 cdata->_vertices = (GeomVertexArrayData *)vertices; 01088 cdata->_num_vertices = num_vertices; 01089 01090 cdata->_modified = Geom::get_next_modified(); 01091 cdata->_got_minmax = false; 01092 } 01093 01094 //////////////////////////////////////////////////////////////////// 01095 // Function: GeomPrimitive::set_nonindexed_vertices 01096 // Access: Published 01097 // Description: Sets the primitive up as a nonindexed primitive, 01098 // using the indicated vertex range. 01099 // 01100 // Don't call this in a downstream thread unless you 01101 // don't mind it blowing away other changes you might 01102 // have recently made in an upstream thread. 01103 // 01104 // This method is intended for low-level usage only. 01105 // There are higher-level methods for more common usage. 01106 // We recommend you do not use this method directly. If 01107 // you do, be sure you know what you are doing! 01108 //////////////////////////////////////////////////////////////////// 01109 void GeomPrimitive:: 01110 set_nonindexed_vertices(int first_vertex, int num_vertices) { 01111 nassertv(num_vertices != -1); 01112 CDWriter cdata(_cycler, true); 01113 cdata->_vertices = (GeomVertexArrayData *)NULL; 01114 cdata->_first_vertex = first_vertex; 01115 cdata->_num_vertices = num_vertices; 01116 01117 cdata->_modified = Geom::get_next_modified(); 01118 cdata->_got_minmax = false; 01119 01120 // Force the minmax to be recomputed. 01121 recompute_minmax(cdata); 01122 } 01123 01124 //////////////////////////////////////////////////////////////////// 01125 // Function: GeomPrimitive::modify_ends 01126 // Access: Published 01127 // Description: Returns a modifiable pointer to the primitive ends 01128 // array, so application code can directly fiddle with 01129 // this data. Use with caution, since there are no 01130 // checks that the data will be left in a stable state. 01131 // 01132 // Note that simple primitive types, like triangles, do 01133 // not have a ends array: since all the primitives 01134 // have the same number of vertices, it is not needed. 01135 // 01136 // Don't call this in a downstream thread unless you 01137 // don't mind it blowing away other changes you might 01138 // have recently made in an upstream thread. 01139 // 01140 // This method is intended for low-level usage only. 01141 // There are higher-level methods for more common usage. 01142 // We recommend you do not use this method directly. If 01143 // you do, be sure you know what you are doing! 01144 //////////////////////////////////////////////////////////////////// 01145 PTA_int GeomPrimitive:: 01146 modify_ends() { 01147 CDWriter cdata(_cycler, true); 01148 01149 cdata->_modified = Geom::get_next_modified(); 01150 cdata->_got_minmax = false; 01151 01152 if (cdata->_ends.get_ref_count() > 1) { 01153 PTA_int new_ends; 01154 new_ends.v() = cdata->_ends.v(); 01155 cdata->_ends = new_ends; 01156 } 01157 return cdata->_ends; 01158 } 01159 01160 //////////////////////////////////////////////////////////////////// 01161 // Function: GeomPrimitive::set_ends 01162 // Access: Published 01163 // Description: Completely replaces the primitive ends array with 01164 // a new table. Chances are good that you should also 01165 // replace the vertices list with set_vertices() at the 01166 // same time. 01167 // 01168 // Note that simple primitive types, like triangles, do 01169 // not have a ends array: since all the primitives 01170 // have the same number of vertices, it is not needed. 01171 // 01172 // Don't call this in a downstream thread unless you 01173 // don't mind it blowing away other changes you might 01174 // have recently made in an upstream thread. 01175 // 01176 // This method is intended for low-level usage only. 01177 // There are higher-level methods for more common usage. 01178 // We recommend you do not use this method directly. If 01179 // you do, be sure you know what you are doing! 01180 //////////////////////////////////////////////////////////////////// 01181 void GeomPrimitive:: 01182 set_ends(CPTA_int ends) { 01183 CDWriter cdata(_cycler, true); 01184 cdata->_ends = (PTA_int &)ends; 01185 01186 cdata->_modified = Geom::get_next_modified(); 01187 cdata->_got_minmax = false; 01188 } 01189 01190 //////////////////////////////////////////////////////////////////// 01191 // Function: GeomPrimitive::set_minmax 01192 // Access: Published 01193 // Description: Explicitly specifies the minimum and maximum 01194 // vertices, as well as the lists of per-component min 01195 // and max. 01196 // 01197 // Use this method with extreme caution. It's generally 01198 // better to let the GeomPrimitive compute these 01199 // explicitly, unless for some reason you can do it 01200 // faster and you absolutely need the speed improvement. 01201 // 01202 // Note that any modification to the vertex array will 01203 // normally cause this to be recomputed, unless you set 01204 // it immediately again. 01205 // 01206 // This method is intended for low-level usage only. 01207 // There are higher-level methods for more common usage. 01208 // We recommend you do not use this method directly. If 01209 // you do, be sure you know what you are doing! 01210 //////////////////////////////////////////////////////////////////// 01211 void GeomPrimitive:: 01212 set_minmax(int min_vertex, int max_vertex, 01213 GeomVertexArrayData *mins, GeomVertexArrayData *maxs) { 01214 CDWriter cdata(_cycler, true); 01215 cdata->_min_vertex = min_vertex; 01216 cdata->_max_vertex = max_vertex; 01217 cdata->_mins = mins; 01218 cdata->_maxs = maxs; 01219 01220 cdata->_modified = Geom::get_next_modified(); 01221 cdata->_got_minmax = true; 01222 } 01223 01224 //////////////////////////////////////////////////////////////////// 01225 // Function: GeomPrimitive::clear_minmax 01226 // Access: Published 01227 // Description: Undoes a previous call to set_minmax(), and allows 01228 // the minimum and maximum values to be recomputed 01229 // normally. 01230 // 01231 // This method is intended for low-level usage only. 01232 // There are higher-level methods for more common usage. 01233 // We recommend you do not use this method directly. If 01234 // you do, be sure you know what you are doing! 01235 //////////////////////////////////////////////////////////////////// 01236 void GeomPrimitive:: 01237 clear_minmax() { 01238 CDWriter cdata(_cycler, true); 01239 cdata->_got_minmax = false; 01240 } 01241 01242 //////////////////////////////////////////////////////////////////// 01243 // Function: GeomPrimitive::get_num_vertices_per_primitive 01244 // Access: Published, Virtual 01245 // Description: If the primitive type is a simple type in which all 01246 // primitives have the same number of vertices, like 01247 // triangles, returns the number of vertices per 01248 // primitive. If the primitive type is a more complex 01249 // type in which different primitives might have 01250 // different numbers of vertices, for instance a 01251 // triangle strip, returns 0. 01252 // 01253 // This method is intended for low-level usage only. 01254 // There are higher-level methods for more common usage. 01255 // We recommend you do not use this method directly. If 01256 // you do, be sure you know what you are doing! 01257 //////////////////////////////////////////////////////////////////// 01258 int GeomPrimitive:: 01259 get_num_vertices_per_primitive() const { 01260 return 0; 01261 } 01262 01263 //////////////////////////////////////////////////////////////////// 01264 // Function: GeomPrimitive::get_min_num_vertices_per_primitive 01265 // Access: Published, Virtual 01266 // Description: Returns the minimum number of vertices that must be 01267 // added before close_primitive() may legally be called. 01268 // 01269 // This method is intended for low-level usage only. 01270 // There are higher-level methods for more common usage. 01271 // We recommend you do not use this method directly. If 01272 // you do, be sure you know what you are doing! 01273 //////////////////////////////////////////////////////////////////// 01274 int GeomPrimitive:: 01275 get_min_num_vertices_per_primitive() const { 01276 return 3; 01277 } 01278 01279 //////////////////////////////////////////////////////////////////// 01280 // Function: GeomPrimitive::get_num_unused_vertices_per_primitive 01281 // Access: Published, Virtual 01282 // Description: Returns the number of vertices that are added between 01283 // primitives that aren't, strictly speaking, part of 01284 // the primitives themselves. This is used, for 01285 // instance, to define degenerate triangles to connect 01286 // otherwise disconnected triangle strips. 01287 // 01288 // This method is intended for low-level usage only. 01289 // There are higher-level methods for more common usage. 01290 // We recommend you do not use this method directly. If 01291 // you do, be sure you know what you are doing! 01292 //////////////////////////////////////////////////////////////////// 01293 int GeomPrimitive:: 01294 get_num_unused_vertices_per_primitive() const { 01295 return 0; 01296 } 01297 01298 //////////////////////////////////////////////////////////////////// 01299 // Function: GeomPrimitive::prepare 01300 // Access: Public 01301 // Description: Indicates that the data should be enqueued to be 01302 // prepared in the indicated prepared_objects at the 01303 // beginning of the next frame. This will ensure the 01304 // data is already loaded into the GSG if it is expected 01305 // to be rendered soon. 01306 // 01307 // Use this function instead of prepare_now() to preload 01308 // datas from a user interface standpoint. 01309 //////////////////////////////////////////////////////////////////// 01310 void GeomPrimitive:: 01311 prepare(PreparedGraphicsObjects *prepared_objects) { 01312 if (is_indexed()) { 01313 prepared_objects->enqueue_index_buffer(this); 01314 } 01315 } 01316 01317 //////////////////////////////////////////////////////////////////// 01318 // Function: GeomPrimitive::is_prepared 01319 // Access: Published 01320 // Description: Returns true if the data has already been prepared 01321 // or enqueued for preparation on the indicated GSG, 01322 // false otherwise. 01323 //////////////////////////////////////////////////////////////////// 01324 bool GeomPrimitive:: 01325 is_prepared(PreparedGraphicsObjects *prepared_objects) const { 01326 Contexts::const_iterator ci; 01327 ci = _contexts.find(prepared_objects); 01328 if (ci != _contexts.end()) { 01329 return true; 01330 } 01331 return prepared_objects->is_index_buffer_queued(this); 01332 } 01333 01334 //////////////////////////////////////////////////////////////////// 01335 // Function: GeomPrimitive::prepare_now 01336 // Access: Public 01337 // Description: Creates a context for the data on the particular 01338 // GSG, if it does not already exist. Returns the new 01339 // (or old) IndexBufferContext. This assumes that the 01340 // GraphicsStateGuardian is the currently active 01341 // rendering context and that it is ready to accept new 01342 // datas. If this is not necessarily the case, you 01343 // should use prepare() instead. 01344 // 01345 // Normally, this is not called directly except by the 01346 // GraphicsStateGuardian; a data does not need to be 01347 // explicitly prepared by the user before it may be 01348 // rendered. 01349 //////////////////////////////////////////////////////////////////// 01350 IndexBufferContext *GeomPrimitive:: 01351 prepare_now(PreparedGraphicsObjects *prepared_objects, 01352 GraphicsStateGuardianBase *gsg) { 01353 nassertr(is_indexed(), NULL); 01354 01355 Contexts::const_iterator ci; 01356 ci = _contexts.find(prepared_objects); 01357 if (ci != _contexts.end()) { 01358 return (*ci).second; 01359 } 01360 01361 IndexBufferContext *ibc = prepared_objects->prepare_index_buffer_now(this, gsg); 01362 if (ibc != (IndexBufferContext *)NULL) { 01363 _contexts[prepared_objects] = ibc; 01364 } 01365 return ibc; 01366 } 01367 01368 //////////////////////////////////////////////////////////////////// 01369 // Function: GeomPrimitive::release 01370 // Access: Public 01371 // Description: Frees the data context only on the indicated object, 01372 // if it exists there. Returns true if it was released, 01373 // false if it had not been prepared. 01374 //////////////////////////////////////////////////////////////////// 01375 bool GeomPrimitive:: 01376 release(PreparedGraphicsObjects *prepared_objects) { 01377 Contexts::iterator ci; 01378 ci = _contexts.find(prepared_objects); 01379 if (ci != _contexts.end()) { 01380 IndexBufferContext *ibc = (*ci).second; 01381 prepared_objects->release_index_buffer(ibc); 01382 return true; 01383 } 01384 01385 // Maybe it wasn't prepared yet, but it's about to be. 01386 return prepared_objects->dequeue_index_buffer(this); 01387 } 01388 01389 //////////////////////////////////////////////////////////////////// 01390 // Function: GeomPrimitive::release_all 01391 // Access: Public 01392 // Description: Frees the context allocated on all objects for which 01393 // the data has been declared. Returns the number of 01394 // contexts which have been freed. 01395 //////////////////////////////////////////////////////////////////// 01396 int GeomPrimitive:: 01397 release_all() { 01398 // We have to traverse a copy of the _contexts list, because the 01399 // PreparedGraphicsObjects object will call clear_prepared() in response 01400 // to each release_index_buffer(), and we don't want to be modifying the 01401 // _contexts list while we're traversing it. 01402 Contexts temp = _contexts; 01403 int num_freed = (int)_contexts.size(); 01404 01405 Contexts::const_iterator ci; 01406 for (ci = temp.begin(); ci != temp.end(); ++ci) { 01407 PreparedGraphicsObjects *prepared_objects = (*ci).first; 01408 IndexBufferContext *ibc = (*ci).second; 01409 prepared_objects->release_index_buffer(ibc); 01410 } 01411 01412 // Now that we've called release_index_buffer() on every known context, 01413 // the _contexts list should have completely emptied itself. 01414 nassertr(_contexts.empty(), num_freed); 01415 01416 return num_freed; 01417 } 01418 01419 //////////////////////////////////////////////////////////////////// 01420 // Function: GeomPrimitive::get_index_format 01421 // Access: Public 01422 // Description: Returns a registered format appropriate for using to 01423 // store the index table. 01424 //////////////////////////////////////////////////////////////////// 01425 CPT(GeomVertexArrayFormat) GeomPrimitive:: 01426 get_index_format() const { 01427 PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat; 01428 // It's important that the index format *not* respect the global 01429 // setting of vertex-column-alignment. It needs to be tightly 01430 // packed, so we specify an explict column_alignment of 1. 01431 format->add_column(InternalName::get_index(), 1, get_index_type(), C_index, 0, 1); 01432 return GeomVertexArrayFormat::register_format(format); 01433 } 01434 01435 //////////////////////////////////////////////////////////////////// 01436 // Function: GeomPrimitive::clear_prepared 01437 // Access: Private 01438 // Description: Removes the indicated PreparedGraphicsObjects table 01439 // from the data array's table, without actually 01440 // releasing the data array. This is intended to be 01441 // called only from 01442 // PreparedGraphicsObjects::release_index_buffer(); it should 01443 // never be called by user code. 01444 //////////////////////////////////////////////////////////////////// 01445 void GeomPrimitive:: 01446 clear_prepared(PreparedGraphicsObjects *prepared_objects) { 01447 Contexts::iterator ci; 01448 ci = _contexts.find(prepared_objects); 01449 if (ci != _contexts.end()) { 01450 _contexts.erase(ci); 01451 } else { 01452 // If this assertion fails, clear_prepared() was given a 01453 // prepared_objects which the data array didn't know about. 01454 nassertv(false); 01455 } 01456 } 01457 01458 //////////////////////////////////////////////////////////////////// 01459 // Function: GeomPrimitive::get_highest_index_value 01460 // Access: Private, Static 01461 // Description: Returns the largest index value that can be stored in 01462 // an index of the indicated type. 01463 //////////////////////////////////////////////////////////////////// 01464 int GeomPrimitive:: 01465 get_highest_index_value(NumericType index_type) { 01466 switch (index_type) { 01467 case NT_uint8: 01468 return 0xff; 01469 01470 case NT_uint16: 01471 return 0xffff; 01472 01473 case NT_uint32: 01474 // We don't actually allow use of the sign bit, since all of our 01475 // functions receive an "int" instead of an "unsigned int". 01476 return 0x7fffffff; 01477 01478 default: 01479 return 0; 01480 } 01481 } 01482 01483 //////////////////////////////////////////////////////////////////// 01484 // Function: GeomPrimitive::calc_tight_bounds 01485 // Access: Public, Virtual 01486 // Description: Expands min_point and max_point to include all of the 01487 // vertices in the Geom, if any (or the data of any 01488 // point type, for instance, texture coordinates--based 01489 // on the column name). found_any is set true if any 01490 // points are found. It is the caller's responsibility 01491 // to initialize min_point, max_point, and found_any 01492 // before calling this function. 01493 //////////////////////////////////////////////////////////////////// 01494 void GeomPrimitive:: 01495 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, 01496 bool &found_any, 01497 const GeomVertexData *vertex_data, 01498 bool got_mat, const LMatrix4 &mat, 01499 const InternalName *column_name, 01500 Thread *current_thread) const { 01501 GeomVertexReader reader(vertex_data, column_name, current_thread); 01502 if (!reader.has_column()) { 01503 // No vertex data. 01504 return; 01505 } 01506 01507 CDReader cdata(_cycler, current_thread); 01508 01509 if (cdata->_vertices.is_null()) { 01510 // Nonindexed case. 01511 nassertv(cdata->_num_vertices != -1); 01512 if (got_mat) { 01513 for (int i = 0; i < cdata->_num_vertices; i++) { 01514 reader.set_row_unsafe(cdata->_first_vertex + i); 01515 LPoint3 vertex = mat.xform_point(reader.get_data3()); 01516 01517 if (found_any) { 01518 min_point.set(min(min_point[0], vertex[0]), 01519 min(min_point[1], vertex[1]), 01520 min(min_point[2], vertex[2])); 01521 max_point.set(max(max_point[0], vertex[0]), 01522 max(max_point[1], vertex[1]), 01523 max(max_point[2], vertex[2])); 01524 } else { 01525 min_point = vertex; 01526 max_point = vertex; 01527 found_any = true; 01528 } 01529 } 01530 } else { 01531 for (int i = 0; i < cdata->_num_vertices; i++) { 01532 reader.set_row_unsafe(cdata->_first_vertex + i); 01533 const LVecBase3 &vertex = reader.get_data3(); 01534 01535 if (found_any) { 01536 min_point.set(min(min_point[0], vertex[0]), 01537 min(min_point[1], vertex[1]), 01538 min(min_point[2], vertex[2])); 01539 max_point.set(max(max_point[0], vertex[0]), 01540 max(max_point[1], vertex[1]), 01541 max(max_point[2], vertex[2])); 01542 } else { 01543 min_point = vertex; 01544 max_point = vertex; 01545 found_any = true; 01546 } 01547 } 01548 } 01549 01550 } else { 01551 // Indexed case. 01552 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread); 01553 01554 if (got_mat) { 01555 while (!index.is_at_end()) { 01556 int ii = index.get_data1i(); 01557 reader.set_row_unsafe(ii); 01558 LPoint3 vertex = mat.xform_point(reader.get_data3()); 01559 01560 if (found_any) { 01561 min_point.set(min(min_point[0], vertex[0]), 01562 min(min_point[1], vertex[1]), 01563 min(min_point[2], vertex[2])); 01564 max_point.set(max(max_point[0], vertex[0]), 01565 max(max_point[1], vertex[1]), 01566 max(max_point[2], vertex[2])); 01567 } else { 01568 min_point = vertex; 01569 max_point = vertex; 01570 found_any = true; 01571 } 01572 } 01573 } else { 01574 while (!index.is_at_end()) { 01575 int ii = index.get_data1i(); 01576 reader.set_row_unsafe(ii); 01577 const LVecBase3 &vertex = reader.get_data3(); 01578 01579 if (found_any) { 01580 min_point.set(min(min_point[0], vertex[0]), 01581 min(min_point[1], vertex[1]), 01582 min(min_point[2], vertex[2])); 01583 max_point.set(max(max_point[0], vertex[0]), 01584 max(max_point[1], vertex[1]), 01585 max(max_point[2], vertex[2])); 01586 } else { 01587 min_point = vertex; 01588 max_point = vertex; 01589 found_any = true; 01590 } 01591 } 01592 } 01593 } 01594 } 01595 01596 //////////////////////////////////////////////////////////////////// 01597 // Function: GeomPrimitive::decompose_impl 01598 // Access: Protected, Virtual 01599 // Description: Decomposes a complex primitive type into a simpler 01600 // primitive type, for instance triangle strips to 01601 // triangles, and returns a pointer to the new primitive 01602 // definition. If the decomposition cannot be 01603 // performed, this might return the original object. 01604 // 01605 // This method is useful for application code that wants 01606 // to iterate through the set of triangles on the 01607 // primitive without having to write handlers for each 01608 // possible kind of primitive type. 01609 //////////////////////////////////////////////////////////////////// 01610 CPT(GeomPrimitive) GeomPrimitive:: 01611 decompose_impl() const { 01612 return this; 01613 } 01614 01615 //////////////////////////////////////////////////////////////////// 01616 // Function: GeomPrimitive::rotate_impl 01617 // Access: Protected, Virtual 01618 // Description: The virtual implementation of rotate(). 01619 //////////////////////////////////////////////////////////////////// 01620 CPT(GeomVertexArrayData) GeomPrimitive:: 01621 rotate_impl() const { 01622 // The default implementation doesn't even try to do anything. 01623 nassertr(false, NULL); 01624 return NULL; 01625 } 01626 01627 //////////////////////////////////////////////////////////////////// 01628 // Function: GeomPrimitive::doubleside_impl 01629 // Access: Protected, Virtual 01630 // Description: The virtual implementation of doubleside(). 01631 //////////////////////////////////////////////////////////////////// 01632 CPT(GeomPrimitive) GeomPrimitive:: 01633 doubleside_impl() const { 01634 return this; 01635 } 01636 01637 //////////////////////////////////////////////////////////////////// 01638 // Function: GeomPrimitive::reverse_impl 01639 // Access: Protected, Virtual 01640 // Description: The virtual implementation of reverse(). 01641 //////////////////////////////////////////////////////////////////// 01642 CPT(GeomPrimitive) GeomPrimitive:: 01643 reverse_impl() const { 01644 return this; 01645 } 01646 01647 //////////////////////////////////////////////////////////////////// 01648 // Function: GeomPrimitive::requires_unused_vertices 01649 // Access: Protected, Virtual 01650 // Description: Should be redefined to return true in any primitive 01651 // that implements append_unused_vertices(). 01652 //////////////////////////////////////////////////////////////////// 01653 bool GeomPrimitive:: 01654 requires_unused_vertices() const { 01655 return false; 01656 } 01657 01658 //////////////////////////////////////////////////////////////////// 01659 // Function: GeomPrimitive::append_unused_vertices 01660 // Access: Protected, Virtual 01661 // Description: Called when a new primitive is begun (other than the 01662 // first primitive), this should add some degenerate 01663 // vertices between primitives, if the primitive type 01664 // requires that. The second parameter is the first 01665 // vertex that begins the new primitive. 01666 // 01667 // This method is only called if 01668 // requires_unused_vertices(), above, returns true. 01669 //////////////////////////////////////////////////////////////////// 01670 void GeomPrimitive:: 01671 append_unused_vertices(GeomVertexArrayData *, int) { 01672 } 01673 01674 //////////////////////////////////////////////////////////////////// 01675 // Function: GeomPrimitive::recompute_minmax 01676 // Access: Private 01677 // Description: Recomputes the _min_vertex and _max_vertex values if 01678 // necessary. 01679 //////////////////////////////////////////////////////////////////// 01680 void GeomPrimitive:: 01681 recompute_minmax(GeomPrimitive::CData *cdata) { 01682 if (cdata->_vertices.is_null()) { 01683 // In the nonindexed case, we don't need to do much (the 01684 // minmax is trivial). 01685 nassertv(cdata->_num_vertices != -1); 01686 cdata->_min_vertex = cdata->_first_vertex; 01687 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1; 01688 cdata->_mins.clear(); 01689 cdata->_maxs.clear(); 01690 01691 } else { 01692 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows(); 01693 01694 if (num_vertices == 0) { 01695 // Or if we don't have any vertices, the minmax is also trivial. 01696 cdata->_min_vertex = 0; 01697 cdata->_max_vertex = 0; 01698 cdata->_mins.clear(); 01699 cdata->_maxs.clear(); 01700 01701 } else if (get_num_vertices_per_primitive() == 0) { 01702 // This is a complex primitive type like a triangle strip; compute 01703 // the minmax of each primitive (as well as the overall minmax). 01704 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0); 01705 01706 cdata->_mins = make_index_data(); 01707 cdata->_maxs = make_index_data(); 01708 01709 GeomVertexWriter mins(cdata->_mins.get_write_pointer(), 0); 01710 mins.reserve_num_rows(cdata->_ends.size()); 01711 GeomVertexWriter maxs(cdata->_maxs.get_write_pointer(), 0); 01712 maxs.reserve_num_rows(cdata->_ends.size()); 01713 01714 int pi = 0; 01715 01716 unsigned int vertex = index.get_data1i(); 01717 cdata->_min_vertex = vertex; 01718 cdata->_max_vertex = vertex; 01719 unsigned int min_prim = vertex; 01720 unsigned int max_prim = vertex; 01721 01722 for (int vi = 1; vi < num_vertices; ++vi) { 01723 nassertv(!index.is_at_end()); 01724 unsigned int vertex = index.get_data1i(); 01725 cdata->_min_vertex = min(cdata->_min_vertex, vertex); 01726 cdata->_max_vertex = max(cdata->_max_vertex, vertex); 01727 01728 nassertv(pi < (int)cdata->_ends.size()); 01729 if (vi == cdata->_ends[pi]) { 01730 mins.add_data1i(min_prim); 01731 maxs.add_data1i(max_prim); 01732 min_prim = vertex; 01733 max_prim = vertex; 01734 ++pi; 01735 01736 } else { 01737 min_prim = min(min_prim, vertex); 01738 max_prim = max(max_prim, vertex); 01739 } 01740 } 01741 mins.add_data1i(min_prim); 01742 maxs.add_data1i(max_prim); 01743 nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size()); 01744 01745 } else { 01746 // This is a simple primitive type like a triangle; just compute 01747 // the overall minmax. 01748 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0); 01749 01750 cdata->_mins.clear(); 01751 cdata->_maxs.clear(); 01752 01753 unsigned int vertex = index.get_data1i(); 01754 cdata->_min_vertex = vertex; 01755 cdata->_max_vertex = vertex; 01756 01757 for (int vi = 1; vi < num_vertices; ++vi) { 01758 nassertv(!index.is_at_end()); 01759 unsigned int vertex = index.get_data1i(); 01760 cdata->_min_vertex = min(cdata->_min_vertex, vertex); 01761 cdata->_max_vertex = max(cdata->_max_vertex, vertex); 01762 } 01763 } 01764 } 01765 01766 cdata->_got_minmax = true; 01767 } 01768 01769 //////////////////////////////////////////////////////////////////// 01770 // Function: GeomPrimitive::do_make_indexed 01771 // Access: Private 01772 // Description: The private implementation of make_indexed(). 01773 //////////////////////////////////////////////////////////////////// 01774 void GeomPrimitive:: 01775 do_make_indexed(CData *cdata) { 01776 if (cdata->_vertices.is_null()) { 01777 if (gobj_cat.is_debug()) { 01778 gobj_cat.debug() 01779 << this << ".make_indexed()\n"; 01780 } 01781 01782 nassertv(cdata->_num_vertices != -1); 01783 cdata->_vertices = make_index_data(); 01784 GeomVertexWriter index(cdata->_vertices.get_write_pointer(), 0); 01785 index.reserve_num_rows(cdata->_num_vertices); 01786 for (int i = 0; i < cdata->_num_vertices; ++i) { 01787 index.add_data1i(i + cdata->_first_vertex); 01788 } 01789 cdata->_num_vertices = -1; 01790 } 01791 } 01792 01793 //////////////////////////////////////////////////////////////////// 01794 // Function: GeomPrimitive::consider_elevate_index_type 01795 // Access: Private 01796 // Description: If the indicated new vertex index won't fit in the 01797 // specified index type, automatically elevates the 01798 // index type to the next available size. 01799 //////////////////////////////////////////////////////////////////// 01800 void GeomPrimitive:: 01801 consider_elevate_index_type(CData *cdata, int vertex) { 01802 switch (cdata->_index_type) { 01803 case NT_uint8: 01804 if (vertex > 0xff) { 01805 do_set_index_type(cdata, NT_uint16); 01806 } 01807 break; 01808 01809 case NT_uint16: 01810 if (vertex > 0xffff) { 01811 do_set_index_type(cdata, NT_uint32); 01812 } 01813 break; 01814 01815 case NT_uint32: 01816 // Not much we can do here. 01817 nassertv(vertex <= 0x7fffffff); 01818 break; 01819 01820 default: 01821 break; 01822 } 01823 } 01824 01825 //////////////////////////////////////////////////////////////////// 01826 // Function: GeomPrimitive::do_set_index_type 01827 // Access: Private 01828 // Description: The private implementation of set_index_type(). 01829 //////////////////////////////////////////////////////////////////// 01830 void GeomPrimitive:: 01831 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) { 01832 cdata->_index_type = index_type; 01833 01834 if (gobj_cat.is_debug()) { 01835 gobj_cat.debug() 01836 << this << ".set_index_type(" << index_type << ")\n"; 01837 } 01838 01839 if (!cdata->_vertices.is_null()) { 01840 CPT(GeomVertexArrayFormat) new_format = get_index_format(); 01841 01842 CPT(GeomVertexArrayData) array_obj = cdata->_vertices.get_read_pointer(); 01843 if (array_obj->get_array_format() != new_format) { 01844 PT(GeomVertexArrayData) new_vertices = make_index_data(); 01845 new_vertices->set_num_rows(array_obj->get_num_rows()); 01846 01847 GeomVertexReader from(array_obj, 0); 01848 GeomVertexWriter to(new_vertices, 0); 01849 01850 while (!from.is_at_end()) { 01851 to.set_data1i(from.get_data1i()); 01852 } 01853 cdata->_vertices = new_vertices; 01854 cdata->_got_minmax = false; 01855 } 01856 } 01857 } 01858 01859 //////////////////////////////////////////////////////////////////// 01860 // Function: GeomPrimitive::do_modify_vertices 01861 // Access: Private 01862 // Description: The private implementation of modify_vertices(). 01863 //////////////////////////////////////////////////////////////////// 01864 PT(GeomVertexArrayData) GeomPrimitive:: 01865 do_modify_vertices(GeomPrimitive::CData *cdata) { 01866 if (cdata->_vertices.is_null()) { 01867 do_make_indexed(cdata); 01868 } 01869 01870 PT(GeomVertexArrayData) vertices = cdata->_vertices.get_write_pointer(); 01871 01872 cdata->_modified = Geom::get_next_modified(); 01873 cdata->_got_minmax = false; 01874 return vertices; 01875 } 01876 01877 //////////////////////////////////////////////////////////////////// 01878 // Function: GeomPrimitive::write_datagram 01879 // Access: Public, Virtual 01880 // Description: Writes the contents of this object to the datagram 01881 // for shipping out to a Bam file. 01882 //////////////////////////////////////////////////////////////////// 01883 void GeomPrimitive:: 01884 write_datagram(BamWriter *manager, Datagram &dg) { 01885 TypedWritable::write_datagram(manager, dg); 01886 01887 manager->write_cdata(dg, _cycler); 01888 } 01889 01890 //////////////////////////////////////////////////////////////////// 01891 // Function: GeomPrimitive::finalize 01892 // Access: Public, Virtual 01893 // Description: Called by the BamReader to perform any final actions 01894 // needed for setting up the object after all objects 01895 // have been read and all pointers have been completed. 01896 //////////////////////////////////////////////////////////////////// 01897 void GeomPrimitive:: 01898 finalize(BamReader *manager) { 01899 const GeomVertexArrayData *vertices = get_vertices(); 01900 if (vertices != (GeomVertexArrayData *)NULL) { 01901 set_usage_hint(vertices->get_usage_hint()); 01902 } 01903 } 01904 01905 //////////////////////////////////////////////////////////////////// 01906 // Function: GeomPrimitive::fillin 01907 // Access: Protected 01908 // Description: This internal function is called by make_from_bam to 01909 // read in all of the relevant data from the BamFile for 01910 // the new GeomPrimitive. 01911 //////////////////////////////////////////////////////////////////// 01912 void GeomPrimitive:: 01913 fillin(DatagramIterator &scan, BamReader *manager) { 01914 TypedWritable::fillin(scan, manager); 01915 01916 manager->read_cdata(scan, _cycler); 01917 manager->register_finalize(this); 01918 } 01919 01920 //////////////////////////////////////////////////////////////////// 01921 // Function: GeomPrimitive::CData::make_copy 01922 // Access: Public, Virtual 01923 // Description: 01924 //////////////////////////////////////////////////////////////////// 01925 CycleData *GeomPrimitive::CData:: 01926 make_copy() const { 01927 return new CData(*this); 01928 } 01929 01930 //////////////////////////////////////////////////////////////////// 01931 // Function: GeomPrimitive::CData::write_datagram 01932 // Access: Public, Virtual 01933 // Description: Writes the contents of this object to the datagram 01934 // for shipping out to a Bam file. 01935 //////////////////////////////////////////////////////////////////// 01936 void GeomPrimitive::CData:: 01937 write_datagram(BamWriter *manager, Datagram &dg) const { 01938 dg.add_uint8(_shade_model); 01939 dg.add_int32(_first_vertex); 01940 dg.add_int32(_num_vertices); 01941 dg.add_uint8(_index_type); 01942 dg.add_uint8(_usage_hint); 01943 01944 manager->write_pointer(dg, _vertices.get_read_pointer()); 01945 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends); 01946 } 01947 01948 //////////////////////////////////////////////////////////////////// 01949 // Function: GeomPrimitive::CData::complete_pointers 01950 // Access: Public, Virtual 01951 // Description: Receives an array of pointers, one for each time 01952 // manager->read_pointer() was called in fillin(). 01953 // Returns the number of pointers processed. 01954 //////////////////////////////////////////////////////////////////// 01955 int GeomPrimitive::CData:: 01956 complete_pointers(TypedWritable **p_list, BamReader *manager) { 01957 int pi = CycleData::complete_pointers(p_list, manager); 01958 01959 _vertices = DCAST(GeomVertexArrayData, p_list[pi++]); 01960 01961 if (manager->get_file_minor_ver() < 6 && !_vertices.is_null()) { 01962 // Older bam files might have a meaningless number in 01963 // _num_vertices if the primitive is indexed. Nowadays, this 01964 // number is always considered meaningful unless it is -1. 01965 _num_vertices = -1; 01966 } 01967 01968 return pi; 01969 } 01970 01971 //////////////////////////////////////////////////////////////////// 01972 // Function: GeomPrimitive::CData::fillin 01973 // Access: Public, Virtual 01974 // Description: This internal function is called by make_from_bam to 01975 // read in all of the relevant data from the BamFile for 01976 // the new GeomPrimitive. 01977 //////////////////////////////////////////////////////////////////// 01978 void GeomPrimitive::CData:: 01979 fillin(DatagramIterator &scan, BamReader *manager) { 01980 _shade_model = (ShadeModel)scan.get_uint8(); 01981 _first_vertex = scan.get_int32(); 01982 _num_vertices = scan.get_int32(); 01983 _index_type = (NumericType)scan.get_uint8(); 01984 _usage_hint = (UsageHint)scan.get_uint8(); 01985 01986 manager->read_pointer(scan); 01987 READ_PTA(manager, scan, IPD_int::read_datagram, _ends); 01988 01989 _modified = Geom::get_next_modified(); 01990 _got_minmax = false; 01991 } 01992 01993 //////////////////////////////////////////////////////////////////// 01994 // Function: GeomPrimitivePipelineReader::check_minmax 01995 // Access: Public 01996 // Description: Ensures that the primitive's minmax cache has been 01997 // computed. 01998 //////////////////////////////////////////////////////////////////// 01999 void GeomPrimitivePipelineReader:: 02000 check_minmax() const { 02001 if (!_cdata->_got_minmax) { 02002 // We'll need to get a fresh pointer, since another thread might 02003 // already have modified the pointer on the object since we 02004 // queried it. 02005 { 02006 #ifdef DO_PIPELINING 02007 unref_delete((CycleData *)_cdata); 02008 #endif 02009 GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object.p())->_cycler, 02010 false, _current_thread); 02011 ((GeomPrimitivePipelineReader *)this)->_cdata = fresh_cdata; 02012 #ifdef DO_PIPELINING 02013 _cdata->ref(); 02014 #endif 02015 02016 if (!fresh_cdata->_got_minmax) { 02017 // The cache is still stale. We have to do the work of 02018 // freshening it. 02019 ((GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata); 02020 nassertv(fresh_cdata->_got_minmax); 02021 } 02022 02023 // When fresh_cdata goes out of scope, its write lock is 02024 // released, and _cdata reverts to our usual convention of an 02025 // unlocked copy of the data. 02026 } 02027 } 02028 02029 nassertv(_cdata->_got_minmax); 02030 } 02031 02032 //////////////////////////////////////////////////////////////////// 02033 // Function: GeomPrimitivePipelineReader::get_first_vertex 02034 // Access: Public 02035 // Description: 02036 //////////////////////////////////////////////////////////////////// 02037 int GeomPrimitivePipelineReader:: 02038 get_first_vertex() const { 02039 if (_cdata->_vertices.is_null()) { 02040 return _cdata->_first_vertex; 02041 } else if (_vertices_reader->get_num_rows() == 0) { 02042 return 0; 02043 } else { 02044 GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0); 02045 return index.get_data1i(); 02046 } 02047 } 02048 02049 //////////////////////////////////////////////////////////////////// 02050 // Function: GeomPrimitivePipelineReader::get_vertex 02051 // Access: Public 02052 // Description: Returns the ith vertex index in the table. 02053 //////////////////////////////////////////////////////////////////// 02054 int GeomPrimitivePipelineReader:: 02055 get_vertex(int i) const { 02056 if (!_cdata->_vertices.is_null()) { 02057 // The indexed case. 02058 nassertr(i >= 0 && i < _vertices_reader->get_num_rows(), -1); 02059 02060 GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0); 02061 index.set_row_unsafe(i); 02062 return index.get_data1i(); 02063 02064 } else { 02065 // The nonindexed case. 02066 return _cdata->_first_vertex + i; 02067 } 02068 } 02069 02070 //////////////////////////////////////////////////////////////////// 02071 // Function: GeomPrimitivePipelineReader::get_num_primitives 02072 // Access: Public 02073 // Description: 02074 //////////////////////////////////////////////////////////////////// 02075 int GeomPrimitivePipelineReader:: 02076 get_num_primitives() const { 02077 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive(); 02078 02079 if (num_vertices_per_primitive == 0) { 02080 // This is a complex primitive type like a triangle strip: each 02081 // primitive uses a different number of vertices. 02082 return _cdata->_ends.size(); 02083 02084 } else { 02085 // This is a simple primitive type like a triangle: each primitive 02086 // uses the same number of vertices. 02087 return (get_num_vertices() / num_vertices_per_primitive); 02088 } 02089 } 02090 02091 //////////////////////////////////////////////////////////////////// 02092 // Function: GeomPrimitivePipelineReader::check_valid 02093 // Access: Public 02094 // Description: 02095 //////////////////////////////////////////////////////////////////// 02096 bool GeomPrimitivePipelineReader:: 02097 check_valid(const GeomVertexDataPipelineReader *data_reader) const { 02098 return get_num_vertices() == 0 || 02099 get_max_vertex() < data_reader->get_num_rows(); 02100 }