Browse Source

Add convenience methods to turn geometry into patches

rdb 11 years ago
parent
commit
de54dda8c1

+ 13 - 0
panda/src/gobj/geom.I

@@ -242,6 +242,19 @@ make_points() const {
   return new_geom;
   return new_geom;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_patches
+//       Access: Published
+//  Description: Returns a new Geom with each primitive converted
+//               into a patch.  Calls decompose() first.
+////////////////////////////////////////////////////////////////////
+INLINE PT(Geom) Geom::
+make_patches() const {
+  PT(Geom) new_geom = make_copy();
+  new_geom->make_patches_in_place();
+  return new_geom;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::get_modified
 //     Function: Geom::get_modified
 //       Access: Published
 //       Access: Published

+ 37 - 0
panda/src/gobj/geom.cxx

@@ -788,6 +788,43 @@ make_points_in_place() {
   nassertv(all_is_valid);
   nassertv(all_is_valid);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_patches_in_place
+//       Access: Published
+//  Description: Replaces the GeomPrimitives within this Geom with
+//               corresponding GeomPatches.  See
+//               GeomPrimitive::make_patches().
+//
+//               Don't call this in a downstream thread unless you
+//               don't mind it blowing away other changes you might
+//               have recently made in an upstream thread.
+////////////////////////////////////////////////////////////////////
+void Geom::
+make_patches_in_place() {
+  Thread *current_thread = Thread::get_current_thread();
+  CDWriter cdata(_cycler, true, current_thread);
+
+#ifndef NDEBUG
+  bool all_is_valid = true;
+#endif
+  Primitives::iterator pi;
+  for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
+    CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_patches();
+    (*pi) = (GeomPrimitive *)new_prim.p();
+
+#ifndef NDEBUG
+    if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
+      all_is_valid = false;
+    }
+#endif
+  }
+
+  cdata->_modified = Geom::get_next_modified();
+  reset_geom_rendering(cdata);
+  clear_cache_stage(current_thread);
+
+  nassertv(all_is_valid);
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::copy_primitives_from
 //     Function: Geom::copy_primitives_from

+ 2 - 0
panda/src/gobj/geom.h

@@ -102,6 +102,7 @@ PUBLISHED:
   INLINE PT(Geom) rotate() const;
   INLINE PT(Geom) rotate() const;
   INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
   INLINE PT(Geom) unify(int max_indices, bool preserve_order) const;
   INLINE PT(Geom) make_points() const;
   INLINE PT(Geom) make_points() const;
+  INLINE PT(Geom) make_patches() const;
 
 
   void decompose_in_place();
   void decompose_in_place();
   void doubleside_in_place();
   void doubleside_in_place();
@@ -109,6 +110,7 @@ PUBLISHED:
   void rotate_in_place();
   void rotate_in_place();
   void unify_in_place(int max_indices, bool preserve_order);
   void unify_in_place(int max_indices, bool preserve_order);
   void make_points_in_place();
   void make_points_in_place();
+  void make_patches_in_place();
 
 
   virtual bool copy_primitives_from(const Geom *other);
   virtual bool copy_primitives_from(const Geom *other);
 
 

+ 35 - 0
panda/src/gobj/geomPrimitive.cxx

@@ -991,6 +991,41 @@ make_points() const {
   return points;
   return points;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitive::make_patches
+//       Access: Published
+//  Description: Decomposes a complex primitive type into a simpler
+//               primitive type, for instance triangle strips to
+//               triangles, puts these in a new GeomPatches objectand returns a pointer to the new primitive
+//               definition.  If the decomposition cannot be
+//               performed, this might return the original object.
+//
+//               This method is useful for application code that wants
+//               to iterate through the set of triangles on the
+//               primitive without having to write handlers for each
+//               possible kind of primitive type.
+////////////////////////////////////////////////////////////////////
+CPT(GeomPrimitive) GeomPrimitive::
+make_patches() const {
+  if (is_exact_type(GeomPatches::get_class_type())) {
+    return this;
+  }
+
+  CPT(GeomPrimitive) prim = decompose_impl();
+  int num_vertices_per_patch = prim->get_num_vertices_per_primitive();
+
+  PT(GeomPrimitive) patches = new GeomPatches(num_vertices_per_patch, get_usage_hint());
+
+  if (prim->is_indexed()) {
+    patches->set_vertices(prim->get_vertices());
+  } else {
+    patches->set_nonindexed_vertices(prim->get_first_vertex(),
+                                     prim->get_num_vertices());
+  }
+
+  return patches;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitive::get_num_bytes
 //     Function: GeomPrimitive::get_num_bytes
 //       Access: Published
 //       Access: Published

+ 9 - 8
panda/src/gobj/geomPrimitive.h

@@ -133,6 +133,7 @@ PUBLISHED:
   CPT(GeomPrimitive) reverse() const;
   CPT(GeomPrimitive) reverse() const;
   CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const;
   CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const;
   CPT(GeomPrimitive) make_points() const;
   CPT(GeomPrimitive) make_points() const;
+  CPT(GeomPrimitive) make_patches() const;
 
 
   int get_num_bytes() const;
   int get_num_bytes() const;
   INLINE int get_data_size_bytes() const;
   INLINE int get_data_size_bytes() const;
@@ -232,14 +233,14 @@ private:
   // itself from the other's list.
   // itself from the other's list.
   typedef pmap<PreparedGraphicsObjects *, IndexBufferContext *> Contexts;
   typedef pmap<PreparedGraphicsObjects *, IndexBufferContext *> Contexts;
   Contexts _contexts;
   Contexts _contexts;
-    
+
   // This is the data that must be cycled between pipeline stages.
   // This is the data that must be cycled between pipeline stages.
   class EXPCL_PANDA_GOBJ CData : public CycleData {
   class EXPCL_PANDA_GOBJ CData : public CycleData {
   public:
   public:
     INLINE CData();
     INLINE CData();
     INLINE CData(const CData &copy);
     INLINE CData(const CData &copy);
     ALLOC_DELETED_CHAIN(CData);
     ALLOC_DELETED_CHAIN(CData);
-    
+
     virtual CycleData *make_copy() const;
     virtual CycleData *make_copy() const;
     virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
     virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
     virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
     virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
@@ -247,7 +248,7 @@ private:
     virtual TypeHandle get_parent_type() const {
     virtual TypeHandle get_parent_type() const {
       return GeomPrimitive::get_class_type();
       return GeomPrimitive::get_class_type();
     }
     }
-    
+
     ShadeModel _shade_model;
     ShadeModel _shade_model;
     int _first_vertex;
     int _first_vertex;
     int _num_vertices;
     int _num_vertices;
@@ -258,11 +259,11 @@ private:
     COWPT(GeomVertexArrayData) _mins;
     COWPT(GeomVertexArrayData) _mins;
     COWPT(GeomVertexArrayData) _maxs;
     COWPT(GeomVertexArrayData) _maxs;
     UpdateSeq _modified;
     UpdateSeq _modified;
-    
+
     bool _got_minmax;
     bool _got_minmax;
     unsigned int _min_vertex;
     unsigned int _min_vertex;
     unsigned int _max_vertex;
     unsigned int _max_vertex;
-    
+
   public:
   public:
     static TypeHandle get_class_type() {
     static TypeHandle get_class_type() {
       return _type_handle;
       return _type_handle;
@@ -270,7 +271,7 @@ private:
     static void init_type() {
     static void init_type() {
       register_type(_type_handle, "GeomPrimitive::CData");
       register_type(_type_handle, "GeomPrimitive::CData");
     }
     }
-    
+
   private:
   private:
     static TypeHandle _type_handle;
     static TypeHandle _type_handle;
 
 
@@ -282,7 +283,7 @@ private:
   typedef CycleDataWriter<CData> CDWriter;
   typedef CycleDataWriter<CData> CDWriter;
   typedef CycleDataStageReader<CData> CDStageReader;
   typedef CycleDataStageReader<CData> CDStageReader;
   typedef CycleDataStageWriter<CData> CDStageWriter;
   typedef CycleDataStageWriter<CData> CDStageWriter;
-  
+
 private:
 private:
   static PStatCollector _decompose_pcollector;
   static PStatCollector _decompose_pcollector;
   static PStatCollector _doubleside_pcollector;
   static PStatCollector _doubleside_pcollector;
@@ -360,7 +361,7 @@ public:
   INLINE CPTA_int get_ends() const;
   INLINE CPTA_int get_ends() const;
   INLINE CPT(GeomVertexArrayData) get_mins() const;
   INLINE CPT(GeomVertexArrayData) get_mins() const;
   INLINE CPT(GeomVertexArrayData) get_maxs() const;
   INLINE CPT(GeomVertexArrayData) get_maxs() const;
-  
+
 private:
 private:
   CPT(GeomPrimitive) _object;
   CPT(GeomPrimitive) _object;
   Thread *_current_thread;
   Thread *_current_thread;