Panda3D
|
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 ©); 00067 00068 PUBLISHED: 00069 void operator = (const Geom ©); 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 ©); 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 ©); 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 ¶ms); 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 ©); 00389 INLINE void operator = (const GeomPipelineReader ©); 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