apply_texture_colors()

This commit is contained in:
David Rose 2008-08-28 00:46:30 +00:00
parent 5050c994e0
commit 11ae34e109
13 changed files with 461 additions and 24 deletions

View File

@ -325,8 +325,9 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
CDReader cdata(_cycler, current_thread);
do_calc_tight_bounds(min_point, max_point, found_any,
vertex_data, got_mat, mat, cdata,
current_thread);
vertex_data, got_mat, mat,
InternalName::get_vertex(),
cdata, current_thread);
}
////////////////////////////////////////////////////////////////////
@ -351,6 +352,26 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
current_thread);
}
////////////////////////////////////////////////////////////////////
// Function: Geom::calc_tight_bounds
// Access: Public
// Description: Similar to calc_tight_bounds(), for UV coordinates or
// other named columns.
////////////////////////////////////////////////////////////////////
INLINE void Geom::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
Thread *current_thread) const {
CDReader cdata(_cycler, current_thread);
do_calc_tight_bounds(min_point, max_point, found_any,
vertex_data, got_mat, mat,
column_name, cdata, current_thread);
}
////////////////////////////////////////////////////////////////////
// Function: Geom::mark_internal_bounds_stale
// Access: Private

View File

@ -1219,7 +1219,9 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
LPoint3f min, max;
bool found_any = false;
do_calc_tight_bounds(min, max, found_any, vertex_data,
false, LMatrix4f::ident_mat(), cdata, current_thread);
false, LMatrix4f::ident_mat(),
InternalName::get_vertex(),
cdata, current_thread);
if (found_any) {
// Then we put the bounding volume around both of those points.
@ -1268,6 +1270,7 @@ do_calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
const CData *cdata, Thread *current_thread) const {
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
@ -1275,7 +1278,7 @@ do_calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
++pi) {
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
prim->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
got_mat, mat, current_thread);
got_mat, mat, column_name, current_thread);
}
}

View File

@ -151,6 +151,12 @@ public:
Thread *current_thread) const;
INLINE void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any, Thread *current_thread) const;
INLINE void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
Thread *current_thread) const;
static UpdateSeq get_next_modified();
@ -164,6 +170,7 @@ private:
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
const CData *cdata, Thread *current_thread) const;
void clear_prepared(PreparedGraphicsObjects *prepared_objects);

View File

@ -1319,19 +1319,21 @@ get_highest_index_value(NumericType index_type) {
// Function: GeomPrimitive::calc_tight_bounds
// Access: Public, Virtual
// Description: Expands min_point and max_point to include all of the
// vertices in the Geom, if any. found_any is set true
// if any points are found. It is the caller's
// responsibility to initialize min_point, max_point,
// and found_any before calling this function.
// vertices in the Geom, if any (or the data of any
// point type, for instance, texture coordinates--based
// on the column name). found_any is set true if any
// points are found. It is the caller's responsibility
// to initialize min_point, max_point, and found_any
// before calling this function.
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
Thread *current_thread) const {
GeomVertexReader reader(vertex_data, InternalName::get_vertex(),
current_thread);
GeomVertexReader reader(vertex_data, column_name, current_thread);
if (!reader.has_column()) {
// No vertex data.
return;

View File

@ -198,6 +198,7 @@ public:
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4f &mat,
const InternalName *column_name,
Thread *current_thread) const;
protected:

View File

@ -292,7 +292,11 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
transformer.register_vertices(this);
if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
transformer.apply_texture_colors(this, attribs._other);
}
transformer.register_vertices(this, false);
}
////////////////////////////////////////////////////////////////////

View File

