saner treatment of ColorAttrib

This commit is contained in:
David Rose 2009-01-10 01:19:16 +00:00
parent cb2819a5d7
commit e0c65512aa
5 changed files with 65 additions and 88 deletions

View File

@ -40,10 +40,7 @@ ColorAttrib(ColorAttrib::Type type, const Colorf &color) :
// ColorAttrib for all geometry. You can get this // ColorAttrib for all geometry. You can get this
// color via get_color(). // color via get_color().
// //
// T_off - do not issue any color commands at all. // T_off - use the color white.
// This is generally used only in contexts where the
// color is meaningless, e.g. when drawing directly to
// the depth buffer.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE ColorAttrib::Type ColorAttrib:: INLINE ColorAttrib::Type ColorAttrib::
get_color_type() const { get_color_type() const {
@ -53,9 +50,9 @@ get_color_type() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::get_color // Function: ColorAttrib::get_color
// Access: Published // Access: Published
// Description: If the type is T_flat, this returns the color that // Description: If the type is T_flat or T_off, this returns the
// will be applied to geometry. If the type is anything // color that will be applied to geometry. If the type
// else, this is meaningless. // is T_vertex, this is meaningless.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE const Colorf &ColorAttrib:: INLINE const Colorf &ColorAttrib::
get_color() const { get_color() const {

View File

@ -37,7 +37,7 @@ make_vertex() {
if (_vertex != 0) { if (_vertex != 0) {
return _vertex; return _vertex;
} }
ColorAttrib *attrib = new ColorAttrib(T_vertex); ColorAttrib *attrib = new ColorAttrib(T_vertex, Colorf::zero());
_vertex = return_new(attrib); _vertex = return_new(attrib);
return _vertex; return _vertex;
} }
@ -58,15 +58,14 @@ make_flat(const Colorf &color) {
// Function: ColorAttrib::make_off // Function: ColorAttrib::make_off
// Access: Published, Static // Access: Published, Static
// Description: Constructs a new ColorAttrib object that indicates // Description: Constructs a new ColorAttrib object that indicates
// geometry should be rendered without any color // geometry should be rendered in white.
// commands at all.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib:: CPT(RenderAttrib) ColorAttrib::
make_off() { make_off() {
if (_off != 0) { if (_off != 0) {
return _off; return _off;
} }
ColorAttrib *attrib = new ColorAttrib(T_off); ColorAttrib *attrib = new ColorAttrib(T_off, Colorf(1.0f, 1.0f, 1.0f, 1.0f));
_off = return_new(attrib); _off = return_new(attrib);
return _off; return _off;
} }
@ -80,7 +79,7 @@ make_off() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib:: CPT(RenderAttrib) ColorAttrib::
make_default() { make_default() {
return make_flat(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); return make_off();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -143,10 +142,22 @@ compare_to_impl(const RenderAttrib *other) const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ColorAttrib:: void ColorAttrib::
quantize_color() { quantize_color() {
_color[0] = cfloor(_color[0] * 1000.0f + 0.5f) * 0.001f; switch (_type) {
_color[1] = cfloor(_color[1] * 1000.0f + 0.5f) * 0.001f; case T_flat:
_color[2] = cfloor(_color[2] * 1000.0f + 0.5f) * 0.001f; _color[0] = cfloor(_color[0] * 1000.0f + 0.5f) * 0.001f;
_color[3] = cfloor(_color[3] * 1000.0f + 0.5f) * 0.001f; _color[1] = cfloor(_color[1] * 1000.0f + 0.5f) * 0.001f;
_color[2] = cfloor(_color[2] * 1000.0f + 0.5f) * 0.001f;
_color[3] = cfloor(_color[3] * 1000.0f + 0.5f) * 0.001f;
break;
case T_off:
_color.set(1.0f, 1.0f, 1.0f, 1.0f);
break;
case T_vertex:
_color.set(0.0f, 0.0f, 0.0f, 0.0f);
break;
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -184,7 +195,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
TypedWritable *ColorAttrib:: TypedWritable *ColorAttrib::
make_from_bam(const FactoryParams &params) { make_from_bam(const FactoryParams &params) {
ColorAttrib *attrib = new ColorAttrib; ColorAttrib *attrib = new ColorAttrib(T_off, Colorf::zero());
DatagramIterator scan; DatagramIterator scan;
BamReader *manager; BamReader *manager;

View File

@ -34,8 +34,7 @@ PUBLISHED:
}; };
private: private:
INLINE ColorAttrib(Type type = T_vertex, INLINE ColorAttrib(Type type, const Colorf &color);
const Colorf &color = Colorf(0.0f, 0.0f, 0.0f, 1.0f));
PUBLISHED: PUBLISHED:
static CPT(RenderAttrib) make_vertex(); static CPT(RenderAttrib) make_vertex();

View File

@ -134,17 +134,12 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
if ((attrib_types & SceneGraphReducer::TT_color) != 0) { if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
CPT(RenderAttrib) ra = geom_attribs._color; CPT(RenderAttrib) ra = geom_attribs._color;
int override = geom_attribs._color_override; if (ra != (const RenderAttrib *)NULL) {
if (ra == (const RenderAttrib *)NULL) { int override = geom_attribs._color_override;
// If we don't have a color attrib, implicitly apply the entry->_state = entry->_state->add_attrib(ra, override);
// "off" attrib. But use an override of -1, so we don't
// replace a color attrib already on the Geom state.
ra = ColorAttrib::make_off();
override = -1;
} }
entry->_state = entry->_state->add_attrib(ra, override);
ra = entry->_state->get_attrib(ColorAttrib::get_class_slot()); ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
const ColorAttrib *ca = DCAST(ColorAttrib, ra); const ColorAttrib *ca = DCAST(ColorAttrib, ra);
if (ca->get_color_type() != ColorAttrib::T_vertex) { if (ca->get_color_type() != ColorAttrib::T_vertex) {
if (transformer.remove_column(new_geom, InternalName::get_color())) { if (transformer.remove_column(new_geom, InternalName::get_color())) {
@ -160,30 +155,28 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
// Now, if we have an "off" or "flat" color attribute, we // Now, if we have an "off" or "flat" color attribute, we
// simply modify the color attribute, and leave the // simply modify the color attribute, and leave the
// vertices alone. // vertices alone.
const RenderAttrib *ra = entry->_state->get_attrib(ColorAttrib::get_class_slot()); const RenderAttrib *ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
if (ra != (const RenderAttrib *)NULL) { const ColorAttrib *ca = DCAST(ColorAttrib, ra);
const ColorAttrib *ca = DCAST(ColorAttrib, ra); if (ca->get_color_type() == ColorAttrib::T_off) {
if (ca->get_color_type() == ColorAttrib::T_off) { entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex()); // ColorAttrib::T_off means the color scale becomes
// ColorAttrib::T_off means the color scale becomes // the new color.
// the new color. entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
} else if (ca->get_color_type() == ColorAttrib::T_flat) { } else if (ca->get_color_type() == ColorAttrib::T_flat) {
// ColorAttrib::T_flat means the color scale modulates // ColorAttrib::T_flat means the color scale modulates
// the specified color to produce a new color. // the specified color to produce a new color.
const Colorf &c1 = ca->get_color(); const Colorf &c1 = ca->get_color();
const LVecBase4f &c2 = csa->get_scale(); const LVecBase4f &c2 = csa->get_scale();
Colorf color(c1[0] * c2[0], c1[1] * c2[1], Colorf color(c1[0] * c2[0], c1[1] * c2[1],
c1[2] * c2[2], c1[3] * c2[3]); c1[2] * c2[2], c1[3] * c2[3]);
entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color)); entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
} else { } else {
// Otherwise, we have vertex color, and we just scale // Otherwise, we have vertex color, and we just scale
// it normally. // it normally.
if (transformer.transform_colors(new_geom, csa->get_scale())) { if (transformer.transform_colors(new_geom, csa->get_scale())) {
any_changed = true; any_changed = true;
}
} }
} }
} }

View File

@ -819,26 +819,6 @@ remove_column(GeomNode *node, const InternalName *column) {
// RenderStates the same. It does this by // RenderStates the same. It does this by
// canonicalizing the ColorAttribs, and in the future, // canonicalizing the ColorAttribs, and in the future,
// possibly other attribs. // possibly other attribs.
//
// This implementation is not very smart yet. It
// unnecessarily canonicalizes ColorAttribs even if
// this will not yield compatible RenderStates. A
// better algorithm would:
//
// - each geom already starts with an original
// RenderState. In addition to this, calculate for
// each geom a canonical RenderState.
//
// - maintain a table mapping canonical RenderState
// to a list of geoms.
//
// - for each group of geoms with the same
// canonical renderstate, see if they already have
// matching RenderStates.
//
// - If they have differing RenderStates, then
// actually canonicalize the geoms.
//
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool GeomTransformer:: bool GeomTransformer::
make_compatible_state(GeomNode *node) { make_compatible_state(GeomNode *node) {
@ -851,14 +831,15 @@ make_compatible_state(GeomNode *node) {
PT(GeomNode::GeomList) geoms = cdata->modify_geoms(); PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
// For each geom, calculate a canonicalized RenderState, and // For each geom, calculate a canonicalized RenderState, and
// classify all the geoms according to that. // classify all the geoms according to that. By "canonicalize"
// here, we simply mean removing the ColorAttrib.
typedef pmap <CPT(RenderState), pvector<int> > StateTable; typedef pmap <CPT(RenderState), pvector<int> > StateTable;
StateTable state_table; StateTable state_table;
for (int i = 0; i < (int)geoms->size(); i++) { for (int i = 0; i < (int)geoms->size(); i++) {
GeomNode::GeomEntry &entry = (*geoms)[i]; GeomNode::GeomEntry &entry = (*geoms)[i];
CPT(RenderState) canon = entry._state->add_attrib(ColorAttrib::make_vertex(), -1); CPT(RenderState) canon = entry._state->remove_attrib(ColorAttrib::get_class_slot());
state_table[canon].push_back(i); state_table[canon].push_back(i);
} }
@ -871,7 +852,7 @@ make_compatible_state(GeomNode *node) {
// If the geoms in the group already have the same RenderStates, // If the geoms in the group already have the same RenderStates,
// then nothing needs to be done to this group. // then nothing needs to be done to this group.
pvector<int> &indices = (*si).second; const pvector<int> &indices = (*si).second;
bool mismatch = false; bool mismatch = false;
for (int i = 1; i < (int)indices.size(); i++) { for (int i = 1; i < (int)indices.size(); i++) {
if ((*geoms)[indices[i]]._state != (*geoms)[indices[0]]._state) { if ((*geoms)[indices[i]]._state != (*geoms)[indices[0]]._state) {
@ -884,15 +865,13 @@ make_compatible_state(GeomNode *node) {
} }
// The geoms do not have the same RenderState, but they could, // The geoms do not have the same RenderState, but they could,
// since their canonicalized states are the same. Canonicalize them. // since their canonicalized states are the same. Canonicalize
// them, by applying the colors to the vertices.
const RenderState *canon_state = (*si).first; const RenderState *canon_state = (*si).first;
for (int i = 0; i < (int)indices.size(); i++) { for (int i = 0; i < (int)indices.size(); i++) {
GeomNode::GeomEntry &entry = (*geoms)[indices[i]]; GeomNode::GeomEntry &entry = (*geoms)[indices[i]];
const RenderAttrib *ra = entry._state->get_attrib(ColorAttrib::get_class_slot()); const RenderAttrib *ra = entry._state->get_attrib_def(ColorAttrib::get_class_slot());
if (ra == (RenderAttrib *)NULL) {
ra = ColorAttrib::make_off();
}
const ColorAttrib *ca = DCAST(ColorAttrib, ra); const ColorAttrib *ca = DCAST(ColorAttrib, ra);
if (ca->get_color_type() == ColorAttrib::T_vertex) { if (ca->get_color_type() == ColorAttrib::T_vertex) {
// All we need to do is ensure that the geom has a color column. // All we need to do is ensure that the geom has a color column.
@ -900,21 +879,19 @@ make_compatible_state(GeomNode *node) {
PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy(); PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
if (set_color(new_geom, Colorf(1,1,1,1))) { if (set_color(new_geom, Colorf(1,1,1,1))) {
entry._geom = new_geom; entry._geom = new_geom;
any_changed = true;
} }
} }
} else { } else {
Colorf c(1,1,1,1); // A flat color (or "off", which is white). Set the vertices
if (ca->get_color_type() == ColorAttrib::T_flat) { // to the indicated flat color.
c = ca->get_color(); Colorf c = ca->get_color();
}
PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy(); PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
if (set_color(new_geom, c)) { if (set_color(new_geom, c)) {
entry._geom = new_geom; entry._geom = new_geom;
any_changed = true;
} }
} }
entry._state = canon_state; entry._state = canon_state->add_attrib(ColorAttrib::make_vertex());
any_changed = true;
} }
} }