Add M_filled_wireframe render mode

This commit is contained in:
rdb 2015-02-06 12:15:25 +01:00
parent eaabc1bfa5
commit 78f8f65ef9
12 changed files with 236 additions and 121 deletions

View File

@ -140,12 +140,6 @@ open_framework(int &argc, char **&argv) {
_task_mgr.add(task); _task_mgr.add(task);
} }
_highlight_wireframe = NodePath("wireframe");
_highlight_wireframe.set_render_mode_wireframe(1);
_highlight_wireframe.set_texture_off(1);
_highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
_highlight_wireframe.set_attrib(DepthOffsetAttrib::make());
if (!playback_session.empty()) { if (!playback_session.empty()) {
// If the config file so indicates, create a recorder and start it // If the config file so indicates, create a recorder and start it
// playing. // playing.
@ -784,13 +778,7 @@ set_highlight(const NodePath &node) {
if (!_highlight.is_empty()) { if (!_highlight.is_empty()) {
framework_cat.info(false) << _highlight << "\n"; framework_cat.info(false) << _highlight << "\n";
_highlight.show_bounds(); _highlight.show_bounds();
_highlight.set_render_mode_filled_wireframe(LColor(1.0f, 0.0f, 0.0f, 1.0f), 200);
// Also create a new instance of the highlighted geometry, as a
// sibling of itself, under the special highlight property.
if (_highlight.has_parent()) {
_highlight_wireframe.reparent_to(_highlight.get_parent());
_highlight.instance_to(_highlight_wireframe);
}
} }
} }
@ -803,11 +791,8 @@ void PandaFramework::
clear_highlight() { clear_highlight() {
if (!_highlight.is_empty()) { if (!_highlight.is_empty()) {
_highlight.hide_bounds(); _highlight.hide_bounds();
_highlight.clear_render_mode();
_highlight = NodePath(); _highlight = NodePath();
// Clean up the special highlight instance.
_highlight_wireframe.detach_node();
_highlight_wireframe.get_children().detach();
} }
} }
@ -1012,7 +997,13 @@ event_w(const Event *event, void *) {
WindowFramework *wf; WindowFramework *wf;
DCAST_INTO_V(wf, param.get_ptr()); DCAST_INTO_V(wf, param.get_ptr());
wf->set_wireframe(!wf->get_wireframe()); if (!wf->get_wireframe()) {
wf->set_wireframe(true, true);
} else if (wf->get_wireframe_filled()) {
wf->set_wireframe(true, false);
} else {
wf->set_wireframe(false, false);
}
} }
} }
@ -1286,13 +1277,6 @@ event_arrow_left(const Event *, void *data) {
int index = parent.node()->find_child(node.node()); int index = parent.node()->find_child(node.node());
nassertv(index >= 0); nassertv(index >= 0);
int sibling = index - 1; int sibling = index - 1;
if (sibling >= 0 &&
parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
// Skip over the special highlight node.
sibling--;
}
if (sibling >= 0) { if (sibling >= 0) {
self->set_highlight(NodePath(parent, parent.node()->get_child(sibling))); self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
} }
@ -1319,13 +1303,6 @@ event_arrow_right(const Event *, void *data) {
nassertv(index >= 0); nassertv(index >= 0);
int num_children = parent.node()->get_num_children(); int num_children = parent.node()->get_num_children();
int sibling = index + 1; int sibling = index + 1;
if (sibling < num_children &&
parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
// Skip over the special highlight node.
sibling++;
}
if (sibling < num_children) { if (sibling < num_children) {
self->set_highlight(NodePath(parent, parent.node()->get_child(sibling))); self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
} }

View File

@ -33,7 +33,7 @@ get_panda_framework() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE GraphicsWindow *WindowFramework:: INLINE GraphicsWindow *WindowFramework::
get_graphics_window() const { get_graphics_window() const {
if (_window != (GraphicsOutput *)NULL && if (_window != (GraphicsOutput *)NULL &&
_window->is_of_type(GraphicsWindow::get_class_type())) { _window->is_of_type(GraphicsWindow::get_class_type())) {
return DCAST(GraphicsWindow, _window); return DCAST(GraphicsWindow, _window);
} }
@ -117,6 +117,17 @@ get_wireframe() const {
return _wireframe_enabled; return _wireframe_enabled;
} }
////////////////////////////////////////////////////////////////////
// Function: WindowFramework::get_wireframe_filled
// Access: Public
// Description: Returns the current state of the wireframe_filled
// flag.
////////////////////////////////////////////////////////////////////
INLINE bool WindowFramework::
get_wireframe_filled() const {
return _wireframe_filled;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: WindowFramework::get_texture // Function: WindowFramework::get_texture
// Access: Public // Access: Public

View File

@ -87,6 +87,7 @@ WindowFramework(PandaFramework *panda_framework) :
_anim_controls_enabled = false; _anim_controls_enabled = false;
_anim_index = 0; _anim_index = 0;
_wireframe_enabled = false; _wireframe_enabled = false;
_wireframe_filled = false;
_texture_enabled = true; _texture_enabled = true;
_two_sided_enabled = false; _two_sided_enabled = false;
_one_sided_reverse_enabled = false; _one_sided_reverse_enabled = false;
@ -362,7 +363,7 @@ get_pixel_2d() {
PGTop *top = new PGTop("pixel_2d"); PGTop *top = new PGTop("pixel_2d");
_pixel_2d = get_render_2d().attach_new_node(top); _pixel_2d = get_render_2d().attach_new_node(top);
_pixel_2d.set_pos(-1, 0, 1); _pixel_2d.set_pos(-1, 0, 1);
if (_window->has_size()) { if (_window->has_size()) {
int x_size = _window->get_sbs_left_x_size(); int x_size = _window->get_sbs_left_x_size();
int y_size = _window->get_sbs_left_y_size(); int y_size = _window->get_sbs_left_y_size();
@ -653,7 +654,7 @@ load_model(const NodePath &parent, Filename filename) {
// A texture object. Not exactly an image, but certainly a // A texture object. Not exactly an image, but certainly a
// texture. // texture.
is_image = true; is_image = true;
} else { } else {
TexturePool *texture_pool = TexturePool::get_global_ptr(); TexturePool *texture_pool = TexturePool::get_global_ptr();
if (texture_pool->get_texture_type(extension) != NULL) { if (texture_pool->get_texture_type(extension) != NULL) {
@ -845,7 +846,7 @@ adjust_dimensions() {
x_size = _window->get_sbs_left_x_size(); x_size = _window->get_sbs_left_x_size();
y_size = _window->get_sbs_left_y_size(); y_size = _window->get_sbs_left_y_size();
} }
if (this_aspect_ratio == 0.0f) { if (this_aspect_ratio == 0.0f) {
// An aspect ratio of 0.0 means to try to infer it. // An aspect ratio of 0.0 means to try to infer it.
this_aspect_ratio = 1.0f; this_aspect_ratio = 1.0f;
@ -942,28 +943,42 @@ split_window(SplitType split_type) {
// rendering (false). // rendering (false).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void WindowFramework:: void WindowFramework::
set_wireframe(bool enable) { set_wireframe(bool enable, bool filled) {
if (enable == _wireframe_enabled) { if (enable == _wireframe_enabled && filled == _wireframe_filled) {
return; return;
} }
NodePath render = get_render(); NodePath render = get_render();
if (!_two_sided_enabled) {
render.clear_two_sided();
}
if (enable) { if (enable) {
render.set_render_mode_wireframe(override_priority); if (filled) {
render.set_two_sided(true, override_priority); render.set_attrib(RenderModeAttrib::make(
RenderModeAttrib::M_filled_wireframe,
1.4f, false, LColor(1, 1, 1, .5f)),
override_priority);
// Darken the scene so that the wireframe is clearly visible,
// even when the scene is completely white.
render.set_color_scale(LColor(0.7f, 0.7f, 0.7f, 1), override_priority);
} else {
render.set_render_mode_wireframe(override_priority);
render.set_two_sided(true, override_priority);
render.clear_color_scale();
}
} else { } else {
render.clear_render_mode(); render.clear_render_mode();
if (!_two_sided_enabled) {
render.clear_two_sided();
}
if (_one_sided_reverse_enabled) { if (_one_sided_reverse_enabled) {
CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse(); CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
render.node()->set_attrib(attrib); render.node()->set_attrib(attrib);
} }
render.clear_color_scale();
} }
_wireframe_enabled = enable; _wireframe_enabled = enable;
_wireframe_filled = filled;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1285,7 +1300,7 @@ load_image_as_model(const Filename &filename) {
} else { } else {
framework_cat.warning() framework_cat.warning()
<< "Texture size is 0 0: " << *tex << "\n"; << "Texture size is 0 0: " << *tex << "\n";
left = -scale; left = -scale;
right = scale; right = scale;
top = scale; top = scale;
@ -1314,9 +1329,9 @@ load_image_as_model(const Filename &filename) {
// Vertices and 3-d texture coordinates. // Vertices and 3-d texture coordinates.
vformat = GeomVertexFormat::register_format vformat = GeomVertexFormat::register_format
(new GeomVertexArrayFormat (new GeomVertexArrayFormat
(InternalName::get_vertex(), 3, (InternalName::get_vertex(), 3,
GeomEnums::NT_stdfloat, GeomEnums::C_point, GeomEnums::NT_stdfloat, GeomEnums::C_point,
InternalName::get_texcoord(), 3, InternalName::get_texcoord(), 3,
GeomEnums::NT_stdfloat, GeomEnums::C_texcoord)); GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
} }
@ -1331,7 +1346,7 @@ load_image_as_model(const Filename &filename) {
vertex.add_data3(LVertex::rfu(left, 0.02, bottom)); vertex.add_data3(LVertex::rfu(left, 0.02, bottom));
vertex.add_data3(LVertex::rfu(right, 0.02, top)); vertex.add_data3(LVertex::rfu(right, 0.02, top));
vertex.add_data3(LVertex::rfu(right, 0.02, bottom)); vertex.add_data3(LVertex::rfu(right, 0.02, bottom));
texcoord.add_data2(0.0f, tex_scale[1]); texcoord.add_data2(0.0f, tex_scale[1]);
texcoord.add_data2(0.0f, 0.0f); texcoord.add_data2(0.0f, 0.0f);
texcoord.add_data2(tex_scale[0], tex_scale[1]); texcoord.add_data2(tex_scale[0], tex_scale[1]);

View File

@ -97,7 +97,7 @@ public:
const pvector<Filename> &files); const pvector<Filename> &files);
NodePath load_model(const NodePath &parent, Filename filename); NodePath load_model(const NodePath &parent, Filename filename);
NodePath load_default_model(const NodePath &parent); NodePath load_default_model(const NodePath &parent);
void loop_animations(int hierarchy_match_flags = void loop_animations(int hierarchy_match_flags =
PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_part_extra |
PartGroup::HMF_ok_anim_extra); PartGroup::HMF_ok_anim_extra);
void stagger_animations(); void stagger_animations();
@ -122,7 +122,7 @@ public:
}; };
WindowFramework *split_window(SplitType split_type = ST_default); WindowFramework *split_window(SplitType split_type = ST_default);
void set_wireframe(bool enable); void set_wireframe(bool enable, bool filled=false);
void set_texture(bool enable); void set_texture(bool enable);
void set_two_sided(bool enable); void set_two_sided(bool enable);
void set_one_sided_reverse(bool enable); void set_one_sided_reverse(bool enable);
@ -131,6 +131,7 @@ public:
void set_background_type(BackgroundType type); void set_background_type(BackgroundType type);
INLINE bool get_wireframe() const; INLINE bool get_wireframe() const;
INLINE bool get_wireframe_filled() const;
INLINE bool get_texture() const; INLINE bool get_texture() const;
INLINE bool get_two_sided() const; INLINE bool get_two_sided() const;
INLINE bool get_one_sided_reverse() const; INLINE bool get_one_sided_reverse() const;
@ -150,7 +151,7 @@ private:
void destroy_anim_controls(); void destroy_anim_controls();
void update_anim_controls(); void update_anim_controls();
void setup_shuttle_button(const string &label, int index, void setup_shuttle_button(const string &label, int index,
EventHandler::EventCallbackFunction *func); EventHandler::EventCallbackFunction *func);
void back_button(); void back_button();
void pause_button(); void pause_button();
@ -194,12 +195,13 @@ private:
NodePath _alight; NodePath _alight;
NodePath _dlight; NodePath _dlight;
bool _got_keyboard; bool _got_keyboard;
bool _got_trackball; bool _got_trackball;
bool _got_lights; bool _got_lights;
bool _wireframe_enabled; bool _wireframe_enabled;
bool _wireframe_filled;
bool _texture_enabled; bool _texture_enabled;
bool _two_sided_enabled; bool _two_sided_enabled;
bool _one_sided_reverse_enabled; bool _one_sided_reverse_enabled;
@ -210,7 +212,7 @@ private:
PT(SceneGraphAnalyzerMeter) _scene_graph_analyzer_meter; PT(SceneGraphAnalyzerMeter) _scene_graph_analyzer_meter;
BackgroundType _background_type; BackgroundType _background_type;
static PT(TextFont) _shuttle_controls_font; static PT(TextFont) _shuttle_controls_font;
public: public:

View File

@ -39,3 +39,35 @@ get_bin(int bin_index) {
} }
return make_new_bin(bin_index); return make_new_bin(bin_index);
} }
////////////////////////////////////////////////////////////////////
// Function: CullResult::check_flash_bin
// Access: Private
// Description: If the user configured flash-bin-binname, then update
// the object's state to flash all the geometry in the
// bin.
////////////////////////////////////////////////////////////////////
INLINE void CullResult::
check_flash_bin(CPT(RenderState) &state, CullBinManager *bin_manager, int bin_index) {
#ifndef NDEBUG
if (bin_manager->get_bin_flash_active(bin_index)) {
apply_flash_color(state, bin_manager->get_bin_flash_color(bin_index));
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::check_flash_transparency
// Access: Private
// Description: If the user configured show-transparency, then
// update the object's state to flash the current
// geometry with the specified color.
////////////////////////////////////////////////////////////////////
INLINE void CullResult::
check_flash_transparency(CPT(RenderState) &state, const LColor &color) {
#ifndef NDEBUG
if (_show_transparency) {
apply_flash_color(state, color);
}
#endif
}

View File

@ -27,27 +27,28 @@
#include "clockObject.h" #include "clockObject.h"
#include "config_pgraph.h" #include "config_pgraph.h"
#include "depthOffsetAttrib.h" #include "depthOffsetAttrib.h"
#include "colorBlendAttrib.h"
TypeHandle CullResult::_type_handle; TypeHandle CullResult::_type_handle;
// This value is used instead of 1.0 to represent the alpha level of a // This value is used instead of 1.0 to represent the alpha level of a
// pixel that is to be considered "opaque" for the purposes of M_dual. // pixel that is to be considered "opaque" for the purposes of M_dual.
//
// Ideally, 1.0 is the only correct value for this. Realistically, we // Ideally, 1.0 is the only correct value for this. Realistically, we
// have to fudge it lower for two reasons: // have to fudge it lower for two reasons:
//
// (1) The modelers tend to paint textures with very slight // (1) The modelers tend to paint textures with very slight
// transparency levels in places that are not intended to be // transparency levels in places that are not intended to be
// transparent, without realizing it. These very faint transparency // transparent, without realizing it. These very faint transparency
// regions are normally (almost) invisible, but when rendered with // regions are normally (almost) invisible, but when rendered with
// M_dual they may be revealed as regions of poor alpha sorting. // M_dual they may be revealed as regions of poor alpha sorting.
//
// (2) There seems to be some problem in DX where, in certain // (2) There seems to be some problem in DX where, in certain
// circumstances apparently related to automatic texture management, // circumstances apparently related to automatic texture management,
// it spontaneously drops out the bottom two bits of an eight-bit // it spontaneously drops out the bottom two bits of an eight-bit
// alpha channel, causing a value of 255 to become a value of 252 // alpha channel, causing a value of 255 to become a value of 252
// instead. // instead.
//
// We use 256 as the denominator here (instead of, say, 255) because a // We use 256 as the denominator here (instead of, say, 255) because a
// fractional power of two will have a terminating representation in // fractional power of two will have a terminating representation in
// base 2, and thus will be more likely to have a precise value in // base 2, and thus will be more likely to have a precise value in
@ -69,6 +70,10 @@ CullResult(GraphicsStateGuardianBase *gsg,
#ifdef DO_MEMORY_USAGE #ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, get_class_type()); MemoryUsage::update_type(this, get_class_type());
#endif #endif
#ifndef NDEBUG
_show_transparency = show_transparency.get_value();
#endif
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -130,17 +135,13 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
// M_alpha implies an alpha-write test, so we don't waste time // M_alpha implies an alpha-write test, so we don't waste time
// writing 0-valued pixels. // writing 0-valued pixels.
object->_state = state->compose(get_alpha_state()); object->_state = state->compose(get_alpha_state());
#ifndef NDEBUG
check_flash_transparency(object->_state, flash_alpha_color); check_flash_transparency(object->_state, flash_alpha_color);
#endif
break; break;
case TransparencyAttrib::M_binary: case TransparencyAttrib::M_binary:
// M_binary is implemented by explicitly setting the alpha test. // M_binary is implemented by explicitly setting the alpha test.
object->_state = state->compose(get_binary_state()); object->_state = state->compose(get_binary_state());
#ifndef NDEBUG
check_flash_transparency(object->_state, flash_binary_color); check_flash_transparency(object->_state, flash_binary_color);
#endif
break; break;
case TransparencyAttrib::M_multisample: case TransparencyAttrib::M_multisample:
@ -150,9 +151,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
if (!_gsg->get_supports_multisample()) { if (!_gsg->get_supports_multisample()) {
object->_state = state->compose(get_binary_state()); object->_state = state->compose(get_binary_state());
} }
#ifndef NDEBUG
check_flash_transparency(object->_state, flash_multisample_color); check_flash_transparency(object->_state, flash_multisample_color);
#endif
break; break;
case TransparencyAttrib::M_dual: case TransparencyAttrib::M_dual:
@ -192,12 +191,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
int transparent_bin_index = transparent_part->_state->get_bin_index(); int transparent_bin_index = transparent_part->_state->get_bin_index();
CullBin *bin = get_bin(transparent_bin_index); CullBin *bin = get_bin(transparent_bin_index);
nassertv(bin != (CullBin *)NULL); nassertv(bin != (CullBin *)NULL);
#ifndef NDEBUG check_flash_bin(transparent_part->_state, bin_manager, transparent_bin_index);
if (bin_manager->get_bin_flash_active(transparent_bin_index)) {
do_flash_bin(transparent_part->_state,
bin_manager->get_bin_flash_color(transparent_bin_index));
}
#endif
bin->add_object(transparent_part, current_thread); bin->add_object(transparent_part, current_thread);
} else { } else {
delete transparent_part; delete transparent_part;
@ -225,16 +219,34 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
} }
} }
// Check for a special wireframe setting.
const RenderModeAttrib *rmode = (const RenderModeAttrib *)
object->_state->get_attrib(RenderModeAttrib::get_class_slot());
if (rmode != (const RenderModeAttrib *)NULL) {
if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) {
CullableObject *wireframe_part = new CullableObject(*object);
wireframe_part->_state = get_wireframe_overlay_state(rmode);
if (wireframe_part->munge_geom
(_gsg, _gsg->get_geom_munger(wireframe_part->_state, current_thread),
traverser, force)) {
int wireframe_bin_index = bin_manager->find_bin("fixed");
CullBin *bin = get_bin(wireframe_bin_index);
nassertv(bin != (CullBin *)NULL);
check_flash_bin(wireframe_part->_state, bin_manager, wireframe_bin_index);
bin->add_object(wireframe_part, current_thread);
} else {
delete wireframe_part;
}
object->_state = object->_state->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled));
}
}
int bin_index = object->_state->get_bin_index(); int bin_index = object->_state->get_bin_index();
CullBin *bin = get_bin(bin_index); CullBin *bin = get_bin(bin_index);
nassertv(bin != (CullBin *)NULL); nassertv(bin != (CullBin *)NULL);
check_flash_bin(object->_state, bin_manager, bin_index);
#ifndef NDEBUG
if (bin_manager->get_bin_flash_active(bin_index)) {
do_flash_bin(object->_state,
bin_manager->get_bin_flash_color(bin_index));
}
#endif
// Munge vertices as needed for the GSG's requirements, and the // Munge vertices as needed for the GSG's requirements, and the
// object's current state. // object's current state.
@ -410,16 +422,15 @@ get_binary_state() {
return state; return state;
} }
#ifndef NDEBUG
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CullResult::do-flash_bin // Function: CullResult::apply_flash_color
// Access: Private // Access: Private
// Description: If the user configured flash-bin-binname, then update // Description: Update the object's state to flash the geometry
// the object's state to flash all the geometry in the // with a solid color.
// bin.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CullResult:: void CullResult::
do_flash_bin(CPT(RenderState) &state, const LColor &flash_color) { apply_flash_color(CPT(RenderState) &state, const LColor &flash_color) {
#ifndef NDEBUG
int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate); int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
if ((cycle & 1) == 0) { if ((cycle & 1) == 0) {
state = state->remove_attrib(TextureAttrib::get_class_slot()); state = state->remove_attrib(TextureAttrib::get_class_slot());
@ -429,32 +440,8 @@ do_flash_bin(CPT(RenderState) &state, const LColor &flash_color) {
state = state->add_attrib(ColorAttrib::make_flat(flash_color), state = state->add_attrib(ColorAttrib::make_flat(flash_color),
RenderState::get_max_priority()); RenderState::get_max_priority());
} }
}
#endif // NDEBUG #endif // NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function: CullResult::check_flash_transparency
// Access: Private
// Description: If the user configured show-transparency, then
// update the object's state to flash the current
// geometry with the specified color.
////////////////////////////////////////////////////////////////////
void CullResult::
check_flash_transparency(CPT(RenderState) &state, const LColor &transparency) {
#ifndef NDEBUG
if (show_transparency) {
int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * bin_color_flash_rate);
if ((cycle & 1) == 0) {
state = state->remove_attrib(TextureAttrib::get_class_slot());
state = state->remove_attrib(LightAttrib::get_class_slot());
state = state->remove_attrib(ColorScaleAttrib::get_class_slot());
state = state->remove_attrib(FogAttrib::get_class_slot());
state = state->add_attrib(ColorAttrib::make_flat(transparency),
RenderState::get_max_priority());
}
}
#endif
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CullResult::get_dual_transparent_state // Function: CullResult::get_dual_transparent_state
@ -535,3 +522,22 @@ get_dual_opaque_state() {
return state; return state;
} }
////////////////////////////////////////////////////////////////////
// Function: CullResult::get_wireframe_overlay_state
// Access: Private
// Description: Returns a RenderState that renders only the
// wireframe part of an M_filled_wireframe model.
////////////////////////////////////////////////////////////////////
CPT(RenderState) CullResult::
get_wireframe_overlay_state(const RenderModeAttrib *rmode) {
return RenderState::make(
DepthOffsetAttrib::make(1, 0, 0.99999f),
ColorAttrib::make_flat(rmode->get_wireframe_color()),
ColorBlendAttrib::make(ColorBlendAttrib::M_add,
ColorBlendAttrib::O_incoming_alpha,
ColorBlendAttrib::O_one_minus_incoming_alpha),
RenderModeAttrib::make(RenderModeAttrib::M_wireframe,
rmode->get_thickness(),
rmode->get_perspective()));
}

View File

@ -17,6 +17,7 @@
#include "pandabase.h" #include "pandabase.h"
#include "cullBin.h" #include "cullBin.h"
#include "cullBinManager.h"
#include "renderState.h" #include "renderState.h"
#include "cullableObject.h" #include "cullableObject.h"
#include "geomMunger.h" #include "geomMunger.h"
@ -26,12 +27,11 @@
#include "pset.h" #include "pset.h"
#include "pmap.h" #include "pmap.h"
class GraphicsStateGuardianBase;
class CullTraverser; class CullTraverser;
class TransformState; class GraphicsStateGuardianBase;
class RenderState; class RenderState;
class SceneSetup; class SceneSetup;
class TransformState;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : CullResult // Class : CullResult
@ -66,13 +66,19 @@ public:
private: private:
CullBin *make_new_bin(int bin_index); CullBin *make_new_bin(int bin_index);
void do_flash_bin(CPT(RenderState) &state, const LColor &flash_color);
void check_flash_transparency(CPT(RenderState) &state, const LColor &color); INLINE void check_flash_bin(CPT(RenderState) &state, CullBinManager *bin_manager, int bin_index);
INLINE void check_flash_transparency(CPT(RenderState) &state, const LColor &color);
#ifndef NDEBUG
void apply_flash_color(CPT(RenderState) &state, const LColor &flash_color);
#endif
static CPT(RenderState) get_alpha_state(); static CPT(RenderState) get_alpha_state();
static CPT(RenderState) get_binary_state(); static CPT(RenderState) get_binary_state();
static CPT(RenderState) get_dual_transparent_state(); static CPT(RenderState) get_dual_transparent_state();
static CPT(RenderState) get_dual_opaque_state(); static CPT(RenderState) get_dual_opaque_state();
static CPT(RenderState) get_wireframe_overlay_state(const RenderModeAttrib *rmode);
GraphicsStateGuardianBase *_gsg; GraphicsStateGuardianBase *_gsg;
PStatCollector _draw_region_pcollector; PStatCollector _draw_region_pcollector;
@ -80,6 +86,10 @@ private:
typedef pvector< PT(CullBin) > Bins; typedef pvector< PT(CullBin) > Bins;
Bins _bins; Bins _bins;
#ifndef NDEBUG
bool _show_transparency;
#endif
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;

View File

@ -5213,6 +5213,22 @@ set_render_mode_filled(int priority) {
node()->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled, thickness, perspective), priority); node()->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled, thickness, perspective), priority);
} }
////////////////////////////////////////////////////////////////////
// Function: NodePath::set_render_mode_filled_wireframe
// Access: Published
// Description: Sets up the geometry at this level and below (unless
// overridden) to render in filled, but overlay the
// wireframe on top with a fixed color. This is useful
// for debug visualizations.
////////////////////////////////////////////////////////////////////
void NodePath::
set_render_mode_filled_wireframe(const LColor &wireframe_color, int priority) {
nassertv_always(!is_empty());
PN_stdfloat thickness = get_render_mode_thickness();
bool perspective = get_render_mode_perspective();
node()->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled_wireframe, thickness, perspective, wireframe_color), priority);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NodePath::set_render_mode_perspective // Function: NodePath::set_render_mode_perspective
// Access: Published // Access: Published

