Use apply_attribs() to doubleside or reverse triangles
This commit is contained in:
parent
3a5e7bf33a
commit
3de6d5ac4f
|
|
@ -41,6 +41,7 @@ AccumulatedAttribs(const AccumulatedAttribs ©) :
|
|||
_tex_matrix(copy._tex_matrix),
|
||||
_texture(copy._texture),
|
||||
_clip_plane(copy._clip_plane),
|
||||
_cull_face(copy._cull_face),
|
||||
_other(copy._other)
|
||||
{
|
||||
}
|
||||
|
|
@ -58,5 +59,6 @@ operator = (const AccumulatedAttribs ©) {
|
|||
_tex_matrix = copy._tex_matrix;
|
||||
_texture = copy._texture;
|
||||
_clip_plane = copy._clip_plane;
|
||||
_cull_face = copy._cull_face;
|
||||
_other = copy._other;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "texMatrixAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "clipPlaneAttrib.h"
|
||||
#include "cullFaceAttrib.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
|
||||
|
|
@ -65,6 +66,13 @@ write(ostream &out, int attrib_types, int indent_level) const {
|
|||
_clip_plane->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
|
||||
if (_cull_face == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no cull face\n";
|
||||
} else {
|
||||
_cull_face->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
_other->write(out, indent_level);
|
||||
}
|
||||
|
|
@ -159,6 +167,20 @@ collect(PandaNode *node, int attrib_types) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(CullFaceAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a cull face attribute; apply it.
|
||||
if (_cull_face == (const RenderAttrib *)NULL) {
|
||||
_cull_face = node_attrib;
|
||||
} else {
|
||||
_cull_face = _cull_face->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(CullFaceAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
// Collect everything else.
|
||||
nassertv(_other != (RenderState *)NULL);
|
||||
|
|
@ -192,6 +214,13 @@ collect(PandaNode *node, int attrib_types) {
|
|||
collect_state = collect_state->remove_attrib(ClipPlaneAttrib::get_class_type());
|
||||
keep_state = keep_state->add_attrib(attrib, override);
|
||||
}
|
||||
|
||||
attrib = collect_state->get_attrib(CullFaceAttrib::get_class_type());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
int override = collect_state->get_override(CullFaceAttrib::get_class_type());
|
||||
collect_state = collect_state->remove_attrib(CullFaceAttrib::get_class_type());
|
||||
keep_state = keep_state->add_attrib(attrib, override);
|
||||
}
|
||||
|
||||
_other = _other->compose(collect_state);
|
||||
node->set_state(keep_state);
|
||||
|
|
@ -278,6 +307,19 @@ collect(const RenderState *state, int attrib_types) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
new_state->get_attrib(CullFaceAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
if (_cull_face == (const RenderAttrib *)NULL) {
|
||||
_cull_face = node_attrib;
|
||||
} else {
|
||||
_cull_face = _cull_face->compose(node_attrib);
|
||||
}
|
||||
new_state = new_state->remove_attrib(CullFaceAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
// Collect everything else.
|
||||
nassertr(_other != (RenderState *)NULL, new_state);
|
||||
|
|
@ -357,6 +399,19 @@ apply_to_node(PandaNode *node, int attrib_types) {
|
|||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
|
||||
if (_cull_face != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(CullFaceAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_cull_face->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_cull_face);
|
||||
}
|
||||
_cull_face = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
node->set_state(_other->compose(node->get_state()));
|
||||
_other = RenderState::make_empty();
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public:
|
|||
CPT(RenderAttrib) _tex_matrix;
|
||||
CPT(RenderAttrib) _texture;
|
||||
CPT(RenderAttrib) _clip_plane;
|
||||
CPT(RenderAttrib) _cull_face;
|
||||
CPT(RenderState) _other;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,27 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
|||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
|
||||
if (attribs._cull_face != (const RenderAttrib *)NULL) {
|
||||
const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, attribs._cull_face);
|
||||
CullFaceAttrib::Mode mode = cfa->get_effective_mode();
|
||||
switch (mode) {
|
||||
case CullFaceAttrib::M_cull_none:
|
||||
// Doublesided polys. Duplicate them.
|
||||
transformer.doubleside(this);
|
||||
break;
|
||||
|
||||
case CullFaceAttrib::M_cull_counter_clockwise:
|
||||
// Reverse winding order.
|
||||
transformer.reverse(this);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
|
|
|
|||
|
|
@ -499,6 +499,81 @@ reverse_normals(Geom *geom) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomTransformer::doubleside
|
||||
// Access: Public
|
||||
// Description: Duplicates triangles in this GeomNode so that each
|
||||
// triangle is back-to-back with another triangle facing
|
||||
// in the opposite direction. If the geometry has
|
||||
// vertex normals, this will also duplicate and reverse
|
||||
// the normals, so that lighting will work correctly
|
||||
// from both sides. Note that calling this when the
|
||||
// geometry is already doublesided (with back-to-back
|
||||
// polygons) will result in multiple redundant coplanar
|
||||
// polygons.
|
||||
//
|
||||
// Also see CullFaceAttrib, which can enable rendering
|
||||
// of both sides of a triangle without having to
|
||||
// duplicate it (but which doesn't necessarily work in
|
||||
// the presence of lighting).
|
||||
//
|
||||
// Returns true if any Geoms are modified, false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GeomTransformer::
|
||||
doubleside(GeomNode *node) {
|
||||
int num_geoms = node->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; ++i) {
|
||||
CPT(Geom) orig_geom = node->get_geom(i);
|
||||
bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
|
||||
if (has_normals) {
|
||||
// If the geometry has normals, we have to duplicate it to
|
||||
// reverse the normals on the duplicate copy.
|
||||
PT(Geom) new_geom = orig_geom->reverse();
|
||||
reverse_normals(new_geom);
|
||||
node->add_geom(new_geom, node->get_geom_state(i));
|
||||
|
||||
} else {
|
||||
// If there are no normals, we can just doubleside it in
|
||||
// place. This is preferable because we can share vertices.
|
||||
orig_geom.clear();
|
||||
node->modify_geom(i)->doubleside_in_place();
|
||||
}
|
||||
}
|
||||
|
||||
return (num_geoms != 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomTransformer::reverse
|
||||
// Access: Public
|
||||
// Description: Reverses the winding order of triangles in this
|
||||
// GeomNode so that each triangle is facing in the
|
||||
// opposite direction. If the geometry has vertex
|
||||
// normals, this will also reverse the normals, so that
|
||||
// lighting will work correctly.
|
||||
//
|
||||
// Also see CullFaceAttrib, which can effectively change
|
||||
// the facing of a triangle having to modify its
|
||||
// vertices (but which doesn't necessarily work in the
|
||||
// presence of lighting).
|
||||
//
|
||||
// Returns true if any Geoms are modified, false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GeomTransformer::
|
||||
reverse(GeomNode *node) {
|
||||
int num_geoms = node->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; ++i) {
|
||||
PT(Geom) geom = node->modify_geom(i);
|
||||
geom->reverse_in_place();
|
||||
reverse_normals(geom);
|
||||
}
|
||||
|
||||
return (num_geoms != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomTransformer::collect_vertex_data
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ public:
|
|||
bool remove_column(GeomNode *node, const InternalName *column);
|
||||
|
||||
bool reverse_normals(Geom *geom);
|
||||
bool doubleside(GeomNode *node);
|
||||
bool reverse(GeomNode *node);
|
||||
|
||||
int collect_vertex_data(Geom *geom, int collect_bits);
|
||||
int collect_vertex_data(GeomNode *node, int collect_bits);
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
PStatCollector SceneGraphReducer::_flatten_collector("*:Flatten:flatten");
|
||||
PStatCollector SceneGraphReducer::_apply_collector("*:Flatten:apply");
|
||||
PStatCollector SceneGraphReducer::_remove_column_collector("*:Flatten:remove column");
|
||||
PStatCollector SceneGraphReducer::_doubleside_collector("*:Flatten:doubleside");
|
||||
PStatCollector SceneGraphReducer::_reverse_collector("*:Flatten:reverse");
|
||||
PStatCollector SceneGraphReducer::_collect_collector("*:Flatten:collect");
|
||||
PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make nonindexed");
|
||||
PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify");
|
||||
|
|
@ -145,52 +143,6 @@ remove_column(PandaNode *root, const InternalName *column) {
|
|||
return r_remove_column(root, column, _transformer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::doubleside
|
||||
// Access: Published
|
||||
// Description: Duplicates triangles in the GeomNodes at this level
|
||||
// and below so that each triangle is back-to-back with
|
||||
// another triangle facing in the opposite direction.
|
||||
// If the geometry has vertex normals, this will also
|
||||
// duplicate and reverse the normals, so that lighting
|
||||
// will work correctly from both sides. Note that
|
||||
// calling this when the geometry is already doublesided
|
||||
// (with back-to-back polygons) will result in multiple
|
||||
// redundant coplanar polygons.
|
||||
//
|
||||
// Also see CullFaceAttrib, which can enable rendering
|
||||
// of both sides of a triangle without having to
|
||||
// duplicate it (but which doesn't necessarily work in
|
||||
// the presence of lighting).
|
||||
//
|
||||
// Returns the number of GeomNodes modified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SceneGraphReducer::
|
||||
doubleside(PandaNode *root) {
|
||||
PStatTimer timer(_doubleside_collector);
|
||||
return r_doubleside(root, _transformer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::reverse
|
||||
// Access: Published
|
||||
// Description: Reverses the winding order in the GeomNodes at this
|
||||
// level and below so that each triangle is facing in
|
||||
// the opposite direction it was originally. If the
|
||||
// geometry has vertex normals, the normals will be
|
||||
// reversed as well.
|
||||
//
|
||||
// Also see CullFaceAttrib, which can change the visible
|
||||
// direction of a triangle without having to duplicate
|
||||
// it (but which doesn't necessarily work in the
|
||||
// presence of lighting).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SceneGraphReducer::
|
||||
reverse(PandaNode *root) {
|
||||
PStatTimer timer(_reverse_collector);
|
||||
return r_reverse(root, _transformer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::unify
|
||||
// Access: Published
|
||||
|
|
@ -763,84 +715,6 @@ r_remove_column(PandaNode *node, const InternalName *column,
|
|||
return num_changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::r_doubleside
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of doubleside().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SceneGraphReducer::
|
||||
r_doubleside(PandaNode *node, GeomTransformer &transformer) {
|
||||
int num_changed = 0;
|
||||
|
||||
if (node->is_geom_node()) {
|
||||
PT(GeomNode) gnode = DCAST(GeomNode, node);
|
||||
int num_geoms = gnode->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; ++i) {
|
||||
CPT(Geom) orig_geom = gnode->get_geom(i);
|
||||
bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
|
||||
if (has_normals) {
|
||||
// If the geometry has normals, we have to duplicate it to
|
||||
// reverse the normals on the duplicate copy.
|
||||
PT(Geom) new_geom = orig_geom->reverse();
|
||||
transformer.reverse_normals(new_geom);
|
||||
gnode->add_geom(new_geom, gnode->get_geom_state(i));
|
||||
|
||||
} else {
|
||||
// If there are no normals, we can just doubleside it in
|
||||
// place. This is preferable because we can share vertices.
|
||||
orig_geom.clear();
|
||||
gnode->modify_geom(i)->doubleside_in_place();
|
||||
}
|
||||
}
|
||||
|
||||
if (num_geoms != 0) {
|
||||
++num_changed;
|
||||
}
|
||||
}
|
||||
|
||||
PandaNode::Children children = node->get_children();
|
||||
int num_children = children.get_num_children();
|
||||
for (int i = 0; i < num_children; ++i) {
|
||||
num_changed +=
|
||||
r_doubleside(children.get_child(i), transformer);
|
||||
}
|
||||
|
||||
return num_changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::r_reverse
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of reverse().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SceneGraphReducer::
|
||||
r_reverse(PandaNode *node, GeomTransformer &transformer) {
|
||||
int num_changed = 0;
|
||||
|
||||
if (node->is_geom_node()) {
|
||||
PT(GeomNode) gnode = DCAST(GeomNode, node);
|
||||
int num_geoms = gnode->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; ++i) {
|
||||
PT(Geom) geom = gnode->modify_geom(i);
|
||||
geom->reverse_in_place();
|
||||
transformer.reverse_normals(geom);
|
||||
}
|
||||
|
||||
if (num_geoms != 0) {
|
||||
++num_changed;
|
||||
}
|
||||
}
|
||||
|
||||
PandaNode::Children children = node->get_children();
|
||||
int num_children = children.get_num_children();
|
||||
for (int i = 0; i < num_children; ++i) {
|
||||
num_changed +=
|
||||
r_reverse(children.get_child(i), transformer);
|
||||
}
|
||||
|
||||
return num_changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::r_collect_vertex_data
|
||||
// Access: Private
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ PUBLISHED:
|
|||
TT_color_scale = 0x004,
|
||||
TT_tex_matrix = 0x008,
|
||||
TT_clip_plane = 0x010,
|
||||
TT_other = 0x020,
|
||||
TT_cull_face = 0x020,
|
||||
TT_other = 0x040,
|
||||
};
|
||||
|
||||
enum CombineSiblings {
|
||||
|
|
@ -129,15 +130,13 @@ PUBLISHED:
|
|||
INLINE void set_combine_radius(float combine_radius);
|
||||
INLINE float get_combine_radius() const;
|
||||
|
||||
INLINE void apply_attribs(PandaNode *node, int attrib_types = ~TT_clip_plane);
|
||||
INLINE void apply_attribs(PandaNode *node, int attrib_types = ~(TT_clip_plane | TT_cull_face));
|
||||
INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer);
|
||||
|
||||
int flatten(PandaNode *root, int combine_siblings_bits);
|
||||
|
||||
int remove_column(PandaNode *root, const InternalName *column);
|
||||
int doubleside(PandaNode *root);
|
||||
int reverse(PandaNode *root);
|
||||
|
||||
INLINE int collect_vertex_data(PandaNode *root, int collect_bits = ~0);
|
||||
INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0);
|
||||
|
|
@ -172,8 +171,6 @@ protected:
|
|||
|
||||
int r_remove_column(PandaNode *node, const InternalName *column,
|
||||
GeomTransformer &transformer);
|
||||
int r_doubleside(PandaNode *node, GeomTransformer &transformer);
|
||||
int r_reverse(PandaNode *node, GeomTransformer &transformer);
|
||||
|
||||
int r_collect_vertex_data(PandaNode *node, int collect_bits,
|
||||
GeomTransformer &transformer);
|
||||
|
|
@ -190,8 +187,6 @@ private:
|
|||
static PStatCollector _flatten_collector;
|
||||
static PStatCollector _apply_collector;
|
||||
static PStatCollector _remove_column_collector;
|
||||
static PStatCollector _doubleside_collector;
|
||||
static PStatCollector _reverse_collector;
|
||||
static PStatCollector _collect_collector;
|
||||
static PStatCollector _make_nonindexed_collector;
|
||||
static PStatCollector _unify_collector;
|
||||
|
|
|
|||
Loading…
Reference in New Issue