Panda3D
geom.h
1 // Filename: geom.h
2 // Created by: drose (06Mar05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef GEOM_H
16 #define GEOM_H
17 
18 #include "pandabase.h"
19 #include "copyOnWriteObject.h"
20 #include "copyOnWritePointer.h"
21 #include "cycleData.h"
22 #include "cycleDataLockedReader.h"
23 #include "cycleDataReader.h"
24 #include "cycleDataWriter.h"
25 #include "cycleDataStageReader.h"
26 #include "cycleDataStageWriter.h"
27 #include "pipelineCycler.h"
28 #include "geomVertexData.h"
29 #include "geomPrimitive.h"
30 #include "geomMunger.h"
31 #include "geomEnums.h"
32 #include "geomCacheEntry.h"
33 #include "textureStage.h"
34 #include "updateSeq.h"
35 #include "pointerTo.h"
36 #include "indirectLess.h"
37 #include "pset.h"
38 #include "pmap.h"
39 #include "boundingVolume.h"
40 #include "pStatCollector.h"
41 #include "deletedChain.h"
42 #include "lightMutex.h"
43 
44 class GeomContext;
46 
47 ////////////////////////////////////////////////////////////////////
48 // Class : Geom
49 // Description : A container for geometry primitives. This class
50 // associates one or more GeomPrimitive objects with a
51 // table of vertices defined by a GeomVertexData object.
52 // All of the primitives stored in a particular Geom are
53 // drawn from the same set of vertices (each primitive
54 // uses a subset of all of the vertices in the table),
55 // and all of them must be rendered at the same time, in
56 // the same graphics state.
57 ////////////////////////////////////////////////////////////////////
58 class EXPCL_PANDA_GOBJ Geom : public CopyOnWriteObject, public GeomEnums {
59 protected:
60  virtual PT(CopyOnWriteObject) make_cow_copy();
61 
62 PUBLISHED:
63  Geom(const GeomVertexData *data);
64 
65 protected:
66  Geom(const Geom &copy);
67 
68 PUBLISHED:
69  void operator = (const Geom &copy);
70  virtual ~Geom();
71  ALLOC_DELETED_CHAIN(Geom);
72 
73  virtual Geom *make_copy() const;
74 
75  INLINE PrimitiveType get_primitive_type() const;
76  INLINE ShadeModel get_shade_model() const;
77  INLINE int get_geom_rendering() const;
78 
79  INLINE UsageHint get_usage_hint() const;
80  void set_usage_hint(UsageHint usage_hint);
81 
82  INLINE CPT(GeomVertexData) get_vertex_data(Thread *current_thread = Thread::get_current_thread()) const;
83  PT(GeomVertexData) modify_vertex_data();
84  void set_vertex_data(const GeomVertexData *data);
85  void offset_vertices(const GeomVertexData *data, int offset);
86  int make_nonindexed(bool composite_only);
87 
88  INLINE bool is_empty() const;
89 
90  INLINE int get_num_primitives() const;
91  INLINE CPT(GeomPrimitive) get_primitive(int i) const;
92  MAKE_SEQ(get_primitives, get_num_primitives, get_primitive);
93  INLINE PT(GeomPrimitive) modify_primitive(int i);
94  void set_primitive(int i, const GeomPrimitive *primitive);
95  void add_primitive(const GeomPrimitive *primitive);
96  void remove_primitive(int i);
97  void clear_primitives();
98 
99  INLINE PT(Geom) decompose() const;
100  INLINE PT(Geom) doubleside() const;
101  INLINE PT(Geom) reverse() const;
102  INLINE PT(Geom) rotate() const;
103  INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
104  INLINE PT(Geom) make_points() const;
105  INLINE PT(Geom) make_lines() const;
106  INLINE PT(Geom) make_patches() const;
107 
108  void decompose_in_place();
109  void doubleside_in_place();
110  void reverse_in_place();
111  void rotate_in_place();
112  void unify_in_place(int max_indices, bool preserve_order);
113  void make_points_in_place();
114  void make_lines_in_place();
115  void make_patches_in_place();
116 
117  virtual bool copy_primitives_from(const Geom *other);
118 
119  int get_num_bytes() const;
120  INLINE UpdateSeq get_modified(Thread *current_thread = Thread::get_current_thread()) const;
121 
122  bool request_resident() const;
123 
124  void transform_vertices(const LMatrix4 &mat);
125  bool check_valid() const;
126  bool check_valid(const GeomVertexData *vertex_data) const;
127 
128  CPT(BoundingVolume) get_bounds(Thread *current_thread = Thread::get_current_thread()) const;
129  int get_nested_vertices(Thread *current_thread = Thread::get_current_thread()) const;
130  INLINE void mark_bounds_stale() const;
131  INLINE void set_bounds_type(BoundingVolume::BoundsType bounds_type);
132  INLINE BoundingVolume::BoundsType get_bounds_type() const;
133  INLINE void set_bounds(const BoundingVolume *volume);
134  INLINE void clear_bounds();
135 
136  virtual void output(ostream &out) const;
137  virtual void write(ostream &out, int indent_level = 0) const;
138 
139  void clear_cache();
140  void clear_cache_stage(Thread *current_thread);
141 
142  void prepare(PreparedGraphicsObjects *prepared_objects);
143  bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
144  bool release(PreparedGraphicsObjects *prepared_objects);
145  int release_all();
146 
147  GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
149 
150 public:
151  bool draw(GraphicsStateGuardianBase *gsg,
152  const GeomMunger *munger,
153  const GeomVertexData *vertex_data,
154  bool force, Thread *current_thread) const;
155 
156  INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
157  bool &found_any,
158  const GeomVertexData *vertex_data,
159  bool got_mat, const LMatrix4 &mat,
160  Thread *current_thread) const;
161  INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
162  bool &found_any, Thread *current_thread) const;
163  INLINE void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
164  bool &found_any,
165  const GeomVertexData *vertex_data,
166  bool got_mat, const LMatrix4 &mat,
167  const InternalName *column_name,
168  Thread *current_thread) const;
169 
170  static UpdateSeq get_next_modified();
171 
172 private:
173  class CData;
174 
175  INLINE void mark_internal_bounds_stale(CData *cdata);
176  void compute_internal_bounds(CData *cdata, Thread *current_thread) const;
177 
178  void do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
179  PN_stdfloat &sq_center_dist, bool &found_any,
180  const GeomVertexData *vertex_data,
181  bool got_mat, const LMatrix4 &mat,
182  const InternalName *column_name,
183  const CData *cdata, Thread *current_thread) const;
184 
185  void do_calc_sphere_radius(const LPoint3 &center,
186  PN_stdfloat &sq_radius, bool &found_any,
187  const GeomVertexData *vertex_data,
188  const CData *cdata, Thread *current_thread) const;
189 
190  void clear_prepared(PreparedGraphicsObjects *prepared_objects);
191  bool check_will_be_valid(const GeomVertexData *vertex_data) const;
192 
193  void reset_usage_hint(CData *cdata);
194  void reset_geom_rendering(CData *cdata);
195 
196  void combine_primitives(GeomPrimitive *a_prim, const GeomPrimitive *b_prim,
197  Thread *current_thread);
198 
199 private:
201 
202  // We have to use reference-counting pointers here instead of having
203  // explicit cleanup in the GeomVertexFormat destructor, because the
204  // cache needs to be stored in the CycleData, which makes accurate
205  // cleanup more difficult. We use the GeomCacheManager class to
206  // avoid cache bloat.
207 
208  // Note: the above comment is no longer true. The cache is not
209  // stored in the CycleData, which just causes problems; instead, we
210  // cycle each individual CacheEntry as needed. Need to investigate
211  // if we could simplify the cache system now.
212 
213  // The pipelined data with each CacheEntry.
214  class EXPCL_PANDA_GOBJ CDataCache : public CycleData {
215  public:
216  INLINE CDataCache();
217  INLINE CDataCache(const CDataCache &copy);
218  virtual ~CDataCache();
219  ALLOC_DELETED_CHAIN(CDataCache);
220  virtual CycleData *make_copy() const;
221  virtual TypeHandle get_parent_type() const {
222  return Geom::get_class_type();
223  }
224 
225  INLINE void set_result(const Geom *geom_result, const GeomVertexData *data_result);
226 
227  Geom *_source; // A back pointer to the containing Geom
228  const Geom *_geom_result; // ref-counted if not NULL and not same as _source
229  CPT(GeomVertexData) _data_result;
230 
231  public:
232  static TypeHandle get_class_type() {
233  return _type_handle;
234  }
235  static void init_type() {
236  register_type(_type_handle, "Geom::CDataCache");
237  }
238 
239  private:
240  static TypeHandle _type_handle;
241  };
244 
245 public:
246  // The CacheKey class separates out just the part of CacheEntry that
247  // is used to key the cache entry within the map. We have this as a
248  // separate class so we can easily look up a new entry in the map,
249  // without having to execute the relatively expensive CacheEntry
250  // constructor.
251  class CacheKey {
252  public:
253  INLINE CacheKey(const GeomVertexData *source_data,
254  const GeomMunger *modifier);
255  INLINE CacheKey(const CacheKey &copy);
256 #ifdef USE_MOVE_SEMANTICS
257  INLINE CacheKey(CacheKey &&from) NOEXCEPT;
258 #endif
259  INLINE bool operator < (const CacheKey &other) const;
260 
261  CPT(GeomVertexData) _source_data;
262  CPT(GeomMunger) _modifier;
263  };
264  // It is not clear why MSVC7 needs this class to be public.
265  class CacheEntry : public GeomCacheEntry {
266  public:
267  INLINE CacheEntry(Geom *source,
268  const GeomVertexData *source_data,
269  const GeomMunger *modifier);
270  INLINE CacheEntry(Geom *source, const CacheKey &key);
271 #ifdef USE_MOVE_SEMANTICS
272  INLINE CacheEntry(Geom *source, CacheKey &&key) NOEXCEPT;
273 #endif
274  ALLOC_DELETED_CHAIN(CacheEntry);
275 
276  virtual void evict_callback();
277  virtual void output(ostream &out) const;
278 
279  Geom *_source; // A back pointer to the containing Geom
280  CacheKey _key;
281 
283 
284  public:
285  static TypeHandle get_class_type() {
286  return _type_handle;
287  }
288  static void init_type() {
289  GeomCacheEntry::init_type();
290  register_type(_type_handle, "Geom::CacheEntry",
291  GeomCacheEntry::get_class_type());
292  }
293 
294  private:
295  static TypeHandle _type_handle;
296  };
298 
299 private:
300  // This is the data that must be cycled between pipeline stages.
301  class EXPCL_PANDA_GOBJ CData : public CycleData {
302  public:
303  INLINE CData();
304  INLINE CData(const CData &copy);
305  ALLOC_DELETED_CHAIN(CData);
306  virtual CycleData *make_copy() const;
307  virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
308  virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
309  virtual void fillin(DatagramIterator &scan, BamReader *manager);
310  virtual TypeHandle get_parent_type() const {
311  return Geom::get_class_type();
312  }
313 
314  COWPT(GeomVertexData) _data;
315  Primitives _primitives;
316  PrimitiveType _primitive_type;
317  ShadeModel _shade_model;
318  int _geom_rendering;
319  UsageHint _usage_hint;
320  bool _got_usage_hint;
321  UpdateSeq _modified;
322 
323  CPT(BoundingVolume) _internal_bounds;
324  int _nested_vertices;
325  bool _internal_bounds_stale;
326  BoundingVolume::BoundsType _bounds_type;
327  CPT(BoundingVolume) _user_bounds;
328 
329  public:
330  static TypeHandle get_class_type() {
331  return _type_handle;
332  }
333  static void init_type() {
334  register_type(_type_handle, "Geom::CData");
335  }
336 
337  private:
338  static TypeHandle _type_handle;
339  };
340 
341  PipelineCycler<CData> _cycler;
347 
348  Cache _cache;
349  LightMutex _cache_lock;
350 
351  // This works just like the Texture contexts: each Geom keeps a
352  // record of all the PGO objects that hold the Geom, and vice-versa.
354  Contexts _contexts;
355 
356  static UpdateSeq _next_modified;
357  static PStatCollector _draw_primitive_setup_pcollector;
358 
359 public:
360  static void register_with_read_factory();
361  virtual void write_datagram(BamWriter *manager, Datagram &dg);
362 
363  virtual void finalize(BamReader *manager);
364 
365 protected:
366  static TypedWritable *make_from_bam(const FactoryParams &params);
367  void fillin(DatagramIterator &scan, BamReader *manager);
368 
369 public:
370  static TypeHandle get_class_type() {
371  return _type_handle;
372  }
373  static void init_type() {
374  CopyOnWriteObject::init_type();
375  register_type(_type_handle, "Geom",
376  CopyOnWriteObject::get_class_type());
377  CDataCache::init_type();
378  CacheEntry::init_type();
379  CData::init_type();
380  }
381  virtual TypeHandle get_type() const {
382  return get_class_type();
383  }
384  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
385 
386 private:
387  static TypeHandle _type_handle;
388 
389  friend class CacheEntry;
390  friend class GeomMunger;
391  friend class GeomContext;
392  friend class GeomPipelineReader;
393  friend class PreparedGraphicsObjects;
394 };
395 
396 ////////////////////////////////////////////////////////////////////
397 // Class : GeomPipelineReader
398 // Description : Encapsulates the data from a Geom,
399 // pre-fetched for one stage of the pipeline.
400 ////////////////////////////////////////////////////////////////////
401 class EXPCL_PANDA_GOBJ GeomPipelineReader : public GeomEnums {
402 public:
403  INLINE GeomPipelineReader(const Geom *object, Thread *current_thread);
404 private:
405  INLINE GeomPipelineReader(const GeomPipelineReader &copy);
406  INLINE void operator = (const GeomPipelineReader &copy);
407 
408 public:
409  INLINE ~GeomPipelineReader();
410  ALLOC_DELETED_CHAIN(GeomPipelineReader);
411 
412  INLINE const Geom *get_object() const;
413  INLINE Thread *get_current_thread() const;
414 
415  void check_usage_hint() const;
416 
417  INLINE PrimitiveType get_primitive_type() const;
418  INLINE ShadeModel get_shade_model() const;
419  INLINE int get_geom_rendering() const;
420  INLINE UsageHint get_usage_hint() const;
421  INLINE CPT(GeomVertexData) get_vertex_data() const;
422  INLINE int get_num_primitives() const;
423  INLINE CPT(GeomPrimitive) get_primitive(int i) const;
424 
425  INLINE UpdateSeq get_modified() const;
426 
427  bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
428 
429  INLINE GeomContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
430  GraphicsStateGuardianBase *gsg) const;
431 
432  bool draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
433  const GeomVertexDataPipelineReader *data_reader,
434  bool force) const;
435 
436 private:
437  CPT(Geom) _object;
438  Thread *_current_thread;
439  const Geom::CData *_cdata;
440 
441 public:
442  static TypeHandle get_class_type() {
443  return _type_handle;
444  }
445  static void init_type() {
446  register_type(_type_handle, "GeomPipelineReader");
447  }
448 
449 private:
450  static TypeHandle _type_handle;
451 };
452 
453 INLINE ostream &operator << (ostream &out, const Geom &obj);
454 
455 #include "geom.I"
456 
457 #endif
This is a special class object that holds all the information returned by a particular GSG to indicat...
Definition: geomContext.h:39
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:57
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
This class exists just to provide scoping for the various enumerated types used by Geom...
Definition: geomEnums.h:27
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
virtual TypeHandle get_parent_type() const
Returns the type of the container that owns the CycleData.
Definition: cycleData.cxx:91
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
This is our own Panda specialization on the default STL list.
Definition: plist.h:38
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Definition: geom.h:401
A table of objects that are saved within the graphics context for reference by handle later...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
A container for geometry primitives.
Definition: geom.h:58
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A thread; that is, a lightweight process.
Definition: thread.h:51
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This object contains a single cache entry in the GeomCacheManager.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:45
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43