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