View File

@ -766,6 +766,7 @@ PUBLISHED:
void set_render_mode_wireframe(int priority = 0); void set_render_mode_wireframe(int priority = 0);
void set_render_mode_filled(int priority = 0); void set_render_mode_filled(int priority = 0);
void set_render_mode_filled_wireframe(const LColor &wireframe_color, int priority = 0);
void set_render_mode_thickness(PN_stdfloat thickness, int priority = 0); void set_render_mode_thickness(PN_stdfloat thickness, int priority = 0);
void set_render_mode_perspective(bool perspective, int priority = 0); void set_render_mode_perspective(bool perspective, int priority = 0);
void set_render_mode(RenderModeAttrib::Mode mode, PN_stdfloat thickness, int priority = 0); void set_render_mode(RenderModeAttrib::Mode mode, PN_stdfloat thickness, int priority = 0);

View File

@ -21,10 +21,11 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE RenderModeAttrib:: INLINE RenderModeAttrib::
RenderModeAttrib(RenderModeAttrib::Mode mode, PN_stdfloat thickness, RenderModeAttrib(RenderModeAttrib::Mode mode, PN_stdfloat thickness,
bool perspective) : bool perspective, const LColor &wireframe_color) :
_mode(mode), _mode(mode),
_thickness(thickness), _thickness(thickness),
_perspective(perspective) _perspective(perspective),
_wireframe_color(wireframe_color)
{ {
} }
@ -68,6 +69,18 @@ get_perspective() const {
return _perspective; return _perspective;
} }
////////////////////////////////////////////////////////////////////
// Function: RenderModeAttrib::get_wireframe_color
// Access: Published
// Description: Returns the color that is used in M_filled_wireframe
// mode to distinguish the wireframe from the rest of
// the geometry.
////////////////////////////////////////////////////////////////////
INLINE const LColor &RenderModeAttrib::
get_wireframe_color() const {
return _wireframe_color;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: RenderModeAttrib::get_geom_rendering // Function: RenderModeAttrib::get_geom_rendering
// Access: Published // Access: Published

View File

@ -44,10 +44,15 @@ int RenderModeAttrib::_attrib_slot;
// it is false, the point thickness is actually a width // it is false, the point thickness is actually a width
// in pixels, and points are a uniform screen size // in pixels, and points are a uniform screen size
// regardless of distance from the camera. // regardless of distance from the camera.
//
// In M_filled_wireframe mode, you should also specify
// the wireframe_color, indicating the flat color to
// assign to the overlayed wireframe.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) RenderModeAttrib:: CPT(RenderAttrib) RenderModeAttrib::
make(RenderModeAttrib::Mode mode, PN_stdfloat thickness, bool perspective) { make(RenderModeAttrib::Mode mode, PN_stdfloat thickness,
RenderModeAttrib *attrib = new RenderModeAttrib(mode, thickness, perspective); bool perspective, const LColor &wireframe_color) {
RenderModeAttrib *attrib = new RenderModeAttrib(mode, thickness, perspective, wireframe_color);
return return_new(attrib); return return_new(attrib);
} }
@ -66,7 +71,7 @@ make_default() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: RenderModeAttrib::output // Function: RenderModeAttrib::output
// Access: Public, Virtual // Access: Public, Virtual
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void RenderModeAttrib:: void RenderModeAttrib::
output(ostream &out) const { output(ostream &out) const {
@ -91,6 +96,10 @@ output(ostream &out) const {
case M_filled_flat: case M_filled_flat:
out << "filled_flat"; out << "filled_flat";
break; break;
case M_filled_wireframe:
out << "filled_wireframe(" << get_wireframe_color() << ")";
break;
} }
if (get_thickness() != 1.0f) { if (get_thickness() != 1.0f) {
@ -130,6 +139,9 @@ compare_to_impl(const RenderAttrib *other) const {
if (_perspective != ta->_perspective) { if (_perspective != ta->_perspective) {
return (int)_perspective - (int)ta->_perspective; return (int)_perspective - (int)ta->_perspective;
} }
if (_mode == M_filled_wireframe && _wireframe_color != ta->_wireframe_color) {
return _wireframe_color.compare_to(ta->_wireframe_color);
}
return 0; return 0;
} }
@ -149,6 +161,9 @@ get_hash_impl() const {
hash = int_hash::add_hash(hash, (int)_mode); hash = int_hash::add_hash(hash, (int)_mode);
hash = float_hash().add_hash(hash, _thickness); hash = float_hash().add_hash(hash, _thickness);
hash = int_hash::add_hash(hash, (int)_perspective); hash = int_hash::add_hash(hash, (int)_perspective);
if (_mode == M_filled_wireframe) {
hash = _wireframe_color.add_hash(hash);
}
return hash; return hash;
} }
@ -180,7 +195,8 @@ compose_impl(const RenderAttrib *other) const {
mode = get_mode(); mode = get_mode();
} }
return make(mode, ta->get_thickness(), ta->get_perspective()); return make(mode, ta->get_thickness(), ta->get_perspective(),
ta->get_wireframe_color());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -207,6 +223,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
dg.add_int8(_mode); dg.add_int8(_mode);
dg.add_stdfloat(_thickness); dg.add_stdfloat(_thickness);
dg.add_bool(_perspective); dg.add_bool(_perspective);
if (_mode == M_filled_wireframe) {
_wireframe_color.write_datagram(dg);
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -243,4 +263,8 @@ fillin(DatagramIterator &scan, BamReader *manager) {
_mode = (Mode)scan.get_int8(); _mode = (Mode)scan.get_int8();
_thickness = scan.get_stdfloat(); _thickness = scan.get_stdfloat();
_perspective = scan.get_bool(); _perspective = scan.get_bool();
if (_mode == M_filled_wireframe) {
_wireframe_color.read_datagram(scan);
}
} }

View File

@ -44,20 +44,27 @@ PUBLISHED:
// Filled polygons, without any particular emphasis on perspective // Filled polygons, without any particular emphasis on perspective
// correctness (a particularly useful designation for software // correctness (a particularly useful designation for software
// rendering sprites). // rendering sprites).
M_filled_flat M_filled_flat,
// Filled polygons with wireframe rendered in front.
// The wireframe is given a solid color.
M_filled_wireframe
}; };
private: private:
INLINE RenderModeAttrib(Mode mode, PN_stdfloat thickness, bool perspective); INLINE RenderModeAttrib(Mode mode, PN_stdfloat thickness, bool perspective,
const LColor &wireframe_color = LColor::zero());
PUBLISHED: PUBLISHED:
static CPT(RenderAttrib) make(Mode mode, PN_stdfloat thickness = 1.0f, static CPT(RenderAttrib) make(Mode mode, PN_stdfloat thickness = 1.0f,
bool perspective = false); bool perspective = false,
const LColor &wireframe_color = LColor::zero());
static CPT(RenderAttrib) make_default(); static CPT(RenderAttrib) make_default();
INLINE Mode get_mode() const; INLINE Mode get_mode() const;
INLINE PN_stdfloat get_thickness() const; INLINE PN_stdfloat get_thickness() const;
INLINE bool get_perspective() const; INLINE bool get_perspective() const;
INLINE const LColor &get_wireframe_color() const;
INLINE int get_geom_rendering(int geom_rendering) const; INLINE int get_geom_rendering(int geom_rendering) const;
@ -73,6 +80,7 @@ private:
Mode _mode; Mode _mode;
PN_stdfloat _thickness; PN_stdfloat _thickness;
bool _perspective; bool _perspective;
LColor _wireframe_color;
PUBLISHED: PUBLISHED:
static int get_class_slot() { static int get_class_slot() {
@ -89,7 +97,7 @@ public:
protected: protected:
static TypedWritable *make_from_bam(const FactoryParams &params); static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager); void fillin(DatagramIterator &scan, BamReader *manager);
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
return _type_handle; return _type_handle;