mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
apply_texture_colors()
This commit is contained in:
parent
5050c994e0
commit
11ae34e109
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user