Panda3D

geom.h

00001 // Filename: geom.h
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 #ifndef GEOM_H
00016 #define GEOM_H
00017 
00018 #include "pandabase.h"
00019 #include "copyOnWriteObject.h"
00020 #include "copyOnWritePointer.h"
00021 #include "cycleData.h"
00022 #include "cycleDataLockedReader.h"
00023 #include "cycleDataReader.h"
00024 #include "cycleDataWriter.h"
00025 #include "cycleDataStageReader.h"
00026 #include "cycleDataStageWriter.h"
00027 #include "pipelineCycler.h"
00028 #include "geomVertexData.h"
00029 #include "geomPrimitive.h"
00030 #include "geomMunger.h"
00031 #include "geomEnums.h"
00032 #include "geomCacheEntry.h"
00033 #include "textureStage.h"
00034 #include "updateSeq.h"
00035 #include "pointerTo.h"
00036 #include "indirectLess.h"
00037 #include "pset.h"
00038 #include "pmap.h"
00039 #include "boundingVolume.h"
00040 #include "pStatCollector.h"
00041 #include "deletedChain.h"
00042 #include "lightMutex.h"
00043 
00044 class GeomContext;
00045 class PreparedGraphicsObjects;
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //       Class : Geom
00049 // Description : A container for geometry primitives.  This class
00050 //               associates one or more GeomPrimitive objects with a
00051 //               table of vertices defined by a GeomVertexData object.
00052 //               All of the primitives stored in a particular Geom are
00053 //               drawn from the same set of vertices (each primitive
00054 //               uses a subset of all of the vertices in the table),
00055 //               and all of them must be rendered at the same time, in
00056 //               the same graphics state.
00057 ////////////////////////////////////////////////////////////////////
00058 class EXPCL_PANDA_GOBJ Geom : public CopyOnWriteObject, public GeomEnums {
00059 protected:
00060   virtual PT(CopyOnWriteObject) make_cow_copy();
00061 
00062 PUBLISHED:
00063   Geom(const GeomVertexData *data);
00064 
00065 protected:
00066   Geom(const Geom &copy);
00067 
00068 PUBLISHED:
00069   void operator = (const Geom &copy);
00070   virtual ~Geom();
00071   ALLOC_DELETED_CHAIN(Geom);
00072 
00073   virtual Geom *make_copy() const;
00074 
00075   INLINE PrimitiveType get_primitive_type() const;
00076   INLINE ShadeModel get_shade_model() const;
00077   INLINE int get_geom_rendering() const;
00078 
00079   INLINE UsageHint get_usage_hint() const;
00080   void set_usage_hint(UsageHint usage_hint);
00081 
00082   INLINE CPT(GeomVertexData) get_vertex_data(Thread *current_thread = Thread::get_current_thread()) const;
00083   PT(GeomVertexData) modify_vertex_data();
00084   void set_vertex_data(const GeomVertexData *data);
00085   void offset_vertices(const GeomVertexData *data, int offset);
00086   int make_nonindexed(bool composite_only);
00087 
00088   INLINE bool is_empty() const;
00089 
00090   INLINE int get_num_primitives() const;
00091   INLINE CPT(GeomPrimitive) get_primitive(int i) const;
00092   MAKE_SEQ(get_primitives, get_num_primitives, get_primitive);
00093   INLINE PT(GeomPrimitive) modify_primitive(int i);
00094   void set_primitive(int i, const GeomPrimitive *primitive);
00095   void add_primitive(const GeomPrimitive *primitive);
00096   void remove_primitive(int i);
00097   void clear_primitives();
00098 
00099   INLINE PT(Geom) decompose() const;
00100   INLINE PT(Geom) doubleside() const;
00101   INLINE PT(Geom) reverse() const;
00102   INLINE PT(Geom) rotate() const;
00103   INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
00104   INLINE PT(Geom) make_points() const;
00105 
00106   void decompose_in_place();
00107   void doubleside_in_place();
00108   void reverse_in_place();
00109   void rotate_in_place();
00110   void unify_in_place(int max_indices, bool preserve_order);
00111   void make_points_in_place();
00112 
00113   virtual bool copy_primitives_from(const Geom *other);
00114 
00115   int get_num_bytes() const;
00116   INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const;
00117 
00118   bool request_resident() const;
00119 
00120   void transform_vertices(const LMatrix4 &mat);
00121   bool check_valid() const;
00122   bool check_valid(const GeomVertexData *vertex_data) const;
00123 
00124   CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const;
00125   int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const;
00126   INLINE void mark_bounds_stale() const;
00127   INLINE void set_bounds_type(BoundingVolume::BoundsType bounds_type);
00128   INLINE BoundingVolume::BoundsType get_bounds_type() const;
00129   INLINE void set_bounds(const BoundingVolume *volume);
00130   INLINE void clear_bounds();
00131 
00132   virtual void output(ostream &out) const;
00133   virtual void write(ostream &out, int indent_level = 0) const;
00134 
00135   void clear_cache();
00136   void clear_cache_stage(Thread *current_thread);
00137 
00138   void prepare(PreparedGraphicsObjects *prepared_objects);
00139   bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
00140   bool release(PreparedGraphicsObjects *prepared_objects);
00141   int release_all();
00142 
00143   GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects, 
00144                            GraphicsStateGuardianBase *gsg);
00145 
00146 public:
00147   bool draw(GraphicsStateGuardianBase *gsg, 
00148             const GeomMunger *munger,
00149             const GeomVertexData *vertex_data,
00150             bool force, Thread *current_thread) const;
00151   
00152   INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00153                                 bool &found_any, 
00154                                 const GeomVertexData *vertex_data,
00155                                 bool got_mat, const LMatrix4 &mat,
00156                                 Thread *current_thread) const;
00157   INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00158                                 bool &found_any, Thread *current_thread) const;
00159   INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00160                                 bool &found_any, 
00161                                 const GeomVertexData *vertex_data,
00162                                 bool got_mat, const LMatrix4 &mat,
00163                                 const InternalName *column_name,
00164                                 Thread *current_thread) const;
00165 
00166   static UpdateSeq get_next_modified();
00167 
00168 private:
00169   class CData;
00170 
00171   INLINE void mark_internal_bounds_stale(CData *cdata);
00172   void compute_internal_bounds(CData *cdata, Thread *current_thread) const;
00173 
00174   void do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00175                             bool &found_any, 
00176                             const GeomVertexData *vertex_data,
00177                             bool got_mat, const LMatrix4 &mat,
00178                             const InternalName *column_name,
00179                             const CData *cdata, Thread *current_thread) const;
00180 
00181   void clear_prepared(PreparedGraphicsObjects *prepared_objects);
00182   bool check_will_be_valid(const GeomVertexData *vertex_data) const;
00183 
00184   void reset_usage_hint(CData *cdata);
00185   void reset_geom_rendering(CData *cdata);
00186 
00187   void combine_primitives(GeomPrimitive *a_prim, const GeomPrimitive *b_prim,
00188                           Thread *current_thread);
00189 
00190 private:
00191   typedef pvector<COWPT(GeomPrimitive) > Primitives;
00192 
00193   // We have to use reference-counting pointers here instead of having
00194   // explicit cleanup in the GeomVertexFormat destructor, because the
00195   // cache needs to be stored in the CycleData, which makes accurate
00196   // cleanup more difficult.  We use the GeomCacheManager class to
00197   // avoid cache bloat.
00198 
00199   // Note: the above comment is no longer true.  The cache is not
00200   // stored in the CycleData, which just causes problems; instead, we
00201   // cycle each individual CacheEntry as needed.  Need to investigate
00202   // if we could simplify the cache system now.
00203 
00204   // The pipelined data with each CacheEntry.
00205   class EXPCL_PANDA_GOBJ CDataCache : public CycleData {
00206   public:
00207     INLINE CDataCache();
00208     INLINE CDataCache(const CDataCache &copy);
00209     virtual ~CDataCache();
00210     ALLOC_DELETED_CHAIN(CDataCache);
00211     virtual CycleData *make_copy() const;
00212     virtual TypeHandle get_parent_type() const {
00213       return Geom::get_class_type();
00214     }
00215 
00216     INLINE void set_result(const Geom *geom_result, const GeomVertexData *data_result);
00217 
00218     Geom *_source;  // A back pointer to the containing Geom
00219     const Geom *_geom_result;  // ref-counted if not NULL and not same as _source
00220     CPT(GeomVertexData) _data_result;
00221     
00222   public:
00223     static TypeHandle get_class_type() {
00224       return _type_handle;
00225     }
00226     static void init_type() {
00227       register_type(_type_handle, "Geom::CDataCache");
00228     }
00229     
00230   private:
00231     static TypeHandle _type_handle;
00232   };
00233   typedef CycleDataReader<CDataCache> CDCacheReader;
00234   typedef CycleDataWriter<CDataCache> CDCacheWriter;
00235 
00236 public:
00237   // The CacheKey class separates out just the part of CacheEntry that
00238   // is used to key the cache entry within the map.  We have this as a
00239   // separate class so we can easily look up a new entry in the map,
00240   // without having to execute the relatively expensive CacheEntry
00241   // constructor.
00242   class CacheKey {
00243   public:
00244     INLINE CacheKey(const GeomVertexData *source_data,
00245                     const GeomMunger *modifier);
00246     INLINE bool operator < (const CacheKey &other) const;
00247 
00248     CPT(GeomVertexData) _source_data;
00249     CPT(GeomMunger) _modifier;
00250   };
00251   // It is not clear why MSVC7 needs this class to be public.
00252   class CacheEntry : public GeomCacheEntry {
00253   public:
00254     INLINE CacheEntry(Geom *source, 
00255                       const GeomVertexData *source_data,
00256                       const GeomMunger *modifier);
00257     ALLOC_DELETED_CHAIN(CacheEntry);
00258 
00259     virtual void evict_callback();
00260     virtual void output(ostream &out) const;
00261 
00262     Geom *_source;  // A back pointer to the containing Geom
00263     CacheKey _key;
00264 
00265     PipelineCycler<CDataCache> _cycler;
00266     
00267   public:
00268     static TypeHandle get_class_type() {
00269       return _type_handle;
00270     }
00271     static void init_type() {
00272       GeomCacheEntry::init_type();
00273       register_type(_type_handle, "Geom::CacheEntry",
00274                     GeomCacheEntry::get_class_type());
00275     }
00276     
00277   private:
00278     static TypeHandle _type_handle;
00279   };
00280   typedef pmap<const CacheKey *, PT(CacheEntry), IndirectLess<CacheKey> > Cache;
00281 
00282 private:
00283   // This is the data that must be cycled between pipeline stages.
00284   class EXPCL_PANDA_GOBJ CData : public CycleData {
00285   public:
00286     INLINE CData();
00287     INLINE CData(const CData &copy);
00288     ALLOC_DELETED_CHAIN(CData);
00289     virtual CycleData *make_copy() const;
00290     virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
00291     virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
00292     virtual void fillin(DatagramIterator &scan, BamReader *manager);
00293     virtual TypeHandle get_parent_type() const {
00294       return Geom::get_class_type();
00295     }
00296 
00297     COWPT(GeomVertexData) _data;
00298     Primitives _primitives;
00299     PrimitiveType _primitive_type;
00300     ShadeModel _shade_model;
00301     int _geom_rendering;
00302     UsageHint _usage_hint;
00303     bool _got_usage_hint;
00304     UpdateSeq _modified;
00305   
00306     CPT(BoundingVolume) _internal_bounds;
00307     int _nested_vertices;
00308     bool _internal_bounds_stale;
00309     BoundingVolume::BoundsType _bounds_type;
00310     CPT(BoundingVolume) _user_bounds;
00311     
00312   public:
00313     static TypeHandle get_class_type() {
00314       return _type_handle;
00315     }
00316     static void init_type() {
00317       register_type(_type_handle, "Geom::CData");
00318     }
00319     
00320   private:
00321     static TypeHandle _type_handle;
00322   };
00323  
00324   PipelineCycler<CData> _cycler;
00325   typedef CycleDataLockedReader<CData> CDLockedReader;
00326   typedef CycleDataReader<CData> CDReader;
00327   typedef CycleDataWriter<CData> CDWriter;
00328   typedef CycleDataStageReader<CData> CDStageReader;
00329   typedef CycleDataStageWriter<CData> CDStageWriter;
00330 
00331   Cache _cache;
00332   LightMutex _cache_lock;
00333 
00334   // This works just like the Texture contexts: each Geom keeps a
00335   // record of all the PGO objects that hold the Geom, and vice-versa.
00336   typedef pmap<PreparedGraphicsObjects *, GeomContext *> Contexts;
00337   Contexts _contexts;
00338 
00339   static UpdateSeq _next_modified;
00340   static PStatCollector _draw_primitive_setup_pcollector;
00341 
00342 public:
00343   static void register_with_read_factory();
00344   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00345 
00346   virtual void finalize(BamReader *manager);
00347 
00348 protected:
00349   static TypedWritable *make_from_bam(const FactoryParams &params);
00350   void fillin(DatagramIterator &scan, BamReader *manager);
00351 
00352 public:
00353   static TypeHandle get_class_type() {
00354     return _type_handle;
00355   }
00356   static void init_type() {
00357     CopyOnWriteObject::init_type();
00358     register_type(_type_handle, "Geom",
00359                   CopyOnWriteObject::get_class_type());
00360     CDataCache::init_type();
00361     CacheEntry::init_type();
00362     CData::init_type();
00363   }
00364   virtual TypeHandle get_type() const {
00365     return get_class_type();
00366   }
00367   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00368 
00369 private:
00370   static TypeHandle _type_handle;
00371 
00372   friend class CacheEntry;
00373   friend class GeomMunger;
00374   friend class GeomContext;
00375   friend class GeomPipelineReader;
00376   friend class PreparedGraphicsObjects;
00377 };
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //       Class : GeomPipelineReader
00381 // Description : Encapsulates the data from a Geom,
00382 //               pre-fetched for one stage of the pipeline.
00383 ////////////////////////////////////////////////////////////////////
00384 class EXPCL_PANDA_GOBJ GeomPipelineReader : public GeomEnums {
00385 public:
00386   INLINE GeomPipelineReader(const Geom *object, Thread *current_thread);
00387 private:
00388   INLINE GeomPipelineReader(const GeomPipelineReader &copy);
00389   INLINE void operator = (const GeomPipelineReader &copy);
00390 
00391 public:
00392   INLINE ~GeomPipelineReader();
00393   ALLOC_DELETED_CHAIN(GeomPipelineReader);
00394 
00395   INLINE const Geom *get_object() const;
00396   INLINE Thread *get_current_thread() const;
00397 
00398   void check_usage_hint() const;
00399 
00400   INLINE PrimitiveType get_primitive_type() const;
00401   INLINE ShadeModel get_shade_model() const;
00402   INLINE int get_geom_rendering() const;
00403   INLINE UsageHint get_usage_hint() const;
00404   INLINE CPT(GeomVertexData) get_vertex_data() const;
00405   INLINE int get_num_primitives() const;
00406   INLINE CPT(GeomPrimitive) get_primitive(int i) const;
00407 
00408   INLINE UpdateSeq get_modified() const;
00409 
00410   bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
00411 
00412   bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
00413             const GeomVertexDataPipelineReader *data_reader,
00414             bool force) const;
00415 
00416 private:
00417   CPT(Geom) _object;
00418   Thread *_current_thread;
00419   const Geom::CData *_cdata;
00420 
00421 public:
00422   static TypeHandle get_class_type() {
00423     return _type_handle;
00424   }
00425   static void init_type() {
00426     register_type(_type_handle, "GeomPipelineReader");
00427   }
00428 
00429 private:
00430   static TypeHandle _type_handle;
00431 };
00432 
00433 INLINE ostream &operator << (ostream &out, const Geom &obj);
00434 
00435 #include "geom.I"
00436 
00437 #endif
 All Classes Functions Variables Enumerations