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

panda/src/gobj/geom.cxx

Go to the documentation of this file.
00001 // Filename: geom.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "geom.h"
00020 #include "config_gobj.h"
00021 
00022 #include "graphicsStateGuardianBase.h"
00023 #include "geometricBoundingVolume.h"
00024 #include "datagram.h"
00025 #include "datagramIterator.h"
00026 #include "bamReader.h"
00027 #include "bamWriter.h"
00028 #include "ioPtaDatagramShort.h"
00029 #include "ioPtaDatagramInt.h"
00030 #include "ioPtaDatagramLinMath.h"
00031 #include "indent.h"
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 // Static variables
00035 ////////////////////////////////////////////////////////////////////
00036 
00037 TypeHandle Geom::_type_handle;
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: get_*_nonindexed
00041 //  Description: Retrieves the next component of the nonindexed array.
00042 ////////////////////////////////////////////////////////////////////
00043 static const Vertexf &get_vertex_nonindexed(Geom::VertexIterator &vi) {
00044   return *(vi._array++);
00045 }
00046 static const Normalf &get_normal_nonindexed(Geom::NormalIterator &vi) {
00047   return *(vi._array++);
00048 }
00049 static const TexCoordf &get_texcoord_nonindexed(Geom::TexCoordIterator &vi) {
00050   return *(vi._array++);
00051 }
00052 static const Colorf &get_color_nonindexed(Geom::ColorIterator &vi) {
00053   return *(vi._array++);
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: get_*_indexed
00058 //  Description: Retrieves the next component of the indexed array.
00059 ////////////////////////////////////////////////////////////////////
00060 static const Vertexf &get_vertex_indexed(Geom::VertexIterator &vi) {
00061   return vi._array[*(vi._index++)];
00062 }
00063 static const Normalf &get_normal_indexed(Geom::NormalIterator &vi) {
00064   return vi._array[*(vi._index++)];
00065 }
00066 static const TexCoordf &get_texcoord_indexed(Geom::TexCoordIterator &vi) {
00067   return vi._array[*(vi._index++)];
00068 }
00069 static const Colorf &get_color_indexed(Geom::ColorIterator &vi) {
00070   return vi._array[*(vi._index++)];
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: get_*_noop
00075 //  Description: Doesn't retrieve anything at all.
00076 ////////////////////////////////////////////////////////////////////
00077 static const Vertexf &get_vertex_noop(Geom::VertexIterator &) {
00078   static Vertexf nothing;
00079   return nothing;
00080 }
00081 static const Normalf &get_normal_noop(Geom::NormalIterator &) {
00082   static Normalf nothing;
00083   return nothing;
00084 }
00085 static const TexCoordf &get_texcoord_noop(Geom::TexCoordIterator &) {
00086   static TexCoordf nothing;
00087   return nothing;
00088 }
00089 static const Colorf &get_color_noop(Geom::ColorIterator &) {
00090   static Colorf nothing;
00091   return nothing;
00092 }
00093 
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 //     Function: GeomBindType output operator
00097 //  Description:
00098 ////////////////////////////////////////////////////////////////////
00099 ostream &operator << (ostream &out, GeomBindType t) {
00100   switch (t) {
00101   case G_OFF:
00102     return out << "off";
00103   case G_OVERALL:
00104     return out << "overall";
00105   case G_PER_PRIM:
00106     return out << "per prim";
00107   case G_PER_COMPONENT:
00108     return out << "per component";
00109   case G_PER_VERTEX:
00110     return out << "per vertex";
00111   }
00112   return out << "(**invalid**)";
00113 }
00114 
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: GeomAttrType output operator
00118 //  Description:
00119 ////////////////////////////////////////////////////////////////////
00120 ostream &operator << (ostream &out, GeomAttrType t) {
00121   switch (t) {
00122   case G_COORD:
00123     return out << "coord";
00124   case G_COLOR:
00125     return out << "color";
00126   case G_NORMAL:
00127     return out << "normal";
00128   case G_TEXCOORD:
00129     return out << "texcoord";
00130   }
00131   return out << "(**invalid**)";
00132 }
00133 
00134 ////////////////////////////////////////////////////////////////////
00135 //     Function: Geom::Constructor
00136 //       Access: Public
00137 //  Description:
00138 ////////////////////////////////////////////////////////////////////
00139 Geom::
00140 Geom(void) : dDrawable() {
00141   _prepared_gsg = (GraphicsStateGuardianBase *)NULL;
00142   _prepared_context = (GeomContext *)NULL;
00143   init();
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: Geom::Constructor
00148 //       Access: Public
00149 //  Description:
00150 ////////////////////////////////////////////////////////////////////
00151 Geom::
00152 Geom(const Geom& copy) : dDrawable() {
00153   _prepared_gsg = (GraphicsStateGuardianBase *)NULL;
00154   _prepared_context = (GeomContext *)NULL;
00155   *this = copy;
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: Geom::Destructor
00160 //       Access: Public
00161 //  Description:
00162 ////////////////////////////////////////////////////////////////////
00163 Geom::
00164 ~Geom() {
00165   unprepare();
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: Geom::Copy assignment operator
00170 //       Access: Public
00171 //  Description:
00172 ////////////////////////////////////////////////////////////////////
00173 void Geom::
00174 operator = (const Geom &copy) {
00175   _coords = copy._coords;
00176   _norms = copy._norms;
00177   _colors = copy._colors;
00178   _texcoords = copy._texcoords;
00179 
00180   _vindex = copy._vindex;
00181   _nindex = copy._nindex;
00182   _cindex = copy._cindex;
00183   _tindex = copy._tindex;
00184 
00185   _numprims = copy._numprims;
00186   _num_vertices = copy._num_vertices;
00187   _primlengths = copy._primlengths;
00188   for (int i = 0; i < num_GeomAttrTypes; i++) {
00189     _bind[i] = copy._bind[i];
00190   }
00191 
00192   _get_vertex = copy._get_vertex;
00193   _get_normal = copy._get_normal;
00194   _get_color = copy._get_color;
00195   _get_texcoord = copy._get_texcoord;
00196 
00197   mark_bound_stale();
00198   make_dirty();
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: Geom::calc_tight_bounds
00203 //       Access: Public
00204 //  Description: Expands min_point and max_point to include all of the
00205 //               vertices in the Geom, if any.  found_any is set true
00206 //               if any points are found.  It is the caller's
00207 //               responsibility to initialize min_point, max_point,
00208 //               and found_any before calling this function.
00209 ////////////////////////////////////////////////////////////////////
00210 void Geom::
00211 calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, 
00212                   bool &found_any) const {
00213   Geom::VertexIterator vi = make_vertex_iterator();
00214   int num_prims = get_num_prims();
00215     
00216   for (int p = 0; p < num_prims; p++) {
00217     int length = get_length(p);
00218     for (int v = 0; v < length; v++) {
00219       Vertexf vertex = get_next_vertex(vi);
00220       
00221       if (found_any) {
00222         min_point.set(min(min_point[0], vertex[0]),
00223                       min(min_point[1], vertex[1]),
00224                       min(min_point[2], vertex[2]));
00225         max_point.set(max(max_point[0], vertex[0]),
00226                       max(max_point[1], vertex[1]),
00227                       max(max_point[2], vertex[2]));
00228       } else {
00229         min_point = vertex;
00230         max_point = vertex;
00231         found_any = true;
00232       }
00233     }
00234   }
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: Geom::transform_vertices
00239 //       Access: Public
00240 //  Description: Applies the indicated transform to all of the
00241 //               vertices in the Geom.  If the Geom happens to share a
00242 //               vertex table with another Geom, this operation will
00243 //               duplicate the vertex table instead of breaking the
00244 //               other Geom; however, if multiple Geoms with shared
00245 //               tables are transformed by the same matrix, they will
00246 //               no longer share tables after the operation.  Consider
00247 //               using the GeomTransformer if you will be applying the
00248 //               same transform to multiple Geoms.
00249 ////////////////////////////////////////////////////////////////////
00250 void Geom::
00251 transform_vertices(const LMatrix4f &mat) {
00252   PTA_Vertexf coords;
00253   PTA_ushort index;
00254   get_coords(coords, index);
00255   PTA_Vertexf new_coords;
00256   new_coords.reserve(coords.size());
00257   PTA_Vertexf::const_iterator vi;
00258   for (vi = coords.begin(); vi != coords.end(); ++vi) {
00259     new_coords.push_back((*vi) * mat);
00260   }
00261   nassertv(new_coords.size() == coords.size());
00262   set_coords(new_coords, index);
00263 }
00264 
00265 ////////////////////////////////////////////////////////////////////
00266 //     Function: Geom::set_coords
00267 //       Access: Public
00268 //  Description:
00269 ////////////////////////////////////////////////////////////////////
00270 void Geom::
00271 set_coords(const PTA_Vertexf &coords, 
00272            const PTA_ushort &vindex) {
00273   _coords = coords;
00274   _bind[G_COORD] = G_PER_VERTEX;
00275   _vindex = vindex;
00276 
00277   mark_bound_stale();
00278   make_dirty();
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: Geom::set_coords
00283 //       Access: Public
00284 //  Description:
00285 ////////////////////////////////////////////////////////////////////
00286 void Geom::
00287 set_coords(const PTA_Vertexf &coords, GeomBindType bind,
00288            const PTA_ushort &vindex) {
00289   nassertv(bind==G_PER_VERTEX);
00290   set_coords(coords, vindex);
00291 }
00292 
00293 ////////////////////////////////////////////////////////////////////
00294 //     Function: Geom::set_normals
00295 //       Access: Public
00296 //  Description:
00297 ////////////////////////////////////////////////////////////////////
00298 void Geom::
00299 set_normals(const PTA_Normalf &norms, GeomBindType bind,
00300             const PTA_ushort &nindex) {
00301   _norms = norms;
00302   _bind[G_NORMAL] = bind;
00303   _nindex = nindex;
00304 
00305   make_dirty();
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: Geom::set_colors
00310 //       Access: Public
00311 //  Description:
00312 ////////////////////////////////////////////////////////////////////
00313 void Geom::
00314 set_colors(const PTA_Colorf &colors, GeomBindType bind,
00315            const PTA_ushort &cindex) {
00316   _colors = colors;
00317   _bind[G_COLOR] = bind;
00318   _cindex = cindex;
00319 
00320   make_dirty();
00321 }
00322 
00323 ////////////////////////////////////////////////////////////////////
00324 //     Function: Geom::set_texcoords
00325 //       Access: Public
00326 //  Description:
00327 ////////////////////////////////////////////////////////////////////
00328 void Geom::
00329 set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind,
00330               const PTA_ushort &tindex) {
00331   _texcoords = texcoords;
00332   assert(bind == G_PER_VERTEX || bind == G_OFF);
00333   _bind[G_TEXCOORD] = bind;
00334   _tindex = tindex;
00335 
00336   make_dirty();
00337 }
00338 
00339 ////////////////////////////////////////////////////////////////////
00340 //     Function: Geom::get_coords
00341 //       Access: Public
00342 //  Description:
00343 ////////////////////////////////////////////////////////////////////
00344 void Geom::
00345 get_coords(PTA_Vertexf &coords,
00346            PTA_ushort &vindex) const {
00347   coords = _coords;
00348   vindex = _vindex;
00349 
00350   // G_PER_VERTEX is implicit binding
00351 }
00352 
00353 ////////////////////////////////////////////////////////////////////
00354 //     Function: Geom::get_coords
00355 //       Access: Public
00356 //  Description:
00357 ////////////////////////////////////////////////////////////////////
00358 void Geom::
00359 get_coords(PTA_Vertexf &coords, GeomBindType &bind,
00360            PTA_ushort &vindex) const {
00361   coords = _coords;
00362   bind = _bind[G_COORD];
00363   vindex = _vindex;
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: Geom::get_normals
00368 //       Access: Public
00369 //  Description:
00370 ////////////////////////////////////////////////////////////////////
00371 void Geom::
00372 get_normals(PTA_Normalf &norms, GeomBindType &bind,
00373             PTA_ushort &nindex) const {
00374   norms = _norms;
00375   bind = _bind[G_NORMAL];
00376   nindex = _nindex;
00377 }
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //     Function: Geom::get_colors
00381 //       Access: Public
00382 //  Description:
00383 ////////////////////////////////////////////////////////////////////
00384 void Geom::
00385 get_colors(PTA_Colorf &colors, GeomBindType &bind,
00386            PTA_ushort &cindex) const {
00387   colors = _colors;
00388   bind = _bind[G_COLOR];
00389   cindex = _cindex;
00390 }
00391 
00392 ////////////////////////////////////////////////////////////////////
00393 //     Function: Geom::get_texcoords
00394 //       Access: Public
00395 //  Description:
00396 ////////////////////////////////////////////////////////////////////
00397 void Geom::
00398 get_texcoords(PTA_TexCoordf &texcoords, GeomBindType &bind,
00399               PTA_ushort &tindex) const {
00400   texcoords = _texcoords;
00401   bind = _bind[G_TEXCOORD];
00402   tindex = _tindex;
00403 }
00404 
00405 ////////////////////////////////////////////////////////////////////
00406 //     Function: Geom::is_dynamic
00407 //       Access: Public, Virtual
00408 //  Description: Returns true if the Geom has any dynamic properties
00409 //               that are expected to change from one frame to the
00410 //               next, or false if the Geom is largely static.  For
00411 //               now, this is the same thing as asking whether its
00412 //               vertices are indexed.
00413 ////////////////////////////////////////////////////////////////////
00414 bool Geom::
00415 is_dynamic() const {
00416   return (_vindex != (ushort*)0L);
00417 }
00418 
00419 ////////////////////////////////////////////////////////////////////
00420 //     Function: Geom::explode
00421 //       Access: Public, Virtual
00422 //  Description: If the Geom is a composite type such as a tristrip,
00423 //               this allocates and returns a new Geom that represents
00424 //               the same geometry as a simple type, for instance a
00425 //               set of triangles.  If the Geom is already a simple
00426 //               type, this allocates and returns a copy.  This is
00427 //               just a convenience function for dealing with
00428 //               composite types when performance is less than
00429 //               paramount.
00430 ////////////////////////////////////////////////////////////////////
00431 Geom *Geom::
00432 explode() const {
00433   return make_copy();
00434 }
00435 
00436 ////////////////////////////////////////////////////////////////////
00437 //     Function: Geom::get_tris
00438 //       Access: Public, Virtual
00439 //  Description: This is similar in principle to explode(), except it
00440 //               returns only a list of triangle vertex indices, with
00441 //               no information about color or whatever.  The array
00442 //               returned is a set of indices into the geom's _coords
00443 //               array, as retrieve by get_coords(); there will be 3*n
00444 //               elements in the array, where n is the number of
00445 //               triangles described by the geometry.  This is useful
00446 //               when it's important to determine the physical
00447 //               structure of the geometry, without necessarily
00448 //               worrying about its rendering properties, and when
00449 //               performance considerations are not overwhelming.
00450 ////////////////////////////////////////////////////////////////////
00451 PTA_ushort Geom::
00452 get_tris() const {
00453   return PTA_ushort();
00454 }
00455 
00456 ////////////////////////////////////////////////////////////////////
00457 //     Function: Geom::draw
00458 //       Access: Public, Virtual
00459 //  Description: Actually draws the Geom with the indicated GSG.
00460 ////////////////////////////////////////////////////////////////////
00461 void Geom::
00462 draw(GraphicsStateGuardianBase *gsg) {
00463   if (is_dirty()) {
00464     config(); 
00465   }
00466   if (_prepared_gsg == gsg) {
00467     draw_immediate(gsg, _prepared_context);
00468   } else {
00469     draw_immediate(gsg, (GeomContext *)NULL);
00470   }
00471 }
00472 
00473 ////////////////////////////////////////////////////////////////////
00474 //     Function: Geom::config
00475 //       Access: Public, Virtual
00476 //  Description: Configure rendering based on current settings
00477 ////////////////////////////////////////////////////////////////////
00478 void Geom::
00479 config() {
00480   WritableConfigurable::config();
00481 
00482   // Only per vertex binding makes any sense
00483   if (_coords != (Vertexf*)0L && _bind[G_COORD] != G_OFF) {
00484     _get_vertex =
00485       (_vindex == (ushort*)0L) ? get_vertex_nonindexed : get_vertex_indexed;
00486   } else {
00487     gobj_cat.error()
00488       << "Geom::Config() - no vertex array!" << endl;
00489   }
00490 
00491   // Set up normal rendering configuration
00492   if (_norms != (Normalf*)0L && _bind[G_NORMAL] != G_OFF) {
00493     _get_normal =
00494       (_nindex == (ushort*)0L) ? get_normal_nonindexed : get_normal_indexed;
00495   } else {
00496     _get_normal = get_normal_noop;
00497   }
00498 
00499   // Set up texture coordinate rendering configuration
00500   if (_texcoords != (TexCoordf*)0L && _bind[G_TEXCOORD] != G_OFF) {
00501     _get_texcoord =
00502       (_tindex == (ushort*)0L) ? get_texcoord_nonindexed : get_texcoord_indexed;
00503   } else {
00504     _get_texcoord = get_texcoord_noop;
00505   }
00506 
00507   // Set up color rendering configuration
00508   if (_colors != (Colorf*)0L && _bind[G_COLOR] != G_OFF) {
00509     _get_color =
00510       (_cindex == (ushort*)0L) ? get_color_nonindexed : get_color_indexed;
00511   } else {
00512     _get_color = get_color_noop;
00513   }
00514 
00515   // Mark the Geom as needing to be prepared again.
00516   unprepare();
00517 }
00518 
00519 ////////////////////////////////////////////////////////////////////
00520 //     Function: Geom::write
00521 //       Access: Public
00522 //  Description:
00523 ////////////////////////////////////////////////////////////////////
00524 void Geom::
00525 write(ostream &out, int indent_level) const {
00526   indent(out, indent_level) << *this << endl;
00527 }
00528 
00529 ////////////////////////////////////////////////////////////////////
00530 //     Function: Geom::output
00531 //       Access: Public, Virtual
00532 //  Description:
00533 ////////////////////////////////////////////////////////////////////
00534 void Geom::
00535 output(ostream &out) const {
00536   out << get_type() << " (" << _numprims << ")";
00537 
00538   /*
00539       << " v:" << _coords.size()
00540       << " n:" << _norms.size()
00541       << " c:" << _colors.size()
00542       << " t:" << _texcoords.size()
00543       << " vi:" << _vindex.size()
00544       << " ni:" << _nindex.size()
00545       << " ci:" << _cindex.size()
00546       << " ti:" << _tindex.size();
00547   */
00548 }
00549 
00550 ////////////////////////////////////////////////////////////////////
00551 //     Function: Geom::prepare
00552 //       Access: Public
00553 //  Description: Creates a context for the Geom on the particular
00554 //               GSG, if it does not already exist.  Returns the new
00555 //               (or old) GeomContext.
00556 //
00557 //               If the given GeomContext pointer is non-NULL, it will
00558 //               be passed to the GSG, which may or may not choose to
00559 //               extend the existing GeomContext, or create a totally
00560 //               new one.
00561 ////////////////////////////////////////////////////////////////////
00562 GeomContext *Geom::
00563 prepare(GraphicsStateGuardianBase *gsg) {
00564   if (gsg != _prepared_gsg) {
00565     GeomContext *gc = gsg->prepare_geom(this);
00566     if (gc != (GeomContext *)NULL) {
00567       unprepare();
00568       _prepared_context = gc;
00569       _prepared_gsg = gsg;
00570     }
00571     return gc;
00572   }
00573 
00574   return _prepared_context;
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: Geom::unprepare
00579 //       Access: Public
00580 //  Description: Frees the context allocated on all GSG's for which
00581 //               the geom has been declared.
00582 ////////////////////////////////////////////////////////////////////
00583 void Geom::
00584 unprepare() {
00585   if (_prepared_gsg != (GraphicsStateGuardianBase *)NULL) {
00586     _prepared_gsg->release_geom(_prepared_context);
00587     _prepared_gsg = (GraphicsStateGuardianBase *)NULL;
00588     _prepared_context = (GeomContext *)NULL;
00589   }
00590 }
00591 
00592 ////////////////////////////////////////////////////////////////////
00593 //     Function: Geom::unprepare
00594 //       Access: Public
00595 //  Description: Frees the geom context only on the indicated GSG,
00596 //               if it exists there.
00597 ////////////////////////////////////////////////////////////////////
00598 void Geom::
00599 unprepare(GraphicsStateGuardianBase *gsg) {
00600   if (_prepared_gsg == gsg) {
00601     _prepared_gsg->release_geom(_prepared_context);
00602     _prepared_gsg = (GraphicsStateGuardianBase *)NULL;
00603     _prepared_context = (GeomContext *)NULL;
00604   }
00605 }
00606 
00607 ////////////////////////////////////////////////////////////////////
00608 //     Function: Geom::clear_gsg
00609 //       Access: Public
00610 //  Description: Removes the indicated GSG from the Geom's known
00611 //               GSG's, without actually releasing the geom on that
00612 //               GSG.  This is intended to be called only from
00613 //               GSG::release_geom(); it should never be called by
00614 //               user code.
00615 ////////////////////////////////////////////////////////////////////
00616 void Geom::
00617 clear_gsg(GraphicsStateGuardianBase *gsg) {
00618   if (_prepared_gsg == gsg) {
00619     _prepared_gsg = (GraphicsStateGuardianBase *)NULL;
00620     _prepared_context = (GeomContext *)NULL;
00621   }
00622 }
00623 
00624 ////////////////////////////////////////////////////////////////////
00625 //     Function: Geom::init
00626 //       Access: Protected
00627 //  Description:
00628 ////////////////////////////////////////////////////////////////////
00629 void Geom::
00630 init() {
00631   int i;
00632 
00633   _coords.clear();
00634   _norms.clear();
00635   _colors.clear();
00636   _texcoords.clear();
00637   _vindex.clear();
00638   _nindex.clear();
00639   _cindex.clear();
00640   _tindex.clear();
00641   _primlengths.clear();
00642 
00643   for ( i = 0; i < num_GeomAttrTypes; i++ )
00644     _bind[i] = G_OFF;
00645 
00646   _get_vertex = get_vertex_noop;
00647   _get_normal = get_normal_noop;
00648   _get_texcoord = get_texcoord_noop;
00649   _get_color = get_color_noop;
00650 
00651   WritableConfigurable::config();
00652 }
00653 
00654 ////////////////////////////////////////////////////////////////////
00655 //     Function: Geom::recompute_bound
00656 //       Access: Protected, Virtual
00657 //  Description: Recomputes the dynamic bounding volume for this Geom.
00658 //               This includes all of the vertices.
00659 ////////////////////////////////////////////////////////////////////
00660 BoundingVolume *Geom::
00661 recompute_bound() {
00662   // First, get ourselves a fresh, empty bounding volume.
00663   BoundingVolume *bound = BoundedObject::recompute_bound();
00664   nassertr(bound != (BoundingVolume*)0L, bound);
00665 
00666   GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
00667 
00668   // Now actually compute the bounding volume by putting it around all
00669   // of our vertices.
00670   pvector<LPoint3f> vertices;
00671   VertexIterator vi = make_vertex_iterator();
00672 
00673   for (int p = 0; p < get_num_prims(); p++) {
00674     for (int v = 0; v < get_length(p); v++) {
00675       vertices.push_back(get_next_vertex(vi));
00676     }
00677   }
00678 
00679   const LPoint3f *vertices_begin = &vertices[0];
00680   const LPoint3f *vertices_end = vertices_begin + vertices.size();
00681 
00682   gbv->around(vertices_begin, vertices_end);
00683 
00684   return bound;
00685 }
00686 
00687 ////////////////////////////////////////////////////////////////////
00688 //     Function: Geom::write_datagram
00689 //       Access: Public
00690 //  Description: Function to write the important information in
00691 //               the particular object to a Datagram
00692 ////////////////////////////////////////////////////////////////////
00693 void Geom::
00694 write_datagram(BamWriter *manager, Datagram &me) {
00695   int i;
00696 
00697   //Coordinates
00698   WRITE_PTA(manager, me, IPD_Vertexf::write_datagram, _coords)
00699   //Normals
00700   WRITE_PTA(manager, me, IPD_Normalf::write_datagram, _norms)
00701   //Colors
00702   WRITE_PTA(manager, me, IPD_Colorf::write_datagram, _colors)
00703   //Texture Coordinates
00704   WRITE_PTA(manager, me, IPD_TexCoordf::write_datagram, _texcoords)
00705 
00706   //Now write out the indices for each array
00707   WRITE_PTA(manager, me, IPD_ushort::write_datagram, _vindex)
00708   WRITE_PTA(manager, me, IPD_ushort::write_datagram, _nindex)
00709   WRITE_PTA(manager, me, IPD_ushort::write_datagram, _cindex)
00710   WRITE_PTA(manager, me, IPD_ushort::write_datagram, _tindex)
00711 
00712   me.add_uint16(_numprims);
00713   WRITE_PTA(manager, me, IPD_int::write_datagram, _primlengths)
00714 
00715   //Write out the bindings for vertices, normals,
00716   //colors and texture coordinates
00717   for(i = 0; i < num_GeomAttrTypes; i++) {
00718     me.add_uint8(_bind[i]);
00719   }
00720 }
00721 
00722 
00723 ////////////////////////////////////////////////////////////////////
00724 //     Function: Geom::fillin
00725 //       Access: Protected
00726 //  Description: Function that reads out of the datagram (or asks
00727 //               manager to read) all of the data that is needed to
00728 //               re-create this object and stores it in the appropiate
00729 //               place
00730 ////////////////////////////////////////////////////////////////////
00731 void Geom::
00732 fillin(DatagramIterator& scan, BamReader* manager) {
00733   int i;
00734 
00735   //Coordinates
00736   READ_PTA(manager, scan, IPD_Vertexf::read_datagram, _coords)
00737   //Normals
00738   READ_PTA(manager, scan, IPD_Normalf::read_datagram, _norms)
00739   //Colors
00740   READ_PTA(manager, scan, IPD_Colorf::read_datagram, _colors)
00741   //Texture Coordinates
00742   READ_PTA(manager, scan, IPD_TexCoordf::read_datagram, _texcoords)
00743 
00744   //Now read in the indices for each array
00745   READ_PTA(manager, scan, IPD_ushort::read_datagram, _vindex)
00746   READ_PTA(manager, scan, IPD_ushort::read_datagram, _nindex)
00747   READ_PTA(manager, scan, IPD_ushort::read_datagram, _cindex)
00748   READ_PTA(manager, scan, IPD_ushort::read_datagram, _tindex)
00749 
00750   _numprims = scan.get_uint16();
00751 
00752   // is there any point in doing this for uses_components()==false?
00753   READ_PTA(manager, scan, IPD_int::read_datagram, _primlengths)
00754 
00755   if (uses_components()) {
00756       _num_vertices = PTA_int_arraysum(_primlengths);
00757   } else {
00758       // except for strips & fans with the length arrays, total verts will be simply this
00759       _num_vertices = _numprims*get_num_vertices_per_prim();
00760   }
00761 
00762   //Write out the bindings for vertices, normals,
00763   //colors and texture coordinates
00764   for(i = 0; i < num_GeomAttrTypes; i++) {
00765     _bind[i] = (enum GeomBindType) scan.get_uint8();
00766   }
00767 }
00768 
00769 ////////////////////////////////////////////////////////////////////
00770 //     Function: describe_attr
00771 //  Description: A handy helper function for output_verbose,
00772 //               below.
00773 ////////////////////////////////////////////////////////////////////
00774 template <class VecType>
00775 static void
00776 describe_attr(ostream &out, const Geom *geom,
00777               GeomBindType bind, const PTA(VecType) &array,
00778               bool newline, int indent_level) {
00779   PTA_int lengths = geom->get_lengths();
00780   int num_prims = geom->get_num_prims();
00781   bool components = geom->uses_components();
00782 
00783   int i, j, vi;
00784   switch (bind) {
00785   case G_PER_VERTEX:
00786     indent(out, indent_level)
00787       << "Per vertex:";
00788     vi = 0;
00789     int num_verts;
00790     num_verts = geom->get_num_vertices_per_prim();
00791     for (i = 0; i < num_prims; i++) {
00792       if (components) {
00793         num_verts = lengths[i];
00794       }
00795       out << "\n";
00796       indent(out, indent_level) << "[ ";
00797       if (num_verts > 0) {
00798         out << array[vi++];
00799         for (j = 1; j < num_verts; j++) {
00800           if (newline) {
00801             out << "\n";
00802             indent(out, indent_level + 2);
00803           } else {
00804             out << " ";
00805           }
00806           out << array[vi++];
00807         }
00808       }
00809       out << " ]";
00810     }
00811     break;
00812 
00813   case G_PER_COMPONENT:
00814     if (!components) {
00815       indent(out, indent_level)
00816         << "Invalid per-component attribute specified!";
00817     } else {
00818       indent(out, indent_level)
00819         << "Per component:";
00820       vi = 0;
00821       for (i = 0; i < num_prims; i++) {
00822         num_verts = lengths[i] - geom->get_num_more_vertices_than_components();
00823         out << "\n";
00824         indent(out, indent_level) << "[ ";
00825         if (num_verts > 0) {
00826           out << array[vi++];
00827           for (j = 1; j < num_verts; j++) {
00828             if (newline) {
00829               out << "\n";
00830               indent(out, indent_level + 2);
00831             } else {
00832               out << " ";
00833             }
00834             out << array[vi++];
00835           }
00836           out << " ]";
00837         }
00838       }
00839     }
00840     break;
00841 
00842   case G_PER_PRIM:
00843     indent(out, indent_level)
00844       << "Per prim:";
00845     for (i = 0; i < num_prims; i++) {
00846       if (newline) {
00847         out << "\n";
00848         indent(out, indent_level + 2);
00849       } else {
00850         out << " ";
00851       }
00852       out << array[i];
00853     }
00854     break;
00855 
00856   case G_OVERALL:
00857     indent(out, indent_level)
00858       << "Overall:";
00859     if (newline) {
00860       out << "\n";
00861       indent(out, indent_level + 2);
00862     } else {
00863       out << " ";
00864     }
00865     out << array[0];
00866 
00867   case G_OFF:
00868     break;
00869   }
00870   out << "\n";
00871 }
00872 
00873 ////////////////////////////////////////////////////////////////////
00874 //     Function: Geom::write_verbose
00875 //       Access: Public
00876 //  Description: Writes to the indicated ostream a formatted picture
00877 //               of the contents of the Geom, in detail--but hopefully
00878 //               not too much detail.
00879 ////////////////////////////////////////////////////////////////////
00880 void Geom::
00881 write_verbose(ostream &out, int indent_level) const {
00882   GeomBindType bind_normals;
00883   GeomBindType bind_tcoords;
00884   GeomBindType bind_colors;
00885 
00886   PTA_Vertexf g_coords;
00887   PTA_Normalf g_normals;
00888   PTA_TexCoordf g_tcoords;
00889   PTA_Colorf g_colors;
00890 
00891   PTA_ushort i_coords;
00892   PTA_ushort i_normals;
00893   PTA_ushort i_tcoords;
00894   PTA_ushort i_colors;
00895 
00896   get_coords(g_coords, i_coords);
00897   get_normals(g_normals, bind_normals, i_normals);
00898   get_texcoords(g_tcoords, bind_tcoords, i_tcoords);
00899   get_colors(g_colors, bind_colors, i_colors);
00900 
00901   out << "\n";
00902   indent(out, indent_level)
00903     << get_type() << " contains "
00904     << get_num_prims() << " primitives:\n";
00905 
00906   if ((i_coords == (ushort *)NULL) && (g_coords == (Vertexf *)NULL)) {
00907     indent(out, indent_level)
00908       << "No coords\n";
00909   } else if (i_coords!=(ushort*)0L) {
00910     indent(out, indent_level)
00911       << "Indexed coords = " << (void *)g_coords << ", length = "
00912       << g_coords.size() << ":\n";
00913     describe_attr(out, this, G_PER_VERTEX, i_coords, false, indent_level + 2);
00914   } else {
00915     indent(out, indent_level)
00916       << "Nonindexed coords:\n";
00917     describe_attr(out, this, G_PER_VERTEX, g_coords, true, indent_level + 2);
00918   }
00919 
00920   if (bind_colors == G_OFF) {
00921     indent(out, indent_level)
00922       << "No colors\n";
00923   } else if (i_colors!=(ushort*)0L) {
00924     indent(out, indent_level)
00925       << "Indexed colors = " << (void *)g_colors << ", length = "
00926       << g_colors.size() << "\n";
00927     describe_attr(out, this, bind_colors, i_colors, false, indent_level + 2);
00928   } else {
00929     indent(out, indent_level)
00930       << "Nonindexed colors:\n";
00931     describe_attr(out, this, bind_colors, g_colors, true, indent_level + 2);
00932   }
00933 
00934   if (bind_tcoords == G_OFF) {
00935     indent(out, indent_level)
00936       << "No tcoords\n";
00937   } else if (i_tcoords!=(ushort*)0L) {
00938     indent(out, indent_level)
00939       << "Indexed tcoords = " << (void *)g_tcoords << ", length = "
00940       << g_tcoords.size() << "\n";
00941     describe_attr(out, this, bind_tcoords, i_tcoords, false, indent_level + 2);
00942   } else {
00943     indent(out, indent_level)
00944       << "Nonindexed tcoords:\n";
00945     describe_attr(out, this, bind_tcoords, g_tcoords, true, indent_level + 2);
00946   }
00947 
00948   if (bind_normals == G_OFF) {
00949     indent(out, indent_level)
00950       << "No normals\n";
00951   } else if (i_normals!=(ushort*)0L) {
00952     indent(out, indent_level)
00953       << "Indexed normals = " << (void *)g_normals << ", length = "
00954       << g_normals.size() << "\n";
00955     describe_attr(out, this, bind_normals, i_normals, false, indent_level + 2);
00956   } else {
00957     indent(out, indent_level)
00958       << "Nonindexed normals:\n";
00959     describe_attr(out, this, bind_normals, g_normals, true, indent_level + 2);
00960   }
00961 }

Generated on Fri May 2 00:39:20 2003 for Panda by doxygen1.3