From 87451d80009c48e104c2371523784d8f644902e2 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 3 Apr 2015 14:15:23 +0200 Subject: [PATCH] Support wireframe and point rendering modes in OpenGL ES --- panda/src/display/standardMunger.I | 13 ++++++ panda/src/display/standardMunger.h | 2 + panda/src/glstuff/glGeomMunger_src.cxx | 44 +++++++++++++++++++ panda/src/glstuff/glGeomMunger_src.h | 6 +++ panda/src/gobj/geom.I | 13 ++++++ panda/src/gobj/geom.cxx | 38 ++++++++++++++++ panda/src/gobj/geom.h | 2 + panda/src/gobj/geomPrimitive.cxx | 60 ++++++++++++++++++++++++++ panda/src/gobj/geomPrimitive.h | 1 + 9 files changed, 179 insertions(+) diff --git a/panda/src/display/standardMunger.I b/panda/src/display/standardMunger.I index 563385856a..17a973cb4c 100644 --- a/panda/src/display/standardMunger.I +++ b/panda/src/display/standardMunger.I @@ -23,3 +23,16 @@ INLINE GraphicsStateGuardian *StandardMunger:: get_gsg() const { return (GraphicsStateGuardian *)GeomMunger::get_gsg(); } + +//////////////////////////////////////////////////////////////////// +// Function: StandardMunger::get_render_mode +// Access: Protected +// Description: Returns the render mode active on this munger. +// Intended for derived classes that may have to munge +// differently depending on render mode. +//////////////////////////////////////////////////////////////////// +INLINE RenderModeAttrib::Mode StandardMunger:: +get_render_mode() const { + return (_render_mode != NULL) ? _render_mode->get_mode() + : RenderModeAttrib::M_filled; +} diff --git a/panda/src/display/standardMunger.h b/panda/src/display/standardMunger.h index 1e2b8ef024..872d2d8403 100644 --- a/panda/src/display/standardMunger.h +++ b/panda/src/display/standardMunger.h @@ -49,6 +49,8 @@ protected: virtual int geom_compare_to_impl(const GeomMunger *other) const; virtual CPT(RenderState) munge_state_impl(const RenderState *state); + INLINE RenderModeAttrib::Mode get_render_mode() const; + private: int _num_components; NumericType _numeric_type; diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index b4da760703..b2deb6e29f 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -362,6 +362,45 @@ premunge_format_impl(const GeomVertexFormat *orig) { return format; } +#ifdef OPENGLES +//////////////////////////////////////////////////////////////////// +// Function: CLP(GeomMunger)::munge_geom_impl +// Access: Protected, Virtual +// Description: Converts a Geom and/or its data as necessary. +//////////////////////////////////////////////////////////////////// +void CLP(GeomMunger):: +munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data, + Thread *current_thread) { + StandardMunger::munge_geom_impl(geom, vertex_data, current_thread); + + // OpenGL ES has no polygon mode, so we have to emulate it. + RenderModeAttrib::Mode render_mode = get_render_mode(); + if (render_mode == RenderModeAttrib::M_point) { + geom = geom->make_points(); + } else if (render_mode == RenderModeAttrib::M_wireframe) { + geom = geom->make_lines(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(GeomMunger)::premunge_geom_impl +// Access: Protected, Virtual +// Description: Converts a Geom and/or its data as necessary. +//////////////////////////////////////////////////////////////////// +void CLP(GeomMunger):: +premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) { + StandardMunger::premunge_geom_impl(geom, vertex_data); + + // OpenGL ES has no polygon mode, so we have to emulate it. + RenderModeAttrib::Mode render_mode = get_render_mode(); + if (render_mode == RenderModeAttrib::M_point) { + geom = geom->make_points(); + } else if (render_mode == RenderModeAttrib::M_wireframe) { + geom = geom->make_lines(); + } +} +#endif // OPENGLES + //////////////////////////////////////////////////////////////////// // Function: CLP(GeomMunger)::compare_to_impl // Access: Protected, Virtual @@ -397,6 +436,11 @@ compare_to_impl(const GeomMunger *other) const { int CLP(GeomMunger):: geom_compare_to_impl(const GeomMunger *other) const { const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other); +#ifdef OPENGLES + if (get_render_mode() != om->get_render_mode()) { + return get_render_mode() < om->get_render_mode() ? -1 : 1; + } +#endif if (_texture != om->_texture) { return _texture < om->_texture ? -1 : 1; } diff --git a/panda/src/glstuff/glGeomMunger_src.h b/panda/src/glstuff/glGeomMunger_src.h index ac3275e859..0c2eaabc8b 100644 --- a/panda/src/glstuff/glGeomMunger_src.h +++ b/panda/src/glstuff/glGeomMunger_src.h @@ -42,6 +42,12 @@ protected: const GeomVertexAnimationSpec &animation); virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig); +#ifdef OPENGLES + virtual void munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data, + Thread *current_thread); + virtual void premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data); +#endif + virtual int compare_to_impl(const GeomMunger *other) const; virtual int geom_compare_to_impl(const GeomMunger *other) const; diff --git a/panda/src/gobj/geom.I b/panda/src/gobj/geom.I index 45d911d2ce..823e9798a4 100644 --- a/panda/src/gobj/geom.I +++ b/panda/src/gobj/geom.I @@ -242,6 +242,19 @@ make_points() const { return new_geom; } +//////////////////////////////////////////////////////////////////// +// Function: Geom::make_lines +// Access: Published +// Description: Returns a new Geom with lines at all the edges. +// See GeomPrimitive::make_lines(). +//////////////////////////////////////////////////////////////////// +INLINE PT(Geom) Geom:: +make_lines() const { + PT(Geom) new_geom = make_copy(); + new_geom->make_lines_in_place(); + return new_geom; +} + //////////////////////////////////////////////////////////////////// // Function: Geom::make_patches // Access: Published diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 92ef2e063f..fe82255c6e 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -750,6 +750,44 @@ unify_in_place(int max_indices, bool preserve_order) { reset_geom_rendering(cdata); } +//////////////////////////////////////////////////////////////////// +// Function: Geom::make_lines_in_place +// Access: Published +// Description: Replaces the GeomPrimitives within this Geom with +// corresponding GeomLines, representing a wireframe +// of the primitives. See GeomPrimitive::make_lines(). +// +// 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_lines_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_lines(); + (*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::make_points_in_place // Access: Published diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index aa890a404f..35337bbfcc 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -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_lines() const; INLINE PT(Geom) make_patches() const; void decompose_in_place(); @@ -110,6 +111,7 @@ PUBLISHED: void rotate_in_place(); void unify_in_place(int max_indices, bool preserve_order); void make_points_in_place(); + void make_lines_in_place(); void make_patches_in_place(); virtual bool copy_primitives_from(const Geom *other); diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index ede9dc71a6..83ae80b266 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -1044,6 +1044,66 @@ make_points() const { return points; } +//////////////////////////////////////////////////////////////////// +// Function: GeomPrimitive::make_lines +// Access: Published +// Description: Returns a new GeomLines primitive that represents +// each of the edges in the original primitive rendered +// as a line. If the original primitive is already a +// GeomLines primitive, returns the original primitive +// unchanged. +//////////////////////////////////////////////////////////////////// +CPT(GeomPrimitive) GeomPrimitive:: +make_lines() const { + if (is_exact_type(GeomLines::get_class_type())) { + return this; + } + + PrimitiveType prim_type = get_primitive_type(); + if (prim_type == PT_lines) { + // It's a line strip, just decompose it. + return decompose(); + + } else if (prim_type != PT_polygons && prim_type != PT_patches) { + // Don't know how to represent this in wireframe. + return this; + } + + if (prim_type == PT_polygons && !is_exact_type(GeomTriangles::get_class_type())) { + // Decompose tristrips. We could probably make this more efficient + // by making a specific implementation of make_lines for GeomTristrips. + return decompose()->make_lines(); + } + + // Iterate through the primitives. + int num_primitives = get_num_primitives(); + int verts_per_prim = get_num_vertices_per_primitive(); + + PT(GeomVertexArrayData) new_vertices = make_index_data(); + new_vertices->unclean_set_num_rows(num_primitives * verts_per_prim * 2); + + GeomVertexWriter new_index(new_vertices, 0); + + for (int i = 0; i < num_primitives; ++i) { + int begin = get_primitive_start(i); + int end = get_primitive_end(i); + if (begin == end) { + continue; + } + for (int vi = begin; vi < end - 1; vi++) { + new_index.set_data1i(get_vertex(vi)); + new_index.set_data1i(get_vertex(vi + 1)); + } + new_index.set_data1i(get_vertex(end - 1)); + new_index.set_data1i(get_vertex(begin)); + } + + PT(GeomPrimitive) lines = new GeomLines(UH_dynamic); + lines->set_vertices(new_vertices); + + return lines; +} + //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::make_patches // Access: Published diff --git a/panda/src/gobj/geomPrimitive.h b/panda/src/gobj/geomPrimitive.h index 1926625f5a..da787edad7 100644 --- a/panda/src/gobj/geomPrimitive.h +++ b/panda/src/gobj/geomPrimitive.h @@ -134,6 +134,7 @@ PUBLISHED: CPT(GeomPrimitive) reverse() const; CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const; CPT(GeomPrimitive) make_points() const; + CPT(GeomPrimitive) make_lines() const; CPT(GeomPrimitive) make_patches() const; int get_num_bytes() const;