@ -82,6 +82,31 @@ operator < (const GeomTransformer::SourceColors &other) const {
return (_color.compare_to(other._color) < 0);
}
////////////////////////////////////////////////////////////////////
// Function: GeomTransformer::SourceTextureColors::Ordering Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool GeomTransformer::SourceTextureColors::
operator < (const GeomTransformer::SourceTextureColors &other) const {
if (_vertex_data != other._vertex_data) {
return _vertex_data < other._vertex_data;
}
if (_tex != other._tex) {
return _tex < other._tex;
}
if (_ts != other._ts) {
return _ts < other._ts;
}
if (_tma != other._tma) {
return _tma < other._tma;
}
if (_keep_vertex_color != other._keep_vertex_color) {
return (int)_keep_vertex_color < (int)other._keep_vertex_color;
}
return (_base_color.compare_to(other._base_color) < 0);
}
////////////////////////////////////////////////////////////////////
// Function: GeomTransformer::SourceFormat::Ordering Operator
// Access: Public

View File

@ -26,12 +26,15 @@
#include "vector_int.h"
#include "userVertexTransform.h"
#include "geomMunger.h"
#include "texture.h"
#include "texturePeeker.h"
#include "config_pgraph.h"
PStatCollector GeomTransformer::_apply_vertex_collector("*:Flatten:apply:vertex");
PStatCollector GeomTransformer::_apply_texcoord_collector("*:Flatten:apply:texcoord");
PStatCollector GeomTransformer::_apply_set_color_collector("*:Flatten:apply:set color");
PStatCollector GeomTransformer::_apply_scale_color_collector("*:Flatten:apply:scale color");
PStatCollector GeomTransformer::_apply_texture_color_collector("*:Flatten:apply:texture color");
PStatCollector GeomTransformer::_apply_set_format_collector("*:Flatten:apply:set format");
TypeHandle GeomTransformer::NewCollectedData::_type_handle;
@ -77,9 +80,12 @@ GeomTransformer::
// unused vertices.
////////////////////////////////////////////////////////////////////
void GeomTransformer::
register_vertices(Geom *geom) {
register_vertices(Geom *geom, bool might_have_unused) {
VertexDataAssoc &assoc = _vdata_assoc[geom->get_vertex_data()];
assoc._geoms.push_back(geom);
if (might_have_unused) {
assoc._might_have_unused = true;
}
}
////////////////////////////////////////////////////////////////////
@ -90,7 +96,7 @@ register_vertices(Geom *geom) {
// unused vertices.
////////////////////////////////////////////////////////////////////
void GeomTransformer::
register_vertices(GeomNode *node) {
register_vertices(GeomNode *node, bool might_have_unused) {
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
@ -99,7 +105,7 @@ register_vertices(GeomNode *node) {
for (gi = geoms.begin(); gi != geoms.end(); ++gi) {
GeomNode::GeomEntry &entry = (*gi);
PT(Geom) geom = entry._geom.get_write_pointer();
register_vertices(geom);
register_vertices(geom, might_have_unused);
}
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
@ -425,6 +431,272 @@ transform_colors(GeomNode *node, const LVecBase4f &scale) {
}
////////////////////////////////////////////////////////////////////
// Function: GeomTransformer::apply_texture_colors
// Access: Public
// Description: Removes textures from Geoms by applying the texture
// colors to the vertices.
//
// See apply_texure_colors(GeomNode *, RenderState *).
////////////////////////////////////////////////////////////////////
bool GeomTransformer::
apply_texture_colors(Geom *geom, TextureStage *ts, Texture *tex,
const TexMatrixAttrib *tma, const Colorf &base_color,
bool keep_vertex_color) {
PStatTimer timer(_apply_texture_color_collector);
nassertr(geom != (Geom *)NULL, false);
PT(TexturePeeker) peeker = tex->peek();
if (peeker == (TexturePeeker *)NULL) {
return false;
}
if (peeker->get_x_size() == 1 &&
peeker->get_y_size() == 1 &&
peeker->get_z_size() == 1) {
// If it's just a one-pixel texture (e.g. a simple ram image),
// don't bother scanning the UV's. Just extract the color and
// apply it.
Colorf color;
peeker->lookup(color, 0.0f, 0.0f);
color.set(color[0] * base_color[0],
color[1] * base_color[1],
color[2] * base_color[2],
color[3] * base_color[3]);
if (keep_vertex_color) {
return transform_colors(geom, color);
} else {
return set_color(geom, color);
}
}
bool got_mat = false;
LMatrix4f mat = LMatrix4f::ident_mat();
if (tma != (TexMatrixAttrib *)NULL && tma->has_stage(ts)) {
mat = tma->get_mat(ts);
got_mat = !mat.almost_equal(LMatrix4f::ident_mat());
}
// This version of the code just applied one overall flat color to
// the entire mesh. Turned out not to be good enough. Instead,
// we'll look up each vertex in the texture map and apply the
// nearest color to the vertex.
/*
// Scan the UV's to get the used range. This is particularly
// necessary for palettized textures.
LPoint3f min_point, max_point;
bool found_any = false;
geom->calc_tight_bounds(min_point, max_point, found_any,
geom->get_vertex_data(),
got_mat, mat,
ts->get_texcoord_name(),
Thread::get_current_thread());
if (found_any) {
// Now use that UV range to determine the overall color of the
// geom's texture.
Colorf color;
peeker->filter_rect(color,
min_point[0], min_point[1], min_point[2],
max_point[0], max_point[1], max_point[2]);
color.set(color[0] * base_color[0],
color[1] * base_color[1],
color[2] * base_color[2],
color[3] * base_color[3]);
if (keep_vertex_color) {
return transform_colors(geom, color);
} else {
return set_color(geom, color);
}
}
return false;
*/
SourceTextureColors stc;
stc._ts = ts;
stc._tex = tex;
stc._tma = tma;
stc._base_color = base_color;
stc._keep_vertex_color = keep_vertex_color;
stc._vertex_data = geom->get_vertex_data();
NewVertexData &new_data = _tex_colors[stc];
if (new_data._vdata.is_null()) {
// We have not yet applied these texture colors. Do so now.
PT(GeomVertexData) vdata;
// Make sure the vdata has a color column.
if (stc._vertex_data->has_column(InternalName::get_color())) {
vdata = new GeomVertexData(*stc._vertex_data);
} else {
// Create a color column where there wasn't one before.
vdata = new GeomVertexData(*stc._vertex_data->set_color
(Colorf(1.0f, 1.0f, 1.0f, 1.0f), 1, Geom::NT_packed_dabc, Geom::C_color));
keep_vertex_color = false;
}
// Check whether it has 2-d or 3-d texture coordinates.
bool tex3d = false;
const GeomVertexColumn *column = vdata->get_format()->get_column(ts->get_texcoord_name());
if (column == (GeomVertexColumn *)NULL) {
return false;
}
if (column->get_num_components() >= 3) {
tex3d = true;
}
// Now walk through the vertices and apply each color from the
// texture as we go.
if (keep_vertex_color) {
// We want to modulate the existing vertex color.
GeomVertexReader gtexcoord(vdata, ts->get_texcoord_name());
GeomVertexRewriter gcolor(vdata, InternalName::get_color());
if (got_mat || tex3d) {
while (!gtexcoord.is_at_end()) {
TexCoord3f p = gtexcoord.get_data3f();
Colorf c = gcolor.get_data4f();
p = p * mat;
Colorf color;
peeker->lookup(color, p[0], p[1], p[2]);
color.set(color[0] * base_color[0] * c[0],
color[1] * base_color[1] * c[1],
color[2] * base_color[2] * c[2],
color[3] * base_color[3] * c[3]);
gcolor.set_data4f(color);
}
} else {
while (!gtexcoord.is_at_end()) {
TexCoordf p = gtexcoord.get_data2f();
Colorf c = gcolor.get_data4f();
Colorf color;
peeker->lookup(color, p[0], p[1]);
color.set(color[0] * base_color[0] * c[0],
color[1] * base_color[1] * c[1],
color[2] * base_color[2] * c[2],
color[3] * base_color[3] * c[3]);
gcolor.set_data4f(color);
}
}
} else {
// We want to replace any existing vertex color.
GeomVertexReader gtexcoord(vdata, ts->get_texcoord_name());
GeomVertexWriter gcolor(vdata, InternalName::get_color());
if (got_mat || tex3d) {
while (!gtexcoord.is_at_end()) {
TexCoord3f p = gtexcoord.get_data3f();
p = p * mat;
Colorf color;
peeker->lookup(color, p[0], p[1], p[2]);
color.set(color[0] * base_color[0],
color[1] * base_color[1],
color[2] * base_color[2],
color[3] * base_color[3]);
gcolor.set_data4f(color);
}
} else {
while (!gtexcoord.is_at_end()) {
TexCoordf p = gtexcoord.get_data2f();
Colorf color;
peeker->lookup(color, p[0], p[1]);
color.set(color[0] * base_color[0],
color[1] * base_color[1],
color[2] * base_color[2],
color[3] * base_color[3]);
gcolor.set_data4f(color);
}
}
}
new_data._vdata = vdata;
}
geom->set_vertex_data(new_data._vdata);
VertexDataAssoc &assoc = _vdata_assoc[new_data._vdata];
if (stc._vertex_data->get_ref_count() > 1) {
_vdata_assoc[new_data._vdata]._might_have_unused = true;
_vdata_assoc[stc._vertex_data]._might_have_unused = true;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GeomTransformer::apply_texture_colors
// Access: Public
// Description: Removes textures from Geoms by applying the texture
// colors to the vertices. This is primarily useful to
// simplify a low-LOD model.
//
// Only the bottommost texture is used (if there is more
// than one), and it is applied as if it were
// M_modulate, and WM_repeat, regardless of its actual
// settings. If the texture has a simple_ram_image,
// this may be used if the main image isn't resident.
//
// After this call, there will be no texturing specified
// on the GeomNode level. Of course, there might still
// be texturing inherited from above.
////////////////////////////////////////////////////////////////////
bool GeomTransformer::
apply_texture_colors(GeomNode *node, const RenderState *state) {
bool any_changed = false;
GeomNode::CDWriter cdata(node->_cycler);
GeomNode::GeomList::iterator gi;
GeomNode::GeomList &geoms = *(cdata->modify_geoms());
for (gi = geoms.begin(); gi != geoms.end(); ++gi) {
GeomNode::GeomEntry &entry = (*gi);
CPT(RenderState) geom_state = state->compose(entry._state);
const TextureAttrib *ta = geom_state->get_texture();
if (ta != (TextureAttrib *)NULL) {
CPT(TextureAttrib) ta2 = ta->filter_to_max(1);
if (ta2->get_num_on_stages() > 0) {
TextureStage *ts = ta2->get_on_stage(0);
Texture *tex = ta2->get_on_texture(ts);
const TexMatrixAttrib *tma = geom_state->get_tex_matrix();
const ColorAttrib *ca = geom_state->get_color();
Colorf base_color(1.0f, 1.0f, 1.0f, 1.0f);
bool keep_vertex_color = true;
if (ca != (ColorAttrib *)NULL && ca->get_color_type() == ColorAttrib::T_flat) {
base_color = ca->get_color();
keep_vertex_color = false;
}
PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
if (apply_texture_colors(new_geom, ts, tex, tma, base_color, keep_vertex_color)) {
entry._geom = new_geom;
any_changed = true;
if (new_geom->get_vertex_data()->has_column(InternalName::get_color())) {
// Ensure we have a ColorAttrib::make_vertex() attrib.
CPT(RenderState) color_state = entry._state->set_attrib(ColorAttrib::make_vertex());
if (entry._state != color_state) {
entry._state = color_state;
any_changed = true;
}
}
}
// Also remove any texture references from the GeomState.
CPT(RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_type());
if (entry._state != no_tex_state) {
entry._state = no_tex_state;
any_changed = true;
}
}
}
}
return any_changed;
}
////////////////////////////////////////////////////////////////////
// Function: GeomTransformer::apply_state
// Access: Public

View File

@ -25,6 +25,7 @@ class GeomNode;
class RenderState;
class InternalName;
class GeomMunger;
class Texture;
////////////////////////////////////////////////////////////////////
// Class : GeomTransformer
@ -51,8 +52,8 @@ public:
INLINE int get_max_collect_vertices() const;
INLINE void set_max_collect_vertices(int max_collect_vertices);
void register_vertices(Geom *geom);
void register_vertices(GeomNode *node);
void register_vertices(Geom *geom, bool might_have_unused);
void register_vertices(GeomNode *node, bool might_have_unused);
bool transform_vertices(Geom *geom, const LMatrix4f &mat);
bool transform_vertices(GeomNode *node, const LMatrix4f &mat);
@ -68,6 +69,11 @@ public:
bool transform_colors(Geom *geom, const LVecBase4f &scale);
bool transform_colors(GeomNode *node, const LVecBase4f &scale);
bool apply_texture_colors(Geom *geom, TextureStage *ts, Texture *tex,
const TexMatrixAttrib *tma,
const Colorf &base_color, bool keep_vertex_color);
bool apply_texture_colors(GeomNode *node, const RenderState *state);
bool apply_state(GeomNode *node, const RenderState *state);
bool set_format(Geom *geom, const GeomVertexFormat *new_format);
@ -88,6 +94,12 @@ public:
PT(Geom) premunge_geom(const Geom *geom, GeomMunger *munger);
private:
static void get_texel_color(Colorf &color, float u, float v,
const unsigned char *image,
int x_size, int y_size);
private:
int _max_collect_vertices;
@ -156,6 +168,22 @@ private:
// modified from the original colors (e.g. via a ColorScaleAttrib).
NewColors _fcolors, _tcolors;
// The table of GeomVertexData objects whose texture colors have
// been applied.
class SourceTextureColors {
public:
INLINE bool operator < (const SourceTextureColors &other) const;
TextureStage *_ts;
Texture *_tex;
const TexMatrixAttrib *_tma;
Colorf _base_color;
bool _keep_vertex_color;
CPT(GeomVertexData) _vertex_data;
};
typedef pmap<SourceTextureColors, NewVertexData> NewTextureColors;
NewTextureColors _tex_colors;
// The table of GeomVertexData objects whose vertex formats have
// been modified. For set_format(): record (format + vertex_data) ->
// vertex_data.
@ -252,6 +280,7 @@ private:
static PStatCollector _apply_texcoord_collector;
static PStatCollector _apply_set_color_collector;
static PStatCollector _apply_scale_color_collector;
static PStatCollector _apply_texture_color_collector;
static PStatCollector _apply_set_format_collector;
public:

View File

@ -6006,6 +6006,33 @@ flatten_strong() {
return num_removed;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::apply_texture_colors
// Access: Published
// Description: Removes textures from Geoms at this node and below by
// applying the texture colors to the vertices. This is
// primarily useful to simplify a low-LOD model. The
// texture colors are replaced by flat colors that
// approximate the original textures.
//
// Only the bottommost texture on each Geom is used (if
// there is more than one), and it is applied as if it
// were M_modulate, and WM_repeat, regardless of its
// actual settings. If the texture has a
// simple_ram_image, this may be used if the main image
// isn't resident.
//
// After this call, there will be no texturing specified
// at this level and below. Of course, there might
// still be texturing inherited from above.
////////////////////////////////////////////////////////////////////
void NodePath::
apply_texture_colors() {
nassertv_always(!is_empty());
SceneGraphReducer gr;
gr.apply_attribs(node(), SceneGraphReducer::TT_apply_texture_color | SceneGraphReducer::TT_tex_matrix | SceneGraphReducer::TT_other);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::find_net_tag
// Access: Published

View File

@ -819,6 +819,7 @@ PUBLISHED:
int flatten_light();
int flatten_medium();
int flatten_strong();
void apply_texture_colors();
INLINE int clear_model_nodes();
INLINE void set_tag(const string &key, const string &value);

View File

@ -31,6 +31,7 @@ PStatCollector SceneGraphReducer::_compatible_state_collector("*:Flatten:compati
PStatCollector SceneGraphReducer::_collect_collector("*:Flatten:collect");
PStatCollector SceneGraphReducer::_make_nonindexed_collector("*:Flatten:make nonindexed");
PStatCollector SceneGraphReducer::_unify_collector("*:Flatten:unify");
PStatCollector SceneGraphReducer::_remove_unused_collector("*:Flatten:remove unused vertices");
PStatCollector SceneGraphReducer::_premunge_collector("*:Premunge");
////////////////////////////////////////////////////////////////////
@ -183,6 +184,25 @@ unify(PandaNode *root, bool preserve_order) {
r_unify(root, max_indices, preserve_order);
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::remove_unused_vertices
// Access: Published
// Description: Removes any vertices in GeomVertexDatas that are no
// longer used at this level and below. This requires
// remapping vertex indices in all of the
// GeomPrimitives, to remove holes in the
// GeomVertexDatas. It is normally not necessary to
// call this explicitly.
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
remove_unused_vertices(PandaNode *root) {
PStatTimer timer(_remove_unused_collector);
r_register_vertices(root, _transformer);
_transformer.finish_apply();
Thread::consider_yield();
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::decompose
// Access: Published
@ -909,6 +929,27 @@ r_unify(PandaNode *node, int max_indices, bool preserve_order) {
Thread::consider_yield();
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::r_register_vertices
// Access: Private
// Description: Recursively calls
// GeomTransformer::register_vertices() on all GeomNodes
// at the indicated root and below.
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
r_register_vertices(PandaNode *node, GeomTransformer &transformer) {
if (node->is_geom_node()) {
GeomNode *geom_node = DCAST(GeomNode, node);
transformer.register_vertices(geom_node, true);
}
PandaNode::Children children = node->get_children();
int num_children = children.get_num_children();
for (int i = 0; i < num_children; ++i) {
r_register_vertices(children.get_child(i), transformer);
}
}
////////////////////////////////////////////////////////////////////
// Function: SceneGraphReducer::r_decompose
// Access: Private

View File

@ -46,13 +46,14 @@ PUBLISHED:
INLINE ~SceneGraphReducer();
enum AttribTypes {
TT_transform = 0x001,
TT_color = 0x002,
TT_color_scale = 0x004,
TT_tex_matrix = 0x008,
TT_clip_plane = 0x010,
TT_cull_face = 0x020,
TT_other = 0x040,
TT_transform = 0x001,
TT_color = 0x002,
TT_color_scale = 0x004,
TT_tex_matrix = 0x008,
TT_clip_plane = 0x010,
TT_cull_face = 0x020,
TT_apply_texture_color = 0x040,
TT_other = 0x080,
};
enum CombineSiblings {
@ -126,7 +127,7 @@ 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 | TT_cull_face));
INLINE void apply_attribs(PandaNode *node, int attrib_types = ~(TT_clip_plane | TT_cull_face | TT_apply_texture_color));
INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
int attrib_types, GeomTransformer &transformer);
@ -142,6 +143,7 @@ PUBLISHED:
INLINE int collect_vertex_data(PandaNode *root, int collect_bits = ~0);
INLINE int make_nonindexed(PandaNode *root, int nonindexed_bits = ~0);
void unify(PandaNode *root, bool preserve_order);
void remove_unused_vertices(PandaNode *root);
INLINE void premunge(PandaNode *root, const RenderState *initial_state);
@ -179,6 +181,7 @@ protected:
GeomTransformer &transformer, bool format_only);
int r_make_nonindexed(PandaNode *node, int collect_bits);
void r_unify(PandaNode *node, int max_indices, bool preserve_order);
void r_register_vertices(PandaNode *node, GeomTransformer &transformer);
void r_decompose(PandaNode *node);
void r_premunge(PandaNode *node, const RenderState *state);
@ -195,6 +198,7 @@ private:
static PStatCollector _collect_collector;
static PStatCollector _make_nonindexed_collector;
static PStatCollector _unify_collector;
static PStatCollector _remove_unused_collector;
static PStatCollector _premunge_collector;
};