Add convenience methods to turn geometry into patches

This commit is contained in:
rdb 2014-07-13 17:09:14 +00:00
parent ce88a95ddc
commit de54dda8c1
5 changed files with 96 additions and 8 deletions

View File

@ -242,6 +242,19 @@ make_points() const {
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
// Access: Published

View File

@ -788,6 +788,43 @@ make_points_in_place() {
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

View File

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

View File

@ -991,6 +991,41 @@ make_points() const {
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
// Access: Published

View File